SSE Stream Parser
Parse, inspect, and reconstruct Server-Sent Events streams — auto-detects OpenAI and Anthropic formats, runs entirely in your browser
You’re debugging a streaming AI API call and your terminal is flooding with data: {...} lines that are impossible to read at a glance. Or you’ve captured a raw SSE stream from a network tab and need to reconstruct the full text the model produced. This tool parses raw SSE data in your browser, pretty-prints each event as JSON, and reconstructs the complete streamed content — without sending anything to a server.
What Is Server-Sent Events (SSE)?
Server-Sent Events is a browser-native protocol defined in the HTML specification that enables a server to push data to a client over a persistent HTTP connection. Unlike WebSockets, SSE is unidirectional (server → client only) and uses plain HTTP, making it firewall-friendly and easy to proxy.
The wire format is text-based and simple:
data: {"key": "value"}
data: second event
event: named-event
data: {"key": "value"}
id: 42
data: checkpoint event
retry: 5000
Each field starts at the beginning of a line, followed by a colon and the field value. Events are separated by blank lines. The four standard fields are data, event, id, and retry. Lines starting with : are comments, typically used as keepalive pings.
SSE in AI API Streaming Responses
Every major AI API uses SSE for streaming completions. When you pass stream: true to the OpenAI API or "stream": true to the Anthropic API, the HTTP response body is an SSE stream where each event contains a JSON chunk of the partial completion.
OpenAI / OpenAI-compatible APIs (GPT-4o, Gemini, Mistral, etc.) follow this pattern:
data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"delta":{"content":"Hello"}}]}
data: {"id":"chatcmpl-xxx","object":"chat.completion.chunk","choices":[{"delta":{"content":" world"}}]}
data: [DONE]
Content is extracted from choices[0].delta.content. The stream ends with the literal data: [DONE] sentinel.
Anthropic Claude API uses a richer event taxonomy with named events:
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Hello"}}
event: message_stop
data: {"type":"message_stop"}
Content is extracted from delta.text in content_block_delta events. The stream includes lifecycle events for the message and content blocks.
This parser auto-detects which format it is looking at based on the JSON structure of the first recognizable data event.
Debugging Streaming Responses
Streaming responses are harder to debug than standard JSON because the useful content is split across dozens or hundreds of events, interleaved with metadata. Common debugging scenarios this tool helps with:
Reconstructing the full response: Capture the raw stream from your browser’s network tab (copy as HAR or copy response body), paste it here, and immediately see the full text the model produced without manually concatenating dozens of chunks.
Finding where a stream stopped: If a response was truncated, the event log shows exactly which event was last received and what finish_reason or stop_reason was set — or if neither was set, confirming the stream was cut prematurely.
Inspecting token-by-token output: Each event card shows the content delta for that chunk. Useful for understanding how the model produces structured output (JSON, code, etc.) incrementally.
Validating streaming integrations: If you’re building a streaming UI and something looks wrong, paste the raw SSE into this parser to verify the upstream data is correct before debugging your rendering logic.
SSE vs. WebSockets
SSE and WebSockets are both used for real-time data, but they serve different use cases:
| SSE | WebSockets | |
|---|---|---|
| Direction | Server → Client only | Bidirectional |
| Protocol | HTTP/HTTPS | ws:// / wss:// |
| Reconnect | Automatic (built-in) | Manual |
| Proxy support | Excellent | Sometimes problematic |
| Browser API | EventSource | WebSocket |
| Use case | Streaming responses, live feeds | Chat, games, collaborative editing |
For AI streaming completions — where the server produces a long response and the client only sends a single request — SSE is the natural fit. The client does not need to send incremental messages back, and the HTTP transport is simpler to proxy, cache-control, and authenticate.
Reading SSE in JavaScript
const source = new EventSource('/api/stream');
source.onmessage = (event) => {
if (event.data === '[DONE]') {
source.close();
return;
}
const chunk = JSON.parse(event.data);
const content = chunk.choices?.[0]?.delta?.content ?? '';
process(content);
};
source.onerror = () => {
source.close();
};
For POST requests (required by most AI APIs), EventSource cannot be used directly since it only supports GET. Use the fetch API with a ReadableStream reader instead:
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages, stream: true }),
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
// Parse SSE lines from text
for (const line of text.split('\n')) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') break;
const chunk = JSON.parse(data);
// handle chunk
}
}
}
Frequently Asked Questions
Why does the parser show fewer events than I expected? SSE events are separated by blank lines. If your captured stream has events separated only by single newlines (no blank line between them), they’ll be parsed as one combined event. Make sure blank lines are preserved when copying the stream from your network tab or log file.
Can I parse SSE streams from APIs other than OpenAI and Anthropic? Yes. The parser reads any valid SSE stream and pretty-prints each JSON data event. If the format is not recognized as OpenAI or Anthropic, it is marked as “Generic SSE” — all events are still shown and any valid JSON is pretty-printed. The reconstructed text section will be empty for unrecognized formats since content extraction is format-specific.
Why does my Anthropic stream show many events with no content?
Anthropic’s event schema includes lifecycle events (message_start, content_block_start, content_block_stop, message_delta, message_stop, ping) that carry metadata rather than content. Only content_block_delta events with type: "text_delta" contain actual text. The parser highlights which events produced content tokens.
Is this tool private? All parsing happens entirely in your browser. No SSE data, API responses, or any other content is transmitted to any server. You can use this tool to debug sensitive API responses safely.