The in-browser voice path depends on three web platform APIs that are still maturing: WebTransport (media and data over QUIC), RTCRtpScriptTransform (the tap that lifts encoded Opus frames out of the browser’s codec — see WebRTC diversion), and WebCodecs (the decoder behind downlink playback). Support for all three is uneven across browsers. This page tells you where the full path runs, where it partly runs, and what to do when it does not run.
This page is about the browser SDK (@clutchcall/sdk) running in a web page. Native SDK cores (Python, Go, Rust, Java, .NET) reach the media plane through a shared QUIC transport and already ship a QUIC-to-WebSocket fallback ladder. The browser does not have that fallback yet. The sections below describe that gap.

The short answer

Chromium family

Full path. Chrome, Edge, and other Chromium-based browsers (Brave, Arc, Opera) run capture, publish, subscribe, and playback end to end.

Firefox

Uplink works, downlink needs your own decoder. Capture and publish run. The bundled player relies on a Chromium-only decoder.

Safari

Not yet. The encoded-frame tap ships only in Safari Technology Preview. Use a telephony leg today, or wait for the planned fallback.

Support matrix

This matrix is accurate as of this writing. Browser support moves quickly, so treat the version floors as a guide. Feature-detect at runtime (the SDK does this for you).
The last row is the one that matters for a product decision: only Chromium runs the whole loop out of the box today.

Why each browser lands where it does

Everything the browser SDK needs is stable in Chromium. WebTransport carries MoQT objects. RTCRtpScriptTransform runs in a Worker to lift encoded Opus off the loopback sender. The WebCodecs AudioDecoder feeds an AudioWorklet ring buffer for playback. If you build and test in Chrome or Edge, you are on the path we exercise most.
The uplink depends on the encoded-frame tap, which ships only in Safari Technology Preview. WebTransport is also still behind a preview flag. Until both land in stable Safari, the browser SDK media path does not run there. You have two options today. Route those users over a telephony leg (SIP / PSTN) instead of in-browser media. Or wait for the planned browser fallback described below.

What the SDK does when a capability is missing

The browser SDK feature-detects and refuses. It does not degrade silently. This is deliberate: a half-working audio path is worse than a clear error you can branch on.
  • captureMicrophone(...) checks for encoded-transform support first. If support is absent, it throws before it touches the microphone.
  • A connect with encoded transform required will reject the session on a browser that cannot provide it.
So on Safari, or an old Firefox, a capture call fails fast. Guard it and fall back to your own path:
There is no automatic WebSocket or WebRTC fallback in the browser today. The encoded-transform Worker is the only uplink path the browser SDK ships. This path is what enables frame-level end-to-end encryption (the relay only ever sees ciphertext). If encodedTransformSupported() is false, the browser cannot publish audio through the SDK. Plan for that branch.

The fallback story (what exists, what is planned)

The stack’s standing transport rule is QUIC and MoQT first-class, with WebSocket and WebRTC as required fallbacks. This is where each rung stands for browsers today:
1

QUIC / WebTransport — shipped (Chromium, Firefox uplink)

The primary path. MoQT rides WebTransport on the shared :443 listener, using the moqt-16 subprotocol. This is what the matrix above measures.
2

WebSocket media fallback — native cores only, not browser yet

The native SDK cores fall back from QUIC to a WebSocket media rung when UDP is blocked or a TCP proxy sits in the way. That ladder is not wired into the browser SDK. Treat browser WebSocket media as planned, not shipped.
3

WebRTC media fallback — server side exists, browser leg planned

The engine can terminate a real WebRTC leg server-side (ICE-lite with in-process DTLS-SRTP). This is how a UDP-blocked or Safari client would eventually reach the media plane. The server capability is in place. The browser SDK wiring for this automatic fallback is planned, not yet available.
Until the browser WebSocket and WebRTC rungs land, the practical fallback for a non-Chromium browser is a telephony leg: dial the user in, or let them dial a provisioned number. The audio path is then SIP/RTP rather than in-browser media. See Transport to telephony.

Local development gotchas

WebTransport and the dev-certificate flow are strict about the environment. These items trip people up before any compatibility question:
  • Secure context required. Serve over HTTPS (or localhost, which browsers treat as secure). RTCRtpScriptTransform, WebTransport, and getUserMedia all refuse to run on an insecure origin.
  • Use 127.0.0.1, not ::1. The IPv6 loopback literal breaks the QUIC handshake during local testing. The IPv4 loopback works.
  • Short-lived ECDSA dev cert. For local QUIC without a public CA, pass the certificate fingerprint via serverCertificateHashes. The certificate must be ECDSA and valid for no more than 14 days. Browsers reject longer-lived certs on that code path. This flow is unavailable in Safari.
  • Multi-brand SNI in production. The WebTransport listener presents per-brand certificates by SNI. Connect to the tenant’s own host (<workspace-id>.webrtc.clutchcall.dev / relay.clutchcall.dev) so the relay selects the right certificate.

Browser audio capture

Capture and encode microphone audio, and publish it as a MoQT track.

WebRTC diversion

Borrow the browser’s Opus encoder and divert encoded frames onto QUIC.

RTCRtpScriptTransform

The Worker tap that makes the encoded-frame path — and its E2EE — possible.

WebTransport

The browser-native QUIC path for media and data.

Mobile app transport

Where native mobile clients stand today.

Transport to telephony

The SIP/PSTN fallback for browsers that can’t run the media path.