WebRTCPSTNTURNSIP GatewayLiveKitReliability

WebRTC with PSTN Fallback: Keep Calls Connected

Browser and app calls work well most of the time. When they don't, it's usually the network: a corporate firewall, hotel Wi-Fi or a weak mobile signal. For sales calls, telehealth, support and anything else that can't simply be rescheduled, you need a plan for those moments. This guide covers the fallback ladder, from TURN relays to the phone network, and how to move a user to the phone without dropping them from the call.

Kaushik ParmarFounder & VoIP Architect · 12+ years in telecom and VoIP 12 min read
4
Steps in the fallback ladder
443
The port that gets through most firewalls
2
Phone options: dial-in, call-me
1
Session kept throughout

Quick answer

How do you add PSTN fallback to WebRTC calls?

WebRTC calls fail when networks block UDP, firewalls inspect traffic, bandwidth collapses or devices misbehave. Keep users connected with a ladder of fallbacks: direct WebRTC, then TURN relay over UDP, then TURN over TCP or TLS on port 443, and finally the phone network. Detect problems early with the ICE connection state and getStats, then offer the user a dial-in number with a PIN, or call them back (call-me), joining their phone into the same room or conference through a SIP gateway. Video can continue in the browser while audio moves to the phone.

Why WebRTC calls fail

WebRTC is reliable on ordinary home and mobile connections. Failures cluster in a few predictable situations, and knowing them tells you which fallback each one needs.

CauseWhat happensWhat fixes it
UDP blocked by a firewallMedia can't flow; the call connects but stays silent or failsTURN over TCP or TLS on port 443
Symmetric NATDirect connections fail between peersTURN relay
Deep packet inspection or strict proxiesEven relayed traffic is blocked or brokenTURN over TLS 443, or phone fallback
Captive portals and guest Wi-FiConnection drops or never startsPhone fallback
Poor bandwidth or heavy packet lossRobotic audio, frozen video, drop-outsAudio-only mode, then phone fallback
Microphone or headset problemsNo audio from the userDevice check, then phone fallback
Blocked permissions or old browsersCall can't startClear guidance, then phone fallback

The fallback ladder

WebRTC with PSTN fallback: a browser or app call first tries a direct WebRTC connection, then TURN over UDP, then TURN over TCP or TLS on port 443; if quality is still too poor or the connection fails, the user joins the same call by phone through dial-in or a call-me callback, connected by a SIP gateway into the same room or conference
Each step catches the failures the previous one can't; the phone is the last resort, not the first.

The goal is to try the cheapest, best-quality option first and fall back only as far as you have to. ICE, the connection process built into WebRTC, already tries the first three steps automatically if you give it the right servers. The last step is yours to build.

StepHow it connectsCatches
1. Direct WebRTCUDP between the browser and the peer or SFUMost home, office and mobile connections
2. TURN over UDPMedia relayed through your TURN serverSymmetric NAT and many restrictive routers
3. TURN over TCP or TLS on 443Media relayed over a connection that looks like HTTPSMost corporate firewalls and proxies
4. Phone networkUser joins by phone into the same callEverything else: blocked networks, poor bandwidth, device problems

Get TURN right before adding the phone

A phone fallback is no substitute for a well-configured TURN service; it is what you add after it. Most "WebRTC doesn't work here" reports disappear once TURN over TLS on port 443 is in place.

  • Run TURN servers close to your users, in each region you serve.
  • Offer TURN over UDP, TCP and TLS, with TLS on port 443 using a valid certificate.
  • Give the browser all of them in iceServers, so ICE can try each automatically.
  • Use short-lived TURN credentials generated by your server, not static passwords in the page.
  • Monitor TURN usage and bandwidth; relayed calls cost you bandwidth on every minute.

Our production TURN server guide covers coturn configuration, TLS on 443 and scaling in detail.

Detecting a failing call

The sooner you notice a problem, the sooner you can offer the phone, ideally before the user gives up. Combine three signals:

Pre-call check

Before joining, test the microphone, speaker and a connection to your TURN server. Catch blocked networks and device problems before the call starts.

ICE connection state

'failed' means no path worked; 'disconnected' for more than a few seconds usually means the network dropped.

Live quality stats

getStats reports packet loss, round-trip time and jitter. Sustained loss above a few percent or high round-trip time means audio is suffering.

Don't switch on a single bad second. Smooth the numbers over several seconds, show a gentle "connection is weak" notice first, and offer the phone if it doesn't recover.

Detection code in the browser

// Watch connection state and quality; offer phone fallback when needed
function watchCall(pc, onTrouble) {
  let badSamples = 0;

  pc.addEventListener("iceconnectionstatechange", () => {
    if (pc.iceConnectionState === "failed") onTrouble("no-connection");
  });

  const timer = setInterval(async () => {
    const stats = await pc.getStats();
    stats.forEach((r) => {
      if (r.type === "remote-inbound-rtp" && r.kind === "audio") {
        const loss = r.fractionLost ?? 0;          // 0..1, reported by the far end
        const rtt = r.roundTripTime ?? 0;          // seconds
        const poor = loss > 0.05 || rtt > 0.4;     // tune for your users
        badSamples = poor ? badSamples + 1 : 0;
        if (badSamples >= 5) onTrouble("poor-quality"); // about 5 seconds of poor audio
      }
    });
  }, 1000);

  return () => clearInterval(timer);
}

// Usage: show the fallback panel with dial-in details or a call-me form
const stop = watchCall(peerConnection, (reason) => {
  showPhoneFallback({ reason });                  // your UI
});

Report each fallback with its reason to your analytics. Over time you will see which networks and regions cause trouble, which often points to a missing TURN region or a customer whose firewall needs a rule.

Try audio-only before the phone

When the connection works but bandwidth is poor, the phone isn't the first answer. Video uses far more bandwidth than voice, so dropping it often rescues the call while keeping the user in the browser.

  • Turn off the user's outgoing video, or lower its resolution and frame rate, when packet loss or round-trip time rises.
  • Stop receiving other participants' video, or switch to a low-quality layer if your SFU uses simulcast.
  • Keep Opus audio with forward error correction (FEC) enabled, which helps it survive packet loss.
  • Prioritise audio in your SFU, so voice keeps flowing when the network is congested.
  • Tell the user what happened ('switched to audio only to keep your call stable') and let them turn video back on.

Only if audio is still poor, or the connection fails outright, offer the phone.

Phone fallback options

OptionHow it worksProsCons
Dial-inThe user calls a number and enters a PIN to joinFamiliar; user pays nothing extra on toll-freeNeeds numbers per country; typing PINs is error-prone
Call-me (callback)The user enters their number; the system calls themEasiest for users; one clickYou pay for outbound calls; some numbers block unknown callers
Audio on phone, video in browserPhone carries audio; browser keeps video and screen shareKeeps the visual part of the meetingUsers must mute the browser to avoid echo
Full switch to phoneThe user leaves the browser and continues by phoneSimplest when the browser is unusableLoses video and chat

Most products offer both dial-in and call-me, with call-me as the default and dial-in for users who prefer it or whose number can't receive calls.

Joining the phone into the same call

The critical design choice: the phone leg must join the same session, not start a new call. Otherwise the user disappears from the meeting and reappears as a stranger.

ArchitectureHow the phone joins
SFU such as LiveKitA SIP participant joins the same room, by dial-in through a SIP trunk or by dial-out from the server
FreeSWITCH conferenceWebRTC users (through Verto or a SIP-over-WebSocket gateway) and phone users join the same conference
Asterisk ConfBridgeWebRTC and SIP channels join the same ConfBridge
CPaaS platformThe provider's conference or room API adds a phone participant

Link the phone participant to the user's identity, so the room shows "Priya (phone)" rather than an unknown number, and so you can mute the browser's microphone automatically when the phone connects. Our WebRTC-SIP gateway guide covers the gateway side.

Example: call the user back into a LiveKit room

With LiveKit, your server can dial the user's phone and add them to the existing room as a SIP participant, using an outbound SIP trunk you have configured.

# Python (livekit-api): call the user's phone and join it to the same room
from livekit import api

async def call_me(room_name: str, user_id: str, phone_e164: str):
    lk = api.LiveKitAPI()   # reads LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET
    try:
        await lk.sip.create_sip_participant(api.CreateSIPParticipantRequest(
            sip_trunk_id="ST_outbound_trunk_id",       # your outbound trunk
            sip_call_to=phone_e164,                     # e.g. "+14155550123"
            room_name=room_name,
            participant_identity=f"{user_id}-phone",    # tie it to the user
            participant_name="Phone audio",
        ))
    finally:
        await lk.aclose()

Validate the phone number on your server, limit how often a user can request callbacks, and only allow callbacks to the number on the user's account or one they have verified, to prevent abuse.

Mobile apps: the same idea, easier switch

Native mobile apps have an advantage: the phone itself can make the fallback call. Instead of asking the user to dial and type a PIN, the app can start a regular phone call to your dial-in number with the PIN sent automatically as keypad tones.

// A tel: link with pauses and the PIN as DTMF: dial-in number, wait, then PIN and #
// iOS and Android both understand commas as pauses in tel: links
const dialIn = "tel:+14155550100,,482913%23";   // %23 is "#"
window.location.href = dialIn;                     // in a native app, open it with the platform's URL API
  • Offer 'Continue on a regular phone call' when the in-app call degrades.
  • Use CallKit on iOS and the Android telecom framework, so the switch looks like a normal phone call.
  • Keep the app's video and chat running if the user wants them, muting the app's audio.
  • Fall back to call-me when the device can't place calls, for example on a tablet without a SIM.

Designing the user experience

  • Show the fallback inside the call screen, not as an error page: 'Your connection is weak. Continue by phone?'
  • Default to call-me with the user's saved number, one click to confirm.
  • Show dial-in numbers for the user's country, with the PIN pre-filled where the phone supports it.
  • When the phone connects, mute the browser microphone and speaker automatically to prevent echo.
  • Keep video, screen sharing and chat running in the browser if they still work.
  • Let the user switch back to the browser when their connection recovers.
  • Tell other participants what happened: 'Priya joined by phone'.

Cost, numbers and security

ItemWhat to plan for
Phone numbersDial-in numbers for each country you serve; toll-free numbers cost more per minute
Outbound minutesCall-me calls are charged per minute, varying by destination country
SIP trunksInbound and outbound trunks connected to your SFU, conference server or gateway
SecurityRandom PINs per session, rate limits on callbacks, no callbacks to premium-rate numbers
Caller IDA recognisable, registered caller ID for callbacks, so users answer
DataPhone audio follows the same recording and retention rules as the WebRTC call

Because fallback is used on a small share of calls, phone costs are usually modest. Track minutes per call and per region to catch abuse or a misconfigured TURN region early. Our WebRTC developments guide covers related trends.

Testing your fallback

Fallback paths are used rarely, which is exactly why they break unnoticed. Test them on purpose, regularly.

ScenarioHow to simulate it
UDP blockedBlock outbound UDP on a test network or with a firewall rule; the call should connect over TURN TCP or TLS
Only port 443 openAllow only TCP 443; TURN over TLS should still connect
Packet loss and delayAdd loss and delay with a network emulator such as Linux tc netem; check audio-only mode and the fallback prompt
Network drop mid-callDisconnect Wi-Fi during a call; check reconnection, then the phone offer
CallbackRequest a call-me to mobile and landline numbers in each country you serve
Dial-inDial each country number and join with the PIN

Metrics to track

Connection path

Share of calls connected directly, through TURN UDP, TURN TCP/TLS and by phone, per region and customer.

Fallback reasons

No connection versus poor quality versus device problems; each points to a different fix.

Time to recover

How long users spent with poor audio before switching, and whether they stayed on the call.

Phone minutes

Dial-in and callback minutes per region, to watch cost and spot abuse.

Review these numbers monthly. A rising share of TURN TCP or phone fallback in one region usually means a missing TURN server nearby, a new corporate customer behind a strict firewall, or a browser update that changed behaviour, all of which are cheaper to fix than to keep paying for in phone minutes.

A real example

CelloIP built a WebRTC-to-SIP gateway for a VoIP provider using Kamailio, RTPengine and FreeSWITCH. Browser users get a web softphone, a click-to-call widget, video calls and calls to ordinary phone numbers, at hundreds of concurrent calls. The same building blocks, a SIP gateway between browsers and the phone network, are what make a PSTN fallback possible: the phone and the browser meet on the same platform.

CelloIP project outcome (client kept private)

Kamailio handles SIP over secure WebSocket, RTPengine converts browser media to standard RTP, and FreeSWITCH connects browser users to SIP phones, other browser users and the phone network. Built in one to three months and maintained by CelloIP.

Frequently asked questions

Why do WebRTC calls fail?

Most failures come from networks: corporate firewalls that block UDP or inspect traffic, symmetric NAT, hotel and guest Wi-Fi, VPNs, and poor mobile coverage. Others come from devices and browsers: denied microphone permission, a missing or busy headset, or an outdated browser.

Isn't a TURN server enough?

TURN fixes most connection failures, especially TURN over TLS on port 443, which looks like normal HTTPS traffic. It doesn't fix very poor bandwidth, heavy packet loss, locked-down networks that block media altogether, or device problems. A phone fallback covers those cases.

What is the difference between dial-in and call-me fallback?

With dial-in, the user calls a phone number and enters a PIN to join the same call. With call-me (callback), the user enters their phone number and the system calls them and connects them. Call-me is easier for users and avoids international dial-in numbers, but you pay for the outbound call.

How do you detect that a WebRTC call is failing?

Watch the RTCPeerConnection's ICE connection state for 'failed' or prolonged 'disconnected', and use getStats to track packet loss, round-trip time and jitter. A short pre-call test can also catch blocked networks and device problems before the call starts.

Can the user keep video while audio moves to the phone?

Yes. A common pattern is audio on the phone and video, screen sharing and chat in the browser, all in the same session. The phone leg joins the same room or conference, so everyone hears the user normally.

Which platforms support adding a phone participant to a WebRTC room?

LiveKit can dial out to a phone number as a SIP participant in a room, or accept dial-in through SIP trunks. FreeSWITCH and Asterisk conferences can mix WebRTC and SIP participants. CPaaS providers offer similar features.

What does a PSTN fallback cost to run?

Mainly phone minutes: inbound dial-in numbers (especially toll-free) and outbound callback calls. Because fallback is used only on a small share of calls, the cost is usually modest compared with the calls it saves.

Work with CelloIP

Want calls that don't drop when the network does?

CelloIP builds WebRTC calling with TURN, SIP gateways and phone fallback on LiveKit, FreeSWITCH, Asterisk and Kamailio, so users stay connected whatever network they're on. You own the code.