WebRTC Calling Without the Science Project: Browsers as First-Class Endpoints
Hand someone a browser and a headset and they’re on the phone — no install, no VPN, works from a hotel lobby. That’s the promise of WebRTC telephony, and the part that usually turns into a science project is everything around the codec: ICE, STUN/TURN, certificate handling, and the NAT scenarios that only fail on customer networks.
RustPBX treats browsers as first-class endpoints. Here’s what’s actually involved.
What a Browser Endpoint Needs
A browser client registers over SIP over WebSocket (WSS) and negotiates DTLS-SRTP media. On the PBX side that’s:
- The WebSocket listener enabled and reachable (WSS through your TLS cert — the ACME post covers certificate automation)
- ICE servers published to clients for NAT traversal (
[ice_servers], or per-agenticeServersfor the CC desk) - Full ICE on WebRTC legs, regardless of the trunk-side settings
RustPBX ships sample browser phones (static/phone_jssip.html, phone_sipjs.html) — open one, enter the extension credentials, and you’re registered. For production agent UIs, the CC Desk is the ready-made option.

Bridging WebRTC ↔ SIP Carriers
The media bridge translates between the two worlds automatically:
- Browser DTLS-SRTP ↔ carrier plain RTP or SDES-SRTP
- Same-codec legs take the fast path (no transcode); mixed codecs enter the transcode path
- ICE stays on the browser leg; the carrier leg is symmetric RTP
No trunk-side toggles needed — negotiate the browser leg normally and the bridge handles the mismatch.
When ICE “Just Doesn’t Work”
ICE failures are almost always one of four things, and the built-in probe surfaces all of them:
| Symptom | Likely cause |
|---|---|
| ICE never leaves “checking” | No STUN reachable, or UDP blocked |
| Connects, then drops | TURN credentials expired / wrong |
| Works on LAN, fails remotely | Only host candidates gathered (no STUN/TURN) |
| Certificate error at answer | WSS cert name mismatch |
Diagnostics → Connection runs a live ICE probe against your configured servers from the browser that will actually place the call — which beats testing from a server on the wrong side of the NAT.
For strict enterprise networks, ice_relay_only forces TURN-relay candidates only (ice.transport_policy = relay on the engine side): you lose direct paths but gain a single predictable media path. Cost: all media transits TURN.
The Desk Angle
CC Desk and RustPhone deliver the same WebRTC stack. RustPhone’s diagnostics panel reports ICE aggregation state, candidate inventories, and per-call media segments (ICE pair, RTP counters, codec) straight to support — so “my calls drop” arrives as data, not a description.
Checklist for Browser Rollout
- WSS cert valid and trusted by the browsers you support
- STUN reachable; TURN configured if any user is behind symmetric NAT
-
ICE servers published to agents (
iceServersfrom agent config) - Media port range open on the host firewall
- ICE probe run from a real client network
That’s the whole science project. Guides: Basic Setup and Agent Desk & Clients.