WebRTC Leaks: What They Are and How to Stop Them

Updated 2026-08-137 min read6 sections
Advertisement
Short answer

A WebRTC leak happens when a web page uses the browser peer-connection API to gather ICE candidates, which can include your real public IP even while a VPN is active. Restrict IP handling per browser to stop it.

What WebRTC actually exposes

WebRTC is the browser API set that makes browser-to-browser audio, video and data connections possible without a plugin. Video calls, screen sharing in web apps, and peer-to-peer file transfer all rely on it. To connect two peers that both sit behind NAT, each side has to discover and advertise every address it might be reachable on. That discovery process is the leak.

The addresses gathered can include the private LAN address of your machine, the public address your traffic exits from, and the address of any relay in use. A page can request this list from JavaScript without any user permission prompt, because gathering candidates for a data channel does not require camera or microphone access.

The practical risk for a VPN user is specific: if the browser gathers a candidate from a network interface that is outside the tunnel, a page can learn your real ISP-assigned address while the rest of your traffic appears to come from the VPN exit. Correlating those two facts is enough to defeat the point of the VPN.

note

A WebRTC leak is not a browser bug and never was. It is the protocol working as specified in RFC 8445 (ICE). The mitigations all work by restricting which interfaces the browser is allowed to enumerate.

How ICE candidate gathering works

Interactive Connectivity Establishment, defined in RFC 8445, has the browser build a list of candidate transport addresses and then test them in pairs until one works. There are three kinds.

Host candidates are the addresses configured on your local interfaces, such as 192.168.1.42 or a fe80:: link-local address. Server-reflexive candidates come from a STUN query (RFC 8489) to a public server, which replies with the address it saw the request arrive from; that is your public IP. Relay candidates come from a TURN server, which relays media when direct connection fails and therefore only reveals the relay's address.

The leak surface is the first two. Host candidates reveal your internal network layout. Server-reflexive candidates reveal your real public address if the STUN request escapes the tunnel, which happens when the VPN routes only some traffic, when the tunnel does not carry UDP, or when a second interface remains routable.

  • Host candidate: candidate:1 1 udp 2122260223 192.168.1.42 51820 typ host
  • Server-reflexive: candidate:2 1 udp 1686052607 203.0.113.77 51820 typ srflx raddr 192.168.1.42
  • Relay: candidate:3 1 udp 41885439 198.51.100.10 60000 typ relay
  • The srflx line is the one that matters most; raddr on the same line also carries the host address.

Testing for a leak yourself

You do not need a testing site. Open the browser console on any page and create a peer connection with a public STUN server, then print every candidate as it arrives. Compare the addresses that appear with the public address your VPN gives you.

Run this with the VPN connected. If any srflx candidate shows an address that is not your VPN exit address, that is a live leak. If host candidates show a .local hostname instead of a private IP, mDNS obfuscation is working.

const pc = new RTCPeerConnection({iceServers:[{urls:'stun:stun.l.google.com:19302'}]});
pc.createDataChannel('x');
pc.onicecandidate = e => { if (e.candidate) console.log(e.candidate.candidate); };
pc.createOffer().then(o => pc.setLocalDescription(o));
tip

Also test after a network interruption. Toggle Wi-Fi off and on with the VPN client running, then immediately re-run the snippet. The reconnection window is where interfaces briefly become routable outside the tunnel.

Advertisement

Chrome, Edge and Brave

Chrome removed the user-facing WebRTC flags years ago. The supported control is the enterprise policy WebRtcIPHandling, which also applies to Edge and to Chromium-based browsers generally. It accepts four values: default, which uses all interfaces; default_public_and_private_interfaces; default_public_interface_only, which stops host candidates from private interfaces; and disable_non_proxied_udp, which forces WebRTC through the configured proxy or falls back to TCP.

For a VPN user, default_public_interface_only is the usual choice because it keeps calls working while removing LAN address exposure. disable_non_proxied_udp is stricter and will break peer-to-peer calls on networks without a proxy, so treat it as the setting for a machine where WebRTC is not needed.

Brave exposes the same control in its own settings rather than requiring policy, at brave://settings/privacy under WebRTC IP handling policy, with the same four options in plain language.

  • Confirm the policy took effect at chrome://policy, not by assuming the registry write worked.
  • Extensions that claim to control WebRTC generally set the same underlying preference; a policy value takes precedence over an extension.
  • Edge reads the same policy names under HKLM\SOFTWARE\Policies\Microsoft\Edge.
