Browser-native softphones. No installs, no per-seat charges, full duplex.
Open a URL, sign in, and your laptop is a SIP phone. It dials another extension, an AI agent, or a PSTN number through your trunk — and it rings when calls come the other way. Encrypted media, no plug-in, no extension chain.
The shortest path from web page to phone call
SIP over WebSocket has been a published IETF standard (RFC 7118) since January 2014. It lets a SIP softphone live entirely inside a browser tab: signalling rides a WebSocket (ws:// or wss://) to the gateway, media flows over WebRTC with DTLS-SRTP encryption. The user installs nothing. The administrator adds an extension to a tenant and shares a URL.
CodeB ships the listener, the per-tenant TLS auto-discovery, the WebRTC to SIP media bridge, and the routing logic that gets in-dialog requests (BYE, REFER, INVITE) back to a browser whose registered Contact URI is not reachable from the public internet. That last part is technically demanding and is the reason several widely deployed soft-PBX platforms still don't offer SIP-WS as a first-class feature.
Browser to bridge to anywhere
Same browser tab, both directions. No second app for incoming calls.
What you can actually do
Full-duplex calling
Dial anything routable from your tenant; ring on inbound. No second-class endpoint. Same auth, same CDRs, same lawful-interception path as a hardphone.
In + OutAI receptionist transfer
An AI agent on a virtual number can transfer the caller to a named registered colleague (browser or hardphone) mid-conversation via SIP REFER, then exit cleanly.
RFC 3515BYOC SIP trunks
The same WebSocket softphone places calls through whichever trunk provider you already pay (consumer routers, on-prem PBX, Tier-1 wholesalers). No third-party intermediary.
No lock-inEncrypted media
Audio negotiates DTLS-SRTP automatically (WebRTC default), Opus at 48 kHz. Per-direction RTP timestamping prevents jitter-buffer resets at the WebRTC to SIP boundary.
DTLS-SRTPNAT traversal handled
The gateway injects server-reflexive ICE candidates into its SDP so the browser can reach it from any public network behind any NAT. Same ICE-Lite responder the sovereign SBC uses for hardphones.
ICE-LiteMulti-tenant TLS
Per-tenant certificate auto-discovery on the WebSocket listener. One bridge process serves many tenants; each tenant's SAN cert is picked at connect time by SNI.
SNI · per-tenantACL gates apply
The same per-tenant allow / deny rules that govern UDP and TCP SIP traffic apply to WebSocket REGISTERs and INVITEs. Manage via the admin console.
Unified policyInstallable as PWA
The demo softphones are Progressive Web Apps: “Add to Home Screen” on iOS / Android puts a launcher icon on the home screen. Credentials persist in browser localStorage.
PWARFC 7118 native
Any RFC 7118 compliant client works — SIP.js, JsSIP, sipML5, Linphone-WS, your own. Not a vendor-locked browser app pretending to be a SIP softphone.
Open standardSix-direction bridging
Every routing direction works: browser to AI agent, browser to office tab, browser to PSTN trunk, trunk to browser, office to browser, and browser to browser. Each direction is a first-class bridge, not a degraded fallback.
Full matrixG.711 transcoding
European trunks negotiate A-law (PCMA), browsers default to mu-law (PCMU). The bridge transcodes between the two in either direction at the codec layer. Pass-through when both sides match; no overhead when codecs align.
PCMA ↔ PCMURingback before answer
180 Ringing fires the moment the bridge receives the INVITE; the final 200 OK is deferred until the callee actually picks up. The caller's softphone plays its local ringback during setup — no silent “connected but dead” window.
Defer 200 OKSibling-fork collapse
When the upstream PBX forks the same call across two trunks, only the first delivery rings the softphone; the second is held silently at 180. The upstream's own fork arbitration resolves cleanly without sabotaging other endpoints.
Multi-trunk safeHot-reload config
Per-trunk capacity (inbound / outbound / total lines), credentials, registrar host and routing rules apply within the watchdog interval (under 10 seconds). No service restart, no dropped calls.
Under 10 sCaller-hangup propagation
When the caller hangs up during ringback the bridge immediately CANCELs the callee leg with a matching Via branch (RFC 3261 sec 9.1). The callee phone stops ringing in milliseconds, not after a 30-second timeout.
RFC 3261Wire-form correctness
Outbound SIP responses re-sync Content-Length to actual body byte count before serialisation. Defends against subtle truncation that some carrier stacks would otherwise reject as malformed SDP.
Bytes matchWhere browser softphones replace something you currently maintain
Bring-your-own-device remote work
Field staff, contractors, hospitality casuals, part-time receptionists. Anyone who needs to make and take calls from a company number on their personal laptop without you shipping them software, paying per-seat licenses, or managing MDM enrollment. Send them a URL; sign-in is the same OIDC sign-in they use for the rest of the suite.
One-click “Talk to sales / support” from any page
A single bookmarked URL on a contact page, in an email signature, or as a QR code on print marketing dials your team instantly when the visitor opens it. No app install, no third-party redirect, no callback queue. Visitors stay on your domain.
AI-first call centres
Inbound calls hit an AI receptionist that triages, books, or hands off. The receptionist's REFER can land on a browser softphone in a corner of the agent's monitor — no separate softphone install per agent seat.
Embedded operations consoles
Drop a sip-js or JsSIP softphone into your internal admin tool / CRM / dispatch board. The phone becomes another widget on the page the operator is already looking at; calls log against the same record they're editing.
Compliance-bound industries
Browser softphones inherit the same per-tenant ACL, signed CDRs, recording hooks, and policy enforcement as the hardphone fleet. No new audit surface; the comms still run on your own self-hosted stack.
Disaster-recovery seat
When the main PBX dies or the hardphones won't register, anyone with the URL and credentials has a working softphone in 30 seconds on whatever browser is nearest.
Two installable demo softphones
Both run against the public CodeB tenant. Sign-in is automatic with the test credentials in the page; you can also add to your home screen and it behaves like a native phone app.
SIP.js demo
SimpleUser API. Smaller surface, easier to drop into existing JS code. Open the SIP.js softphone →
JsSIP demo
Event-driven API. Closer to the underlying SIP protocol; useful when you need full control over individual session events. Open the JsSIP softphone →
If you want to wire your own browser softphone (custom UI, embedded in an existing app), point the library's wsUri at wss://phone.aloaha.com:5443 and the tenant credentials work the same way.
Honest scoping
- Not a transcoding farm: media is forwarded between WebRTC and SIP with codec negotiation, not heavy transcoding (Opus stays Opus, G.711 stays G.711 where both ends speak it).
- Not a substitute for hardphone density: if a desk worker spends 8 hours a day on calls, give them a SIP hardphone with proper acoustics. The browser softphone shines for occasional, mobile, or BYO use.
- Not a free pass on the network. Browsers need ICE / TURN to traverse hostile NATs. The gateway provides STUN and TURN per tenant, but a corporate firewall that blocks UDP entirely will still force TURN-over-TCP and slow down ICE negotiation.
- Not vendor lock-in. You can swap SIP.js for JsSIP for Linphone-WS for your own React component — the WebSocket listener accepts any RFC 7118 compliant client.
Operator questions, answered
Which call directions are supported?
All six: browser to AI agent, browser to office tab, browser to PSTN trunk, trunk to browser, office to browser, browser to browser. Each direction is a dedicated bridge with its own SDP shaping, ICE candidate injection and media path setup.
What about codec mismatch between browser (PCMU) and EU PSTN (PCMA)?
The bridge transcodes G.711 A-law and mu-law in either direction at the codec layer (PCM16 intermediate). Pass-through when both ends negotiate the same variant; no overhead when codecs align.
Does the caller hear ringback before the callee answers?
Yes. The bridge sends 180 Ringing the moment the INVITE arrives and defers the final 200 OK until the callee actually picks up. The caller's softphone plays its local ringback during the wait — no silent “connected but dead” gap.
What happens when an upstream PBX parallel-forks across two trunks?
Sibling-fork collapse: only the first delivery rings the softphone; siblings within a 2-second window are held silently at 180 so the upstream's own fork arbitration resolves naturally without a 4xx that would cancel every ringing endpoint on the account.
Can I disable a trunk for inbound without cancelling carrier parallel forks?
Set MaxConcurrentInbound to 0 in the per-tenant configuration. The bridge holds 180 silently instead of returning 403 Forbidden, so the upstream PBX continues fork arbitration to other trunks.
Are configuration changes hot-reloaded or do they need a restart?
Hot-reloaded. Per-trunk capacity, credentials, host, routing rules apply within the watchdog interval (under 10 seconds). Both global trunks in the bridge's appsettings.json and per-tenant trunks in the admin console reload without restarting the service or interrupting in-flight calls.
What standards does the SIP-WS stack conform to?
RFC 7118 for SIP over WebSocket transport, RFC 3261 for SIP signalling, RFC 3264 for offer/answer, RFC 3515 for in-call REFER, RFC 5245 / 8445 for ICE, RFC 8829 for DTLS-SRTP, RFC 4566 for SDP and RFC 3550 for RTP.
Get a tenant with browser softphones already on
SIP-over-WebSocket is included with every CodeB tenant by default. No extra license, no extra module, no per-seat charge for browser users.
Get your own tenant → All features