Skip to main content

Custom Event Types

§9.2.5 / §9.2.6

event: typename

SSE supports named custom event types via the event: field. Any valid string can be used as an event type (except 'message', 'open', 'error' which are reserved). The browser fires a MessageEvent with event.type set to the custom name. Clients subscribe with addEventListener('typename', handler). Custom types are essential for multiplexing multiple data streams on a single SSE connection.

Details

The event: field in an SSE stream sets the event type for the next dispatched event. When the blank-line terminator is reached, a MessageEvent is created with the type property set to the event: value.

Default behavior: if no event: field is present, type is 'message'. If event: is empty string (''), type is also 'message'.

Use cases for custom event types: 1. Multiplexing – send 'price', 'news', 'alert' events on the same connection 2. Protocol versioning – 'v2.update' vs 'v1.update' 3. LLM streaming – 'content_block_delta', 'message_stop' (Anthropic Claude uses this) 4. Progress events – 'progress', 'complete', 'error'

The three built-in event names (message, open, error) cannot be used as custom types without conflicting with the browser's built-in handlers. Use onmessage for 'message' events, not addEventListener.

Multiple event types on one connection: the browser processes each event independently based on its type. You can have multiple addEventListener calls on a single EventSource for different types.

Examples

Sending custom event types
# Server sends named events:
event: price
data: {"symbol": "BTC", "price": 67432.10}

event: news
data: {"headline": "Bitcoin ETF approved"}

event: alert
data: {"severity": "high", "message": "Threshold exceeded"}

# Each blank line dispatches one event
Client listening for custom types
const source = new EventSource('/market-stream');

source.addEventListener('price', (e) => {
  const tick = JSON.parse(e.data);
  updateChart(tick.symbol, tick.price);
});

source.addEventListener('news', (e) => {
  showBanner(JSON.parse(e.data).headline);
});

source.addEventListener('alert', (e) => {
  triggerAlert(JSON.parse(e.data));
});
Anthropic Claude streaming event types
# Anthropic API uses named SSE events:
event: message_start
data: {"type":"message_start","message":{...}}

event: content_block_delta
data: {"type":"content_block_delta","delta":{"text":"Hello"}}

event: message_stop
data: {"type":"message_stop"}

Gotchas

!

Custom events are not caught by onmessage – use addEventListener('typename', handler) or onmessage only catches 'message' type

!

Event type 'message', 'error', 'open' should not be used as custom event: field values to avoid confusion with native EventSource events

!

The event: field must come before the data: field in the event block for correct parsing in all browsers

!

Event type names are case-sensitive – 'Price' and 'price' are different event types

See Also