WebRTC packet loss: causes and how to diagnose it
Why WebRTC calls lose packets, which getStats metrics measure it, and how to tell a lossy network from a congestion problem.
Modern networks are flaky, working with best effort in mind. This means that packet losses can be quite common. When users complain about calls breaking up consistently, or that the video video dissolved into blocks for a second or two - it might be due to packet loss.
What you do in such cases, is look at webrtc-internals, either directly in the Chrome browser, or after downloading it for analysis. The place to start is by at packet loss metrics.
Here, we are going to explain what packet loss is in a WebRTC call, what causes it, which getStats() metrics to read, and how to tell a genuinely lossy path apart from a congestion problem.
What packet loss actually is
Packet loss is exactly what it sounds like: RTP packets that leave the sender and never arrive at the receiver. WebRTC has several media resilience techniques to cope: it recovers some packets with retransmissions (NACK) and hides others with error concealment. Past a certain rate, though, the loss shows through as audio dropouts, video artifacts, or blockiness.
Two getStats() metrics measure it directly:
inbound-rtp.packetsLost: the running count of packets that never arrived.packetsLost as a percentage: loss expressed against packets expected, which is the number you actually reason about.
The sender's view of loss comes back over RTCP as remote-inbound-rtp.fractionLost, which tells you loss on the path from you to the other side. These are reported back via RTCP packets.
How that loss actually shows up depends on the media. On video it usually surfaces as video freezing: a single lost packet can break a frame and stall playback until a clean one arrives. On audio it surfaces as choppy audio: the missing samples get concealed, which is the robotic, breaking-up sound users report. The metrics here are the technical cause; those two are how it gets seen.
What causes it
In rough order of how often it is the culprit:
- Network congestion. A saturated link drops packets once its queues overflow. This is the most common cause, and it usually rises and falls with bitrate.
- Wi-Fi and radio problems. Interference, weak signal, or a congested channel loses packets in bursts rather than a steady trickle.
- An overloaded or undersized relay. A TURN server or SFU that is out of capacity drops packets under load.
- Rate limiting or shaping on a corporate or carrier network that caps real-time traffic.
- A genuinely lossy last mile (bad cabling, a failing AP, a marginal cellular cell) that loses packets even when nothing is congested.
How to diagnose it
Read the loss rate and not the raw count, and read it against bitrate over time.
| Metric | Healthy | Trouble |
|---|---|---|
packetsLost percentage |
under ~1% | sustained over ~3 to 5% |
nackCount |
low, stable | climbing (receiver asking for resends) |
| loss versus bitrate | loss flat as bitrate rises | loss climbs exactly when bitrate does |
The correlation is what matters:
- Loss climbs as bitrate climbs: congestion. The path cannot carry what you are sending, so the sender needs to back off (and usually will, via bandwidth estimation).
- Loss in bursts, bitrate steady: a radio or Wi-Fi problem, not raw capacity. Look at signal and interference on the affected leg.
- Loss steady and low but audio still bad: loss may not be your real problem. Check jitter and the concealment metrics.
nackCounthigh with loss recovering: retransmission is doing its job, but it adds delay. On a live call that recovery has a latency cost.
Do this over time. A ten second burst of loss during a Wi-Fi roam is a transient issue; loss that tracks bitrate for the whole call is a capacity problem you can act on.
For a deeper walkthrough of reducing packet loss at its source, see fixing packet loss in WebRTC.
How rtcStats surfaces it
Doing that correlation by hand in webrtc-internals means lining up the loss, bitrate, and NACK timelines yourself. rtcStats reads the dump for you: it flags the loss spike as an Observation, ties it to what bitrate and retransmission were doing at the same moment as a Deduction (congestion versus a lossy radio path), and reflects the impact in the Experience Score so you can see how much the loss actually hurt the call. The AI Summary gives you the one-paragraph version to paste into your bug thread.
Related
- inbound-rtp.packetsLost
- inbound-rtp.packetsLost (%)
- remote-inbound-rtp.fractionLost
- inbound-rtp.nackCount
- WebRTC video freezing
- WebRTC choppy audio
Upload a webrtc-internals or rtcstats dump and rtcStats tells you whether the loss was congestion or the network, free.
Was this page helpful?