2 min read

Web Transport API

WebTransport is a modern API that provides low-latency, bidirectional, client-server messaging. It is built on top of HTTP/3 (and thus QUIC), offering a powerful alternative to WebSockets.

1. Why WebTransport?

While WebSockets are great for real-time communication, they are based on TCP. This means they suffer from "Head-of-Line Blocking": if one packet is lost, all subsequent packets must wait until it is retransmitted.

WebTransport, being based on QUIC, solves this. It supports:

  • Datagrams: Unreliable, out-of-order delivery (like UDP). Great for gaming or live streaming where speed > perfect accuracy.
  • Streams: Reliable, ordered delivery (like TCP), but multiple streams within a single connection are independent. If one stream blocks, others continue.

2. Connecting

To connect, you create a WebTransport instance with a URL (must be HTTPS).

const url = 'https://example.com:4433/webtransport';
const transport = new WebTransport(url);

// Wait for connection to be ready
try {
  await transport.ready;
  console.log('Connected to WebTransport!');
} catch (e) {
  console.error('Connection failed:', e);
}

// Handle closure
transport.closed.then(() => {
  console.log('Connection closed normally');
}).catch((error) => {
  console.error('Connection closed abruptly:', error);
});

3. Sending Datagrams (Unreliable)

Datagrams are "fire and forget". They are fast but might arrive out of order or not at all.

const writer = transport.datagrams.writable.getWriter();
const data = new Uint8Array([65, 66, 67]);

writer.write(data);
writer.releaseLock();

4. Receiving Datagrams

const reader = transport.datagrams.readable.getReader();

while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  console.log('Received datagram:', value);
}

5. Streams (Reliable)

WebTransport supports both unidirectional (one-way) and bidirectional (two-way) streams. These use the standard Streams API.

Creating a Bidirectional Stream

const stream = await transport.createBidirectionalStream();
// stream.readable (ReadableStream)
// stream.writable (WritableStream)

const writer = stream.writable.getWriter();
await writer.write(new TextEncoder().encode("Hello Server"));
writer.close();

Receiving Streams

You listen for incoming streams from the server.

const reader = transport.incomingBidirectionalStreams.getReader();

while (true) {
  const { value, done } = await reader.read();
  if (done) break;

  const stream = value;
  // Handle the new stream...
  // readDataFromStream(stream.readable);
}

6. WebTransport vs. WebSockets

Feature WebSockets WebTransport
Protocol TCP QUIC (HTTP/3)
Head-of-Line Blocking Yes (Global) No (Per stream/datagram)
Unreliable Data No Yes (Datagrams)
Multiple Streams No (Single stream) Yes (Lightweight streams)
Use Case Chat, simple real-time Gaming, Live Streaming, heavy real-time

programming/javascript/vanilla/javascript programming/javascript/vanilla/websockets programming/javascript/vanilla/streams-api