Streaming Event Types Reference
A dense lookup for every event type the Messages API emits while streaming, its fields, and when it fires in the event lifecycle.
How to Use This List
- Skim the Event Lifecycle table top to bottom - it's the order events actually arrive in for a typical response.
- Use the Delta Types table when you're inside a
content_block_deltahandler and need to know whatevent.delta.typecan be. - The Field Reference tables list every field you'll actually read off each event object in the Python SDK.
- Cross-reference with How Server-Sent Events Power Claude's Streaming Responses for the conceptual model behind this table.
Event Lifecycle
| Order | Event type | Fires | Purpose |
|---|---|---|---|
| 1 | message_start | Once, first | Opens the message; carries id, model, role, and initial (near-zero) usage. |
| 2 | content_block_start | Once per content block | Opens a block; carries the block's type (text, tool_use, or thinking) and index. |
| 3 | content_block_delta | Many times per block | Carries an incremental piece of that block's content - see Delta Types below. |
| 4 | content_block_stop | Once per content block | Closes a block; the block's content is now complete for that index. |
| - | (steps 2-4 repeat) | Per additional block | A response can contain multiple blocks (e.g. thinking then text then tool_use) in sequence. |
| 5 | message_delta | Once, near the end | Carries stop_reason, stop_sequence, and finalized usage (output tokens). |
| 6 | message_stop | Once, last | Signals the stream is complete; no further events follow. |
| - | ping | Any time (rare) | A keep-alive event with no payload; safe to ignore. |
| - | error | Any time | Signals a mid-stream error (e.g. an overloaded model); ends the stream. |
Delta Types (inside content_block_delta)
delta.type | Belongs to block type | Key field | Meaning |
|---|---|---|---|
text_delta | text | delta.text | The next fragment of generated prose. |
input_json_delta | tool_use | delta.partial_json | The next fragment of a tool call's JSON arguments string. |
thinking_delta | thinking | delta.thinking | The next fragment of extended-thinking reasoning text. |
signature_delta | thinking | delta.signature | A cryptographic signature fragment for the thinking block, sent near its close. |
Field Reference: message_start
| Field | Type | Description |
|---|---|---|
message.id | str | Unique identifier for this message. |
message.model | str | The model that generated the response (e.g. claude-sonnet-5). |
message.role | str | Always "assistant" for API responses. |
message.usage.input_tokens | int | Input token count, known immediately. |
message.usage.output_tokens | int | Near-zero at this point; finalized later in message_delta. |
Field Reference: content_block_start / content_block_stop
| Field | Type | Description |
|---|---|---|
index | int | Which content block this event belongs to; the key for tracking per-block state. |
content_block.type | str | "text", "tool_use", or "thinking". |
content_block.name | str | Tool name - present only when type is "tool_use". |
content_block.id | str | The tool_use_id - present only when type is "tool_use". |
Field Reference: message_delta / message_stop
| Field | Type | Description |
|---|---|---|
delta.stop_reason | str | Why generation stopped: "end_turn", "max_tokens", "tool_use", "stop_sequence". |
delta.stop_sequence | str | None | The custom stop sequence matched, if stop_reason is "stop_sequence". |
usage.output_tokens | int | Finalized output token count for the whole message. |
| (none) | - | message_stop carries no payload beyond type - it's a pure signal. |
Python SDK Access Patterns
| You want | Use |
|---|---|
| Only the text, as it arrives | for text in stream.text_stream: |
| Every raw event, all types | for event in stream: |
The complete Message after streaming | stream.get_final_message() after iteration finishes |
| Async equivalents | async for text in stream.text_stream: / async for event in stream: on AsyncAnthropic |
FAQs
What's the very first event in every stream?
message_start, always. It arrives before any content block exists.
What's the very last event in every stream?
message_stop, always - it's a pure signal event with no payload of its own.
Where do I find token usage counts?
Input tokens are in message_start.message.usage.input_tokens. Output tokens finalize in message_delta.usage.output_tokens.
How do I tell a text block apart from a tool_use block?
Check content_block.type on the content_block_start event for that block's index - it's "text", "tool_use", or "thinking".
What field do I read for streamed tool call arguments?
event.delta.partial_json on content_block_delta events where event.delta.type == "input_json_delta" - accumulate these before parsing as JSON.
Is `ping` something I need to handle?
No, it's a keep-alive with no payload. Safe to ignore in a type-based dispatch (it just won't match any of your handled cases).
What does `stop_reason` tell me?
Why the model stopped generating: "end_turn" (natural completion), "max_tokens" (hit the token cap), "tool_use" (paused to call a tool), or "stop_sequence" (matched a custom stop string).
Can a response contain more than one content block?
Yes - for example a thinking block followed by a text block, or a text block followed by one or more tool_use blocks, each opened and closed independently by index.
What's `signature_delta` for?
It streams a cryptographic signature associated with an extended-thinking block, used to verify the thinking content wasn't tampered with when passed back in a later turn.
Does an `error` event mean my whole request failed?
It means the stream ended abnormally mid-generation. Treat it the same as a dropped connection: whatever content arrived before it is incomplete, and the request should typically be retried.
How is `content_block_delta` different from `message_delta`?
content_block_delta carries incremental content inside one block (text, JSON, or thinking fragments). message_delta carries message-level metadata (stop_reason, final usage) that's only known once generation is wrapping up.
Where do I find the model name that generated a response?
message_start.message.model - it echoes back the model you requested (useful if your code allows a model alias to resolve to a specific dated snapshot).
Related
- How Server-Sent Events Power Claude's Streaming Responses - the conceptual model behind this table.
- Streaming Responses Basics - runnable examples using these event types.
- Handling Partial JSON During Streamed Tool Calls - using
input_json_deltain practice. - Streaming Extended Thinking Blocks to the Frontend - using
thinking_deltaandsignature_delta. - Messages API Roles and Content Block Types Reference - the non-streaming content block model this maps onto.
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5 - and the official
anthropicPython SDK (latest 0.x release). Model names, SDK versions, and pricing move quickly - verify current specifics at platform.claude.com/docs before relying on them.