message
§9.2.6event: message (default)
The default SSE event type. Fired when the server sends a data: field without an explicit event: field, or when event: message is set explicitly. Handled by the EventSource onmessage handler or addEventListener('message', handler). The most commonly used event type for LLM token streaming.
Details
Every SSE event has an event type. When no event: field is present in the event, the type defaults to 'message'. This fires the onmessage event handler on the EventSource object.
An SSE event is terminated by a blank line (two consecutive newlines). Multiple data: lines are concatenated with a newline character between them.
For LLM streaming: each token or chunk is a separate message event. The OpenAI API sends data: {"choices":[{"delta":{"content":"token"}}]} for each chunk, then data: [DONE] as a sentinel to signal completion.
The event.data property on the MessageEvent contains the concatenated data lines as a string. Parse JSON with JSON.parse(event.data).
For a stream that sends binary data: SSE is UTF-8 only. Binary content must be base64-encoded in the data: field. For binary streaming, use WebSocket or WebTransport instead.
Examples
# Server sends: data: Hello, world! # Client receives MessageEvent: # event.type = "message" # event.data = "Hello, world!"
# Server sends:
data: {"userId": "usr_1", "score": 42}
# Client:
source.onmessage = (e) => {
const payload = JSON.parse(e.data);
console.log(payload.userId); // "usr_1"
};# Server sends: data: line one data: line two data: line three # Client receives: # event.data = "line one\nline two\nline three"
data: {"choices":[{"delta":{"content":"Hello"}}]}
data: {"choices":[{"delta":{"content":" world"}}]}
data: [DONE]
# Client:
source.onmessage = (e) => {
if (e.data === '[DONE]') { source.close(); return; }
const chunk = JSON.parse(e.data);
output += chunk.choices[0].delta.content ?? '';
};Gotchas
data: lines with a leading space have the space stripped – data: hello becomes 'hello' not ' hello'
An event with no data: lines is discarded even if it has an id: or event: field
The [DONE] sentinel used by LLM APIs is not part of the SSE spec – it is an application-level convention
JSON.parse will throw if the server sends malformed JSON – always wrap in try/catch
SSE is UTF-8 only – binary data requires base64 encoding in the data: field