WebTransport
ActiveWebTransport is a W3C/IETF protocol framework that provides browser-accessible low-latency, bidirectional transport over QUIC (HTTP/3). It supports reliable ordered streams, reliable unordered datagrams, and out-of-order delivery – capabilities impossible with WebSocket. WebTransport reached Baseline in March 2026 with support across Chrome, Edge, Firefox, and Safari 26.4. It is the primary transport for real-time gaming, AI agent communication, and Media over QUIC.
In one line
WebTransport (W3C WD + IETF draft-webtrans-http3-16) is a QUIC-based browser transport that reached Baseline in March 2026. It multiplexes reliable streams and unreliable datagrams over a single QUIC connection. Unlike WebSocket (one ordered TCP stream), WebTransport gives independent streams (no head-of-line blocking), low-latency datagrams, and native HTTP/3 integration. Primary use: real-time games, AI streaming, Media over QUIC (MoQ), collaborative tools.
Quick Reference
| Field | Size | Description |
|---|---|---|
| Transport | QUIC / HTTP/3 | WebTransport over HTTP/3 is the primary variant. All WebTransport sessions are multiplexed over a single HTTP/3 connection (QUIC connection to the origin). |
| Streams | Bidirectional + Uni | sendStream() creates a unidirectional send stream (server cannot write back). createBidirectionalStream() creates a bidirectional stream. Both are independent – no head-of-line blocking between streams. |
| Datagrams | Unreliable | datagrams.writable / datagrams.readable provide access to unreliable, unordered UDP-like datagrams. Max size limited by QUIC path MTU (~1200 bytes). Best for game state, real-time sensor data. |
| Session URL | https:// only | WebTransport connects to wss:// equivalent over HTTPS. URL scheme is https:// – same origin as the page. new WebTransport('https://example.com/webtransport'). |
| Stream API | WHATWG Streams | All streams use the WHATWG Streams API (ReadableStream / WritableStream). Compatible with TextEncoderStream, TransformStream, and pipeTo(). |
| Server Push | incomingStreams | Server can push streams to client via transport.incomingBidirectionalStreams and transport.incomingUnidirectionalStreams (ReadableStream of streams). |
| Close codes | Uint32 + reason | transport.close({ closeCode: number, reason: string }) closes the session. The server receives the close code and reason. Similar to WebSocket close frames. |
| HTTP/2 fallback | draft-webtrans-http2 | WebTransport over HTTP/2 (draft) provides WebTransport semantics without QUIC – for environments that block UDP. No datagrams in HTTP/2 variant. |
Key Characteristics
No head-of-line blocking
Each WebTransport stream is independent at the QUIC layer. A lost packet on stream A does not delay stream B. WebSocket has a single TCP stream where packet loss blocks all data.
Datagrams + streams
Unique combination: reliable ordered streams (like TCP) and unreliable datagrams (like UDP) over one connection. Games use datagrams for position, streams for chat.
Same-origin QUIC
WebTransport connects to the same origin as the page. TLS is provided by the QUIC connection – no additional TLS handshake. Certificate fingerprint verification supported for self-signed certs in development.
QUIC required
Primary variant requires QUIC/HTTP/3. Firewalls that block UDP port 443 prevent WebTransport. The HTTP/2 fallback draft addresses this but loses datagrams.
Message Format
// WebTransport connection
const transport = new WebTransport('https://game.example.com/webtransport');
await transport.ready;
// Send datagrams (unreliable, unordered)
const writer = transport.datagrams.writable.getWriter();
await writer.write(new Uint8Array([/* game state */]));
// Send on a reliable stream
const stream = await transport.createUnidirectionalStream();
const w = stream.getWriter();
await w.write(encoder.encode('{"type":"chat","msg":"Hello"}'));
await w.close();
// Bidirectional stream (request-response)
const { readable, writable } = await transport.createBidirectionalStream();
const rw = writable.getWriter();
await rw.write(encoder.encode('{"op":"subscribe","channel":"prices"}'));
const rr = readable.getReader();
const { value } = await rr.read(); // server response// Server pushes streams to client
const streams = transport.incomingUnidirectionalStreams.getReader();
while (true) {
const { value: stream, done } = await streams.read();
if (done) break;
const reader = stream.getReader();
const chunks = [];
while (true) {
const { value, done } = await reader.read();
if (done) break;
chunks.push(value);
}
console.log('server push:', new TextDecoder().decode(
Buffer.concat(chunks)
));
}
// WebTransport vs WebSocket comparison
// WebSocket: one ordered TCP stream, head-of-line blocking
// WebTransport: many QUIC streams, independent, plus UDP datagrams
// Both: TLS, same-origin, browser API