Privacy and exposure

WebRTC leaks

WebRTC sets up peer-to-peer connections by gathering candidate addresses for your device, including its local address and the public address a STUN server sees. A page can read those candidates with JavaScript, which historically exposed your real IP even behind a VPN. Modern browsers replace the local address with a random mDNS name, so what remains at risk is mainly the public one.

See what your browser offers up right now on /webrtc-leak-test.

What WebRTC is doing when it leaks

WebRTC lets two browsers exchange audio, video, and data directly, without relaying everything through a server. To do that each side has to work out how the other can reach it, which is hard when both sit behind NAT.

The mechanism is ICE, Interactive Connectivity Establishment, RFC 8445. Your browser collects every plausible way it might be reachable, calls each one a candidate, and offers the list to the other side. Both ends then test pairs until something works.

The leak is that a page can start this gathering process without any peer at the other end, and read the candidate list as it arrives. Nothing is exploited. The API is doing exactly what it was designed to do.

The three candidate types

Type Where it comes from What it shows
host The device’s own interfaces Your private address, such as 192.168.1.47, or a global IPv6 address
srflx (server-reflexive) A STUN server reports the address it saw Your public address, as NAT rewrote it
relay A TURN server that will forward the media The relay’s address, not yours

A server-reflexive candidate is obtained from a STUN server, RFC 8489, whose entire job is to answer “what address did this packet appear to come from”. Relay candidates use TURN, RFC 8656, and cost the operator bandwidth, so they are a fallback rather than a default.

The host candidate was the damaging one. In 2015 a page could read the private address of every interface, including the address on a VPN adapter, which fingerprinted the network layout behind NAT and defeated a tunnel that only handled the public side.

mDNS obfuscation closed most of the hole

Browsers now replace host candidates with a random hostname ending in .local, resolvable only over multicast DNS on the local link. The approach is specified in the IETF draft Using Multicast DNS to protect privacy when exposing ICE candidates, and it ships in Chrome, Edge, Safari, and Firefox.

A candidate now looks like this:

candidate:1 1 UDP 2122260223 a1b2c3d4-e5f6-4789-a0b1-c2d3e4f56789.local 54321 typ host

The other end of a genuine call is on your network, or is going to use a different candidate anyway, so resolution works where it needs to. A remote web page gets a UUID that means nothing. This is why a leak test showing .local names is a pass rather than a finding.

What mDNS does not cover is the server-reflexive candidate. That one is a real public address by definition, and it is the field to read on any test.

When a public address still leaks through a VPN

The srflx candidate reports whichever public address the STUN packets came from. If your VPN carries those packets, it shows the VPN’s address and everything agrees. It shows your real address when:

  • Split tunnelling excludes the browser or excludes UDP traffic.
  • The tunnel is IPv4 only on a dual-stack connection, so a global IPv6 host candidate or an IPv6 reflexive candidate goes direct. This is the same failure mode that produces DNS leaks and direct IPv6 web traffic.
  • The client sets a proxy for HTTP but not for UDP, which some browser-extension VPNs do.
  • The tunnel dropped and traffic fell back to the physical interface without a kill switch.

The tell is a mismatch: the address on /report belongs to the VPN provider, while /webrtc-leak-test shows a candidate from your ISP. Two addresses from the same provider is a pass.

Per-browser mitigation

Firefox. Open about:config and set media.peerconnection.enabled to false to switch WebRTC off entirely. To keep it working while limiting exposure, leave it enabled and set media.peerconnection.ice.default_address_only to true, which restricts gathering to the default route.

Chrome and Edge. There is no setting to disable WebRTC. The old #enable-webrtc-hide-local-ips-with-mdns flag is now default behaviour and no longer exposed. For more control, use the official WebRTC Network Limiter extension, which sets the browser’s IP handling policy rather than blocking the API.

Safari. mDNS obfuscation is on by default. Safari also asks before granting camera and microphone access to a site, which limits the cases where full candidate gathering happens.

Brave. Settings, Privacy and security, WebRTC IP handling policy, set to “Disable non-proxied UDP” if you run a proxy or VPN.

Any browser with a VPN. Prefer fixing the tunnel over disabling WebRTC. A tunnel that carries UDP and IPv6 makes the candidates correct instead of absent, and it fixes DNS and plain web traffic at the same time.

Testing it properly

Run /webrtc-leak-test and read three things:

  1. Are host candidates .local names, or real private addresses?
  2. Does the server-reflexive address match the address on /report?
  3. Do IPv4 and IPv6 candidates come from the same network?

Then check it again after your VPN reconnects, because a client that applies its rules only at connection time can pass immediately after connecting and fail after a network change. The combined verdict on /vpn-check runs all of this together with the DNS and address checks.

Questions people ask

Do I still need to worry about WebRTC leaks?
Less than in 2015. Chrome, Edge, Safari, and Firefox now hide the local address behind a random mDNS hostname by default. The server-reflexive candidate still shows a public address, so a split-tunnel VPN or a partial tunnel can still expose your real one.
Should I disable WebRTC?
Only if you never use browser video calls, screen sharing, or in-browser voice chat, since disabling it breaks all of them. Firefox has a real off switch. Chrome does not, so an extension that restricts candidate gathering is the closest equivalent.
Why does the test show a name ending in .local?
That is mDNS obfuscation working. The browser replaced your private address with a random UUID hostname that only devices on your own network can resolve. It reveals nothing about you.
Does a VPN stop WebRTC leaks?
It does if all traffic including UDP goes through the tunnel. It does not if the client uses split tunnelling, if it tunnels IPv4 only, or if it leaves UDP outside. Test it rather than assume it.

Last reviewed 2026-09-04. Reviewed quarterly, or sooner when a vendor changes something.