API Features & Capabilities

Streaming Event Types: Every SSE Block Explained

Set stream: true and Claude's response arrives as a sequence of typed events instead of one JSON blob. Knowing the sequence is the difference between a smooth UI and a mystery bug.

Claude 3P 101 · Updated July 2026 · Unofficial guide

Streaming matters for anything interactive: users see the first words in well under the time a full response takes, and long generations cannot hit client timeouts. Enable it with "stream": true and the Messages API responds with server-sent events (SSE) — a plain-text protocol where each event has a type and a JSON payload. Streaming is core API behavior, generally available on all four third-party platforms. Here is what actually comes down the wire.

The event sequence

Every streamed response follows the same skeleton:

EventWhat it carries
message_startA Message object with an empty content array — the frame you will fill in
content_block_startOpens one content block (text, tool_use, thinking) with its index
content_block_deltaOne or more incremental updates to that block
content_block_stopCloses the block at that index
message_deltaTop-level changes to the Message — stop reason, cumulative usage
message_stopEnd of stream

The start/delta/stop trio repeats per content block, and each block carries an index matching its final position in the content array — so assembly is just "append deltas to the block at this index." Two more event types can appear anywhere: ping events (keep-alives you can ignore) and error events, such as an overloaded_error mid-stream. That last one is important: because the HTTP status was already 200 when streaming began, failures arrive as events, not status codes. Your handler needs an error branch even after a successful connection.

The delta types

Inside content_block_delta, the payload's type tells you what kind of block is growing. text_delta carries visible text. thinking_delta carries reasoning text when thinking display is on. signature_delta arrives just before a thinking block closes and carries the cryptographic signature you must pass back unchanged in later turns. And input_json_delta streams a tool call's arguments as partial_json string fragments — accumulate them and parse only after content_block_stop, because the fragments are not valid JSON on their own. Current models emit roughly one complete key/value pair at a time, so gaps between these events are normal, and fine-grained streaming of parameter values can be enabled per tool with eager_input_streaming.

Note on thinking: with thinking.display: "omitted" (the default on the newest models), no thinking_delta events are sent at all — the thinking block opens, receives a single signature_delta, and closes. Don't treat the silence as a stall.

Assembling a response in practice

from anthropic import AnthropicVertex

client = AnthropicVertex(project_id="my-project", region="global")
stream = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    stream=True,
    messages=[{"role": "user", "content": "Draft a weekly status update."}],
)
for event in stream:
    if event.type == "content_block_delta" and event.delta.type == "text_delta":
        print(event.delta.text, end="", flush=True)
    elif event.type == "message_delta":
        usage = event.usage  # cumulative token counts

Token counts in message_delta usage are cumulative, not incremental — read the last one you received as the total, and treat it as the billing ground truth for the response. The official SDKs also offer higher-level stream helpers that do the assembly for you; the raw loop above is what those helpers are doing underneath.

Odds and ends worth knowing

If your request uses server-side fallback between models, a fallback content block appears at each model boundary as a start/stop pair with no deltas in between. If you use server-side compaction, the summary arrives as a normal content block: one content_block_start, a single delta containing the whole summary, then stop. And for requests likely to run past ten minutes, streaming is not just nice to have — official guidance is to stream (or use batches) rather than hold a non-streaming connection open that long.

Where to go next

See streaming with tools for the tool-use loop under SSE, the Messages API anatomy for the non-streaming object you are reassembling, and the feature matrix for platform coverage.

Sources