Skip to content

Reference · printable

WebTransport API cheat sheet

The browser API on one page: session, streams, datagrams, closing and errors. Snippets are examples with placeholder URLs.

Last updated October 28, 2026 · Facts checked October 28, 2026 · Print this page for a one-page copy.

Create a session

Connect with the WebTransport constructor

The URL must use https and an explicit port; a bad URL or a fragment throws SyntaxError. MDN currently marks this 'Baseline 2026, Newly available' (since March 2026), with a note that parts of the feature have varying support, and it is secure-context only.

const transport = new WebTransport("https://example.com:4433/echo");
await transport.ready; // resolves once the session is established
console.log("connected");

Sources: WebTransport() constructor (MDN) ; WebTransport.ready (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Trust a certificate by hash with serverCertificateHashes

Replaces Web PKI validation for this connection. MDN says the certificate must be X.509v3 with under two weeks of validity and an ECDSA P-256 key, and the option cannot be combined with allowPooling: true. Only sha-256 is defined.

const certHash = new Uint8Array(32); // placeholder: SHA-256 of your server certificate
const transport = new WebTransport("https://example.com:4433/echo", {
  serverCertificateHashes: [{ algorithm: "sha-256", value: certHash }],
});
await transport.ready;

Sources: WebTransport() constructor (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Hint a congestion control preference

Only a hint; the browser may fall back to "default". MDN currently marks this 'Limited availability' (not Baseline) on the congestionControl property page, and the spec flags "low-latency" as a feature at risk because no browser implements a low-latency algorithm yet.

const transport = new WebTransport("https://example.com:4433/echo", {
  congestionControl: "low-latency", // "default" | "throughput" | "low-latency"
});
await transport.ready;
console.log(transport.congestionControl); // the preference as the browser reports it

Sources: WebTransport() constructor (MDN) ; WebTransport.congestionControl (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Refuse a reliable-only fallback with requireUnreliable

Defaults to false. MDN marks the reliability property page 'Limited availability' (not Baseline), while the constructor page shows 'Baseline 2026, Newly available' (since March 2026).

const transport = new WebTransport("https://example.com:4433/echo", {
  requireUnreliable: true, // do not fall back to a reliable-only (HTTP/2) session
});
await transport.ready;
console.log(transport.reliability); // "pending" before ready, then "reliable-only" or "supports-unreliable"

Sources: WebTransport() constructor (MDN) ; WebTransport.reliability (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Negotiate an application protocol with protocols

If the server supports none of the offered protocols, ready rejects. Per the spec, duplicates, empty values and values over 512 characters throw SyntaxError. The option is documented by both MDN and the W3C spec.

const transport = new WebTransport("https://example.com:4433/echo", {
  protocols: ["chat", "file-transfer"], // in order of preference
});
await transport.ready;
console.log(transport.protocol); // the server's choice, or "" if it selected none

Sources: WebTransport() constructor (MDN) ; WebTransport API (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Session lifecycle

Watch ready and closed

Both promises exist from construction. closed resolves with { closeCode, reason } and rejects on unexpected closure such as a network failure. MDN currently marks this 'Baseline 2026, Newly available' (since March 2026).

const transport = new WebTransport("https://example.com:4433/echo");
transport.closed
  .then(({ closeCode, reason }) => console.log("closed", closeCode, reason))
  .catch((err) => console.error("closed abruptly", err));
try {
  await transport.ready;
} catch (err) {
  console.error("session failed", err);
}

Sources: WebTransport.ready (MDN) ; WebTransport.closed (MDN) ; WebTransport API (MDN) . Checked Oct 28, 2026.

React to draining

Draining is only a request: either side may keep using the session, but the app is expected to wrap up soon. The W3C spec lists draining as a session state. MDN's draining page carries no Baseline banner at the moment.

async function migrateOnDraining(url, oldTransport) {
  await oldTransport.draining; // fulfills when the server signals draining
  const next = new WebTransport(url);
  await next.ready;
  oldTransport.close(); // retire the old session once the new one is up
  return next;
}

Sources: WebTransport.draining (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Close with a code and reason

closeCode defaults to 0 and the reason is truncated to 1024 UTF-8 bytes per the spec. MDN names the parameter info; the spec calls it closeInfo. MDN currently marks this 'Baseline 2026, Newly available' (since March 2026).

transport.close({ closeCode: 17, reason: "CloseButtonPressed" });
const info = await transport.closed;
console.log(info.closeCode, info.reason);

Sources: WebTransport.close() (MDN) ; WebTransport.closed (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Inspect reliability after ready

Tells you whether the session can carry unreliable datagrams. MDN currently marks this 'Limited availability' (not Baseline).

await transport.ready; // reliability is "pending" before this point
if (transport.reliability === "reliable-only") {
  // no datagrams: stick to streams
} else {
  // "supports-unreliable": datagrams are available
}

Sources: WebTransport.reliability (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Bidirectional streams

Open a stream, write, then read

Assumes a server that echoes and closes its side. MDN currently marks this 'Baseline 2026, Newly available' (since March 2026) for createBidirectionalStream(), with partial-support asterisk. It rejects with InvalidStateError if the session is closed or failed.

const stream = await transport.createBidirectionalStream();
const writer = stream.writable.getWriter();
await writer.write(new TextEncoder().encode("hello"));
await writer.close(); // tries to send pending data before closing
const reader = stream.readable.getReader();
for (;;) {
  const { value, done } = await reader.read();
  if (done) break;
  console.log(new TextDecoder().decode(value)); // value is a Uint8Array
}

Sources: WebTransport.createBidirectionalStream() (MDN) ; WebTransportBidirectionalStream (MDN) ; WebTransport API (MDN) . Checked Oct 28, 2026.

Accept server-opened streams

incomingBidirectionalStreams is a ReadableStream of WebTransportBidirectionalStream objects. MDN currently marks this 'Baseline 2026, Newly available' (since March 2026).

const reader = transport.incomingBidirectionalStreams.getReader();
for (;;) {
  const { value: stream, done } = await reader.read();
  if (done) break;
  // each value is a WebTransportBidirectionalStream opened by the server
  stream.readable.pipeTo(stream.writable).catch(console.error); // echo it back
}

Sources: WebTransport.incomingBidirectionalStreams (MDN) ; WebTransportBidirectionalStream (MDN) ; ReadableStream (MDN) . Checked Oct 28, 2026.

Prioritise streams with sendOrder

MDN's createBidirectionalStream() page documents only sendOrder (an integer; its own examples pass a string). The W3C spec also lists sendGroup and waitUntilAvailable, which MDN does not describe on that page.

const urgent = await transport.createBidirectionalStream({ sendOrder: 10 });
const bulk = await transport.createBidirectionalStream({ sendOrder: 1 });
// queued bytes on the higher sendOrder stream are sent first

Sources: WebTransport.createBidirectionalStream() (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Unidirectional streams

Send on a client-opened stream

The returned WebTransportSendStream is itself a WritableStream. MDN currently marks this 'Limited availability' (not Baseline) on the createUnidirectionalStream() page (it is also marked this way on the WebTransportSendStream page).

const stream = await transport.createUnidirectionalStream(); // a WebTransportSendStream
const writer = stream.getWriter();
writer.write(new Uint8Array([65, 66, 67]));
try {
  await writer.close(); // tries to send all pending data first
  console.log("All data has been sent.");
} catch (error) {
  console.error(`An error occurred: ${error}`);
}

Sources: WebTransport.createUnidirectionalStream() (MDN) ; WebTransportSendStream (MDN) . Checked Oct 28, 2026.

Receive server-opened unidirectional streams

The outer loop awaits each stream in turn; handle streams concurrently in real code. MDN currently marks this 'Baseline 2026, Newly available' (since March 2026) for incomingUnidirectionalStreams, whereas the WebTransportReceiveStream page is marked 'Limited availability' (not Baseline).

const reader = transport.incomingUnidirectionalStreams.getReader();
for (;;) {
  const { value: receiveStream, done } = await reader.read();
  if (done) break;
  const chunks = receiveStream.getReader(); // a WebTransportReceiveStream
  for (;;) {
    const r = await chunks.read();
    if (r.done) break;
    console.log(r.value); // Uint8Array
  }
}

Sources: WebTransport.incomingUnidirectionalStreams (MDN) ; WebTransportReceiveStream (MDN) . Checked Oct 28, 2026.

Abort a send stream

With abort() the browser may discard data that has not yet been sent. Without a WebTransportError reason, the spec sends error code 0. See the Errors section for aborting with a code.

const stream = await transport.createUnidirectionalStream();
const writer = stream.getWriter();
writer.write(new Uint8Array([65, 66, 67]));
await writer.abort(); // pending data may be discarded

Sources: WebTransport.createUnidirectionalStream() (MDN) ; WritableStream (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Datagrams

Send datagrams with createWritable()

MDN calls the datagrams.writable fallback "deprecated and non-standard" and prefers createWritable(); the W3C spec text I read lists only createWritable(). MDN currently marks this 'Baseline 2026, Newly available' (since March 2026) for the datagrams property.

const writable =
  typeof transport.datagrams.createWritable === "function"
    ? transport.datagrams.createWritable()
    : transport.datagrams.writable; // deprecated and non-standard
const writer = writable.getWriter();
await writer.ready;
writer.write(new Uint8Array([65, 66, 67])).catch(() => {});

Sources: WebTransport.datagrams (MDN) ; WebTransportDatagramDuplexStream.createWritable() (MDN) ; WebTransportDatagramDuplexStream (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Read incoming datagrams

Datagrams are unreliable: not guaranteed to arrive, and not in order. Only works on sessions that support unreliable transport.

const reader = transport.datagrams.readable.getReader();
for (;;) {
  const { value, done } = await reader.read();
  if (done) break;
  console.log(value); // Uint8Array
}

Sources: WebTransport.datagrams (MDN) ; WebTransportDatagramDuplexStream (MDN) . Checked Oct 28, 2026.

Respect maxDatagramSize

maxDatagramSize is the largest outgoing datagram, in bytes, that may be written. It is read-only.

const writer = transport.datagrams.createWritable().getWriter();
const payload = new Uint8Array(200);
if (payload.byteLength <= transport.datagrams.maxDatagramSize) {
  await writer.ready;
  writer.write(payload).catch(() => {});
}

Sources: WebTransportDatagramDuplexStream (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Expire stale datagrams with incomingMaxAge and outgoingMaxAge

Both are read/write and measured in milliseconds. Per the spec, 0 is stored as null, and a negative or NaN value throws RangeError.

transport.datagrams.incomingMaxAge = 2000;  // milliseconds
transport.datagrams.outgoingMaxAge = 2000;
console.log(transport.datagrams.outgoingMaxAge); // null when no maximum age is set

Sources: WebTransportDatagramDuplexStream (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Datagram queue-size attributes (names differ) sources differ

MDN documents incomingHighWaterMark and outgoingHighWaterMark; the W3C spec text I read documents incomingMaxBufferedDatagrams and outgoingMaxBufferedDatagrams (minimum 1) instead. Probe for the name before using either.

const d = transport.datagrams;
console.log("incomingHighWaterMark" in d);        // named by MDN
console.log("incomingMaxBufferedDatagrams" in d); // named by the W3C spec

Sources: WebTransportDatagramDuplexStream (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Errors and aborting

Inspect a WebTransportError

source is "stream" or "session"; streamErrorCode is null if unavailable. MDN says the code is in the range 0-255, but the W3C spec defines an unsigned long, so treat the upper bound as unsettled. MDN currently marks this 'Baseline 2026, Newly available' (since March 2026).

try {
  await transport.ready;
} catch (error) {
  if (error instanceof WebTransportError) {
    console.log(error.source, error.streamErrorCode); // "stream" | "session", number | null
  } else {
    throw error; // e.g. a SyntaxError for a bad URL
  }
}

Sources: WebTransportError (MDN) ; WebTransportError() constructor (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Abort a send stream or cancel a receive stream with a code sources differ

Per the spec, abort and cancel use the reason's streamErrorCode when the reason is a WebTransportError, else 0, and clamp to 0-4294967295. The constructor signature disagrees: the spec shows (message, { source, streamErrorCode }) while MDN shows a single init object with message and streamErrorCode.

const send = await transport.createUnidirectionalStream();
await send.getWriter().abort(new WebTransportError("done", { streamErrorCode: 7 }));

// for a server-opened receive stream:
await receiveStream.getReader().cancel(new WebTransportError("unwanted", { streamErrorCode: 7 }));

Sources: WebTransport (W3C Working Draft) ; WebTransportError() constructor (MDN) ; WebTransportError (MDN) ; WebTransportSendStream (MDN) ; WebTransportReceiveStream (MDN) . Checked Oct 28, 2026.

Feature detection

Check that WebTransport exists

In a worker, use typeof WebTransport !== "undefined" instead, since window is not defined there. The interfaces are exposed in Window and Worker contexts.

if ("WebTransport" in window) {
  // safe to construct a WebTransport
} else {
  // fall back to WebSocket or another transport
}

Sources: WebTransport.supportsReliableOnly (MDN) ; WebTransport (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Check for a secure context

The WebTransport interfaces are marked SecureContext, so they exist only on https pages (or localhost). In workers, check self.isSecureContext.

if (!window.isSecureContext) {
  console.warn("WebTransport needs a secure context (https or localhost)");
}

Sources: Secure contexts (MDN) ; WebTransport (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Probe members that may be missing

Treat newer members as optional. MDN currently marks congestionControl, reliability, createUnidirectionalStream(), WebTransportSendStream and WebTransportReceiveStream as 'Limited availability' (not Baseline), while the main WebTransport page shows 'Baseline 2026, Newly available' with partial-support asterisk.

const hasCreateWritable = typeof transport.datagrams.createWritable === "function";
const hasCongestionControl = "congestionControl" in WebTransport.prototype;
const hasSendGroups = "createSendGroup" in WebTransport.prototype;
const canFallBackToReliableOnly = WebTransport.supportsReliableOnly; // static boolean

Sources: WebTransport (MDN) ; WebTransport.supportsReliableOnly (MDN) ; WebTransport.datagrams (MDN) ; WebTransport.congestionControl (MDN) ; WebTransport (W3C Working Draft) . Checked Oct 28, 2026.

Terms: see the glossary. Try the API in the tester. Download as JSON.

Cite this page

Title
WebTransport API cheat sheet
Author
WebTransport Day (organization)
URL
https://webtransport.day/cheatsheet/
Updated

WebTransport Day. "WebTransport API cheat sheet." Last updated October 28, 2026. https://webtransport.day/cheatsheet/

Type to search. Esc closes.