sse_parser

A minimal, dependency-free, spec-compliant Server-Sent Events (SSE) parser for Dart and Flutter.

It does one thing well: turn a byte/text stream into a clean stream of typed events, correctly, across arbitrary chunk boundaries. Built for LLM token streaming (OpenAI Responses, chat completions, Anthropic, etc.) and any text/event-stream source.

  • Pure Dart. No Flutter dependency — works in apps and on the server.
  • Zero runtime dependencies.
  • Two layers: a push core (SseParser.feed) and a Stream API (parseSse()).
  • Correct. Models the WHATWG HTML event-stream algorithm and the TypeScript eventsource-parser: BOM strip, \n / \r / \r\n (including a CRLF split across two chunks), comment lines, one-space field-value trimming, colon-less fields, multi-line data, persistent last-event-id (with NUL guard), and ASCII-digit retry.

Stream API

import 'package:http/http.dart' as http;
import 'package:sse_parser/sse_parser.dart';

final request = http.Request('POST', uri)..body = body;
final response = await http.Client().send(request);

await for (final SseEvent event in response.stream.parseSse()) {
  if (event.data == '[DONE]') break;
  final json = jsonDecode(event.data);
  // event.event -> the `event:` type (or null for the default)
  // event.id    -> the last `id:` seen so far
}

A Stream<String> works too (stream.parseSse()); the byte variant decodes UTF-8 for you, tolerating multi-byte sequences split across chunks.

Push API

When you are not driving a Stream — e.g. feeding raw chunks from a custom socket — use the core directly:

final parser = SseParser(
  onEvent: (event) => print(event.data),
  onComment: (text) {},      // optional: `:` keep-alive lines
  onRetry: (duration) {},    // optional: `retry:` reconnect hint
);

parser.feed('data: hel');
parser.feed('lo\n\n');       // -> onEvent(SseEvent(data: 'hello'))
parser.close();              // discards any unterminated trailing block

Pass close(dispatchPending: true) (or parseSse(dispatchPendingOnDone: true)) to leniently emit a final event that arrived without its terminating blank line.

Why not an existing package?

Most Dart SSE packages are EventSource clients (GET + auto-reconnect) or carry a transport. This is just the parser — the part you actually want to share across apps and pair with your own POST/streaming transport.

License

MIT

Libraries

sse_parser
A minimal, dependency-free, spec-compliant Server-Sent Events (SSE) parser.