Streaming & SSE
Streaming uses Server-Sent Events; the SDK gives you a simple stream you can loop over.
Under the hood, Claude streams using Server-Sent Events (SSE) — a long-lived HTTP response that delivers a sequence of small events. Each event carries a chunk of the reply.
You rarely parse SSE by hand
The SDK wraps SSE in a friendly stream object. In JavaScript you call client.messages.stream(...) and iterate over text deltas as they arrive.
Getting the full message too
After the loop, the SDK can hand you the complete assembled message with finalMessage(), so you get both live tokens and the final result.
Example
const stream = client.messages.stream({
model: "claude-opus-4-8",
max_tokens: 2048,
messages: [{ role: "user", content: "Write a haiku about servers." }],
});
// 'text' fires with each new chunk of text
stream.on("text", (delta) => process.stdout.write(delta));
// After streaming, get the complete message object
const final = await stream.finalMessage();
console.log("\nTokens:", final.usage.output_tokens);When to use it
- Build a Node.js Express endpoint that opens a streaming Claude request and forwards SSE events to the client.
- Use the SDK's stream helper to accumulate the full text after streaming completes, for logging or storage.
- Handle stream error events gracefully so the UI shows a user-friendly message if Claude's response is interrupted.
More examples
Stream and log each SSE event type
Iterates raw SSE events and shows how to filter for the content_block_delta events that carry text.
const stream = await client.messages.stream({
model: "claude-haiku-4-5",
max_tokens: 128,
messages: [{ role: "user", content: "Count to five." }],
});
for await (const event of stream) {
// event.type: 'message_start' | 'content_block_delta' | 'message_delta' | 'message_stop'
if (event.type === "content_block_delta") {
process.stdout.write(event.delta.text);
}
}Get full text after stream ends
Uses the event-emitter API to stream live text while also awaiting the final message for usage data.
const stream = client.messages.stream({
model: "claude-haiku-4-5",
max_tokens: 256,
messages: [{ role: "user", content: "Explain REST APIs." }],
});
// Stream to stdout live
stream.on("text", (text) => process.stdout.write(text));
// Await the final message object for usage stats
const final = await stream.finalMessage();
console.log("\nTokens:", final.usage);Handle stream errors gracefully
Wraps the stream loop in try/catch so network interruptions or API errors are caught and handled cleanly.
try {
const stream = await client.messages.stream({
model: "claude-haiku-4-5",
max_tokens: 128,
messages: [{ role: "user", content: "Hello" }],
});
for await (const chunk of stream) {
if (chunk.type === "content_block_delta") {
process.stdout.write(chunk.delta.text);
}
}
} catch (err) {
console.error("Stream failed:", err.message);
// Show fallback UI to the user
}
Discussion