:443. There is
no second media port to open, no UDP range to whitelist beyond 443, and no raw
protocol port to reason about. The browser dials https://relay.clutchcall.dev
and gets a WebTransport session on the same endpoint that serves everything
else.
Open a session
You never touch theWebTransport object directly. Every SDK ships a
MoqtClient that opens the session, negotiates the protocol version, and keeps
it alive across drops. Call connect and start publishing.
- TypeScript
- Python
- The SDK rewrites the
quic://URL tohttps://and attaches the tenant token as a query parameter. The relay’s control plane checks the token before any track flows. - The client advertises the MoQT version as the WebTransport subprotocol
(
moqt-16). The relay refuses a session that does not offer it, so this is not optional. The SDK always sends it for you. connectreturns as soon as the session is up. The client auto-reconnects with capped backoff if the link drops, and it replays every publication and subscription. TheonStatecallback reportsConnecting/Connected/Reconnecting/Closed/Failed.
The browser SDK is WebTransport-only today. If QUIC is blocked (some
corporate proxies, UDP-filtered networks), the browser client cannot fall back
on its own. The QUIC→WebSocket fallback ladder currently ships only in the
native SDK cores. For those environments, use the WebRTC media leg described in
Browser compatibility.
How MoQT rides the session
MoQT (Media-over-QUIC Transport) carries your named tracks (voice/<sid>/uplink and
voice/<sid>/downlink for a call) inside the one WebTransport session. It uses
two of WebTransport’s primitives:
- A control stream — a single bidirectional stream carries MoQT setup and the subscribe/publish signalling. This is where the client and relay agree on versions, announce namespaces, and track subscriptions.
- Object streams — each track group opens its own unidirectional stream of objects. Audio rolls over to a fresh group roughly once a second, so a live call is a rolling series of short-lived streams, each carrying ~1 s of encoded audio objects. Each group on its own stream means a lost or slow group cannot head-of-line-block the next one. The transport keeps moving.
Streams vs datagrams
WebTransport offers two ways to move bytes, and they trade reliability for latency differently:The server certificate hash
In production, the relay presents a normal CA-issued certificate with multi-brand SNI, so the browser trusts it like any HTTPS origin. You pass no hash, and theserverCertificateHashes machinery never engages.
For local development against a self-signed relay, WebTransport lets you
pin the exact certificate by its SHA-256 fingerprint, so you do not need to
install a CA. Pass the base64 hash, and the SDK wires it into the session:
- Dev (self-signed)
- Production (CA cert)
Related
Transport to web & apps
How browser and mobile clients reach the voice stack over QUIC.
Browser audio capture
Capture and encode the microphone, then publish it over this session.
One-line WebRTC diversion
Divert an existing WebRTC audio pipeline onto QUIC in one call.
Browser compatibility
What works where, and the fallback when QUIC is blocked.

