AI & LLM APIs cookbook · Intermediate
Stream model answers to the browser with SSE
Show the answer as it is generated instead of making users wait several seconds for the full reply.
Approach
Use the SDK's messages.stream() helper on the server and forward each text delta as a server-sent event.
The browser reads the stream with EventSource or fetch. Keep the API key on the server, send a final event
with usage and stop reason, and handle errors mid-stream.
Solution
import json
import anthropic
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
app = FastAPI()
client = anthropic.AsyncAnthropic() # reads ANTHROPIC_API_KEY
class Ask(BaseModel):
question: str
def sse(event: str, data: dict) -> str:
return f"event: {event}\ndata: {json.dumps(data)}\n\n"
@app.post("/ask")
async def ask(body: Ask):
async def events():
try:
async with client.messages.stream(
model="claude-sonnet-5-5",
max_tokens=1024,
system="You are a concise support assistant.",
messages=[{"role": "user", "content": body.question}],
) as stream:
async for text in stream.text_stream:
yield sse("delta", {"text": text})
final = await stream.get_final_message()
yield sse("done", {"stop_reason": final.stop_reason,
"output_tokens": final.usage.output_tokens})
except anthropic.APIError as exc:
yield sse("error", {"message": "The answer was interrupted. Please try again."})
raise exc
return StreamingResponse(events(), media_type="text/event-stream",
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"})
Pitfalls
- Buffering proxies (nginx, some CDNs) hold the stream until it ends; disable buffering for this route.
- Validating structured output per chunk: parse only after the stream is complete.
- Calling the API from the browser with your key; always proxy through your server.
Variations
- Use
fetchwith aReadableStreamreader in the browser when you need POST bodies (EventSource is GET-only). - For WebSocket apps, send the same delta and done messages over the socket.
Further reading: Streaming messages
Reference: https://docs.anthropic.com/en/docs/build-with-claude/streaming
More AI & LLM APIs recipes
- Answer with citations that point at the source text
- Build hybrid RAG search on PostgreSQL with pgvector
- Cache a long system prompt and documents
- Cache answers to frequent questions safely
- Classify thousands of items with the Batch API
- Compare two prompt versions with an unbiased model judge
- Expose an internal API as an MCP server
- Extract structured data with a schema