Skip to main content
SSE

Server-Sent Events

Active

Server-Sent Events (SSE) is a server-push technology over plain HTTP that lets a server stream data to a browser or client via a persistent connection. The client subscribes using the EventSource API; the server responds with Content-Type: text/event-stream and writes newline-delimited events indefinitely. SSE is unidirectional – server to client only. It became dominant in 2023–2026 as the streaming transport for every major LLM API (OpenAI, Anthropic, Google Gemini).

SSEEventSourceStreamingHTTPtext/event-streamLLM2006
Event Types

In one line

Server-Sent Events (SSE) is defined in the WHATWG HTML Living Standard §9.2. A client opens a persistent HTTP connection using the EventSource API; the server responds with Content-Type: text/event-stream and streams newline-delimited events indefinitely. Events carry optional id, event, data, and retry fields. The browser auto-reconnects using Last-Event-ID. SSE is unidirectional (server to client). It is the standard streaming transport for LLM APIs – OpenAI, Anthropic Claude, and Google Gemini all use text/event-stream for token streaming.

Quick Reference

FieldSizeDescription
Content-Typetext/event-streamServer MUST respond with Content-Type: text/event-stream. Charset defaults to UTF-8. No other encoding is permitted per spec §9.2.3.
Event fields4 fieldsdata: (payload), event: (type name), id: (last event ID), retry: (reconnect delay ms). Fields are colon-separated. Blank line terminates an event.
Auto-reconnectLast-Event-ID headerOn disconnect, browser automatically reconnects and sends Last-Event-ID header with the id of the last received event. Server uses this to resume from the right position.
Retry fieldmillisecondsretry: 3000 tells the client to wait 3 seconds before reconnecting. Server can update the retry interval dynamically by sending new retry: fields.
Stop reconnectHTTP 204Server responds 204 No Content to tell the client to permanently stop reconnecting. Any other non-2xx response also stops reconnection.
Event typesUnlimitedDefault event type is 'message'. Custom types set with event: field. Client listens with addEventListener('typename', handler).
HTTP/2 advantageNo connection limitHTTP/1.1 browsers limit 6 connections per origin. HTTP/2 multiplexes all SSE streams on one connection – unlimited SSE subscriptions per origin.
CORSwithCredentialsCross-origin SSE requires CORS. Set withCredentials: true in EventSourceInit to send cookies. Server must return Access-Control-Allow-Origin and Access-Control-Allow-Credentials: true.

Key Characteristics

Unidirectional push

Server streams events to client. Client cannot send data back over the SSE connection. Use fetch/XHR for client-to-server communication alongside SSE.

Auto-reconnect

The browser EventSource API automatically reconnects on disconnect, exponential backoff by default, respecting the retry: field from the server. No client code needed.

LLM streaming

Every major LLM API streams tokens via SSE: OpenAI Chat Completions, Anthropic Claude, Google Gemini, Mistral. The pattern: data: {"delta": "token"} then data: [DONE].

Plain HTTP

SSE works over any HTTP connection including HTTP/1.1, HTTP/2, and HTTP/3. No protocol upgrade. No WebSocket handshake. Proxies and CDNs handle it without special configuration.

Message Format

Request
http
# SSE request – client opens EventSource
GET /events HTTP/1.1
Host: api.example.com
Accept: text/event-stream
Cache-Control: no-cache
Authorization: Bearer <token>
# On reconnect, browser sends:
Last-Event-ID: 42

# JavaScript client
const source = new EventSource('/events', { withCredentials: true });
source.onmessage  = (e) => console.log(e.data);
source.addEventListener('update', (e) => handleUpdate(JSON.parse(e.data)));
source.onerror    = (e) => console.error('SSE error', e);
Response
http
# SSE response – text/event-stream format
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
X-Accel-Buffering: no

# Simple message event
data: Hello, world!

# Named event with JSON payload
event: update
data: {"userId": "usr_1", "action": "login"}

# Event with ID (enables Last-Event-ID resumption)
id: 42
event: price
data: {"symbol": "BTC", "price": 67432.10}

# Set reconnect delay to 5 seconds
retry: 5000

# Keep-alive comment (prevents proxy timeouts)
: ping

# LLM token streaming pattern
data: {"choices":[{"delta":{"content":"Hello"}}]}
data: {"choices":[{"delta":{"content":" world"}}]}
data: [DONE]

Implementations

linuxsince Native EventSource in all browsers. Node.js: eventsource npm, native via Response streaming. Python: flask-sse, sse-starlette, FastAPI StreamingResponse.built-in
macossince Safari 5+ native EventSource. Same server libraries as Linux.built-in
windowssince Edge 79+ native EventSource. .NET: ServerSentEvents NuGet, Yarp streaming.built-in
iossince Safari iOS 5+ EventSource. WKWebView supports SSE natively.built-in
androidsince Chrome Android native EventSource. OkHttp with EventSource client library.built-in