# Windows, run as Administrator
reg add "HKLM\SOFTWARE\Policies\Google\Chrome" /v WebRtcIPHandling /t REG_SZ /d default_public_interface_only /f

# macOS
sudo defaults write com.google.Chrome WebRtcIPHandling -string "default_public_interface_only"

# verify in the browser
# open chrome://policy and confirm the policy shows as applied

Firefox and Safari

Firefox still allows direct configuration in about:config, which makes it the easiest browser to lock down precisely. Three preferences matter. Setting media.peerconnection.enabled to false disables WebRTC entirely and will break browser-based calls. Setting media.peerconnection.ice.default_address_only to true restricts candidates to the default route's address. Setting media.peerconnection.ice.no_host to true suppresses host candidates while leaving server-reflexive gathering intact.

For most people the pairing of default_address_only set to true and no_host set to true is the right balance: calls continue to work, the LAN address stops appearing, and candidates follow the default route, which is the VPN when the VPN is up.

Safari does not gather candidates as aggressively and does not expose the local address to a page that has not been granted media permission. If you need to inspect its behaviour, enable Settings, Advanced, Show features for web developers, then use the Develop menu, where WebRTC options including ICE candidate restrictions appear. Safari on iOS follows the same model and has no user-facing WebRTC toggle.

// Firefox about:config
media.peerconnection.ice.default_address_only = true
media.peerconnection.ice.no_host = true
media.peerconnection.ice.proxy_only_if_behind_proxy = true
// nuclear option, breaks video calls
media.peerconnection.enabled = false

What mDNS obfuscation changed, and what it did not

Chromium and Firefox now replace host candidates with randomly generated multicast DNS hostnames that look like 9a1b2c3d-4e5f-6789-abcd-ef0123456789.local. Peers on the same network can resolve them; a remote web page cannot. This effectively closed the local-address disclosure that fingerprinting scripts used to enumerate your LAN.

It did not close the public address disclosure. Server-reflexive candidates still carry a real routable address, because that is the entire purpose of a STUN query. If the STUN packet leaves through your ISP rather than your VPN, the page still learns your real IP.

So the mitigation order is: make sure the tunnel actually carries UDP and captures all interfaces, then restrict IP handling in the browser as a second layer, and only disable WebRTC entirely if you genuinely never use browser calls. Also confirm the tunnel is not split by application, since split tunnelling that excludes the browser reintroduces every problem this article describes.

warning

Disabling WebRTC breaks Google Meet, Jitsi, Discord in the browser, browser-based screen sharing, and many customer-support widgets. If those matter, use IP-handling restrictions instead of a full disable, and keep a second browser profile for the rare case where you need unrestricted peer connections.

Frequently asked

Does a VPN stop WebRTC leaks on its own?

Sometimes. A full-tunnel VPN that captures UDP and leaves no other routable interface will make every gathered candidate show the VPN exit address. Split tunnelling, IPv4-only tunnels on dual-stack networks, and browser extensions that proxy separately all break that assumption, which is why an independent browser-side restriction is worth setting.

Is a .local address in my ICE candidates a leak?

No. That is mDNS obfuscation working correctly. The browser generates a random hostname that only resolves on your local network, so a remote page learns nothing about your internal addressing. It is the server-reflexive candidate, marked typ srflx, that carries a real public address and needs checking.

Which Chrome setting stops WebRTC leaks?

There is no user-facing setting; Chrome removed the flags. Use the WebRtcIPHandling enterprise policy set to default_public_interface_only for a balance of privacy and working calls, or disable_non_proxied_udp for maximum restriction. Verify at chrome://policy that the value is applied rather than assuming the registry or defaults write succeeded.

Do WebRTC leaks affect mobile browsers?

Yes for Chrome and Firefox on Android, which gather candidates the same way as desktop. On iOS every browser uses the system WebKit engine, which is more conservative and does not expose local addresses to pages without media permission. Mobile VPN profiles that capture all traffic generally prevent public address exposure.

Can a website read my IP through WebRTC without asking permission?

It can gather ICE candidates for a data channel without any prompt, because no camera or microphone access is involved. Media permission prompts only appear when the page requests those devices. This is why the exposure is worth mitigating rather than relying on noticing a permission dialogue.

Advertisement

Related reading

Run the diagnostics on your own connection