Guides ·

WebRTC leaks: what they are, how to test, and what each browser does

WebRTC is the browser feature behind voice and video calls and peer-to-peer data. To find a working path it sends UDP requests to a STUN server, which replies with the address it saw. If that UDP request doesn’t go through your proxy, the STUN server sees your home connection’s public IP, and any web page can read it. That is a WebRTC leak. Modern browsers hide your local network IP by default, but not the public IP that STUN reports back. For someone in mainland China, the leaked address is usually a mainland IP that doesn’t match the proxy exit.

At a glance: how WebRTC leaks another IPPage requests go through the proxy, so sites see the proxy exit. WebRTC’s STUN request uses UDP, which skips the proxy in system-proxy mode, so the page can read your home broadband IP. At a glance: how WebRTC leaks another IP Page requests (HTTPS) Proxied Browser Proxy app Proxy exit IP Sites see the proxy exit, same as a checker WebRTC STUN request (UDP) May go direct Browser Skips proxy Home ISP IP A few lines of JavaScript can read this IP Usually system-proxy mode; with TUN, check routing rules.
Page traffic and WebRTC’s UDP take separate routes. STUN only sees your proxy exit when UDP goes through the proxy too.

How WebRTC learns your IPs

WebRTC uses ICE to gather “candidate” addresses and then tests which ones connect. RFC 8445 defines several types; two matter here:

  • host: an address on one of your network interfaces, including virtual ones such as a VPN’s. Usually a private IP like 192.168.x.x.
  • srflx (server reflexive): the address and port a STUN server saw when your device sent it a packet. RFC 8489 describes STUN as a way for an endpoint to learn the IP and port a NAT allocated to it.

Candidates are handed to the page as text lines (RFC 8839) ending in typ host, typ srflx and so on. No camera or microphone permission is needed: WebKit explains that without that access Safari still exposes server-reflexive and TURN candidates.

mDNS hides the local IP, not the public one

Local IPs can be used for tracking, so browsers replace the address in host candidates with a random .local name. The IETF draft describing this (a random UUID plus .local) expired without becoming an RFC, but browsers ship the idea:

  • Chrome began rolling it out in Chrome 76 in 2019; the announcement says it applies to all sites except those with camera or microphone permission.
  • Firefox has media.peerconnection.ice.obfuscate_host_addresses on by default, and its source skips the obfuscation while a page is capturing or holds camera or microphone permission.
  • Safari withholds host candidates until the page is granted camera or microphone access.

The same draft is explicit that a server-reflexive candidate is still generated, and it carries a real IP address. mDNS does nothing for the public address STUN sees.

Why it leaks with a proxy on

RFC 8828, the IETF’s WebRTC IP-handling requirements, lists three exposures: a split-tunnel VPN lets WebRTC find both the VPN address and the ISP address; private addresses behind a NAT can be learned; and behind a proxy with direct internet access allowed, STUN checks bypass the proxy and reveal the client’s public IP. It also notes that all HTTP proxies and most SOCKS proxies don’t support UDP.

In terms of a typical proxy app:

  • System proxy mode: the app registers itself as the OS HTTP / SOCKS proxy, and page requests go through it. WebRTC’s UDP follows the routing table straight out of your home connection, so STUN sees your real public IP.
  • TUN mode (virtual adapter / enhanced mode): the app creates a virtual network device — the Linux kernel docs describe a TUN device as one that passes packets to and from a user-space program — so UDP reaches the app too. What happens next depends on whether the line can forward UDP and on your routing rules; requests to STUN servers inside China may match a “direct” rule.

Any page can read srflx addresses with a few lines of JavaScript. Whether ChatGPT, Claude or Gemini do, and how they would use it, isn’t public. Still, page traffic from an overseas exit next to a WebRTC address in mainland China is a pair of signals that don’t agree.

How IP Judge tests for it

The check runs on the home page and on the Claude, ChatGPT and Muse pages, in the WebRTC row of “Browser and connection checks”:

  1. It opens four WebRTC connections at once, each with a single STUN server: Cloudflare (stun.cloudflare.com:3478), Google (stun.l.google.com:19302), and two in China, Xiaomi (stun.miwifi.com:3478) and Bilibili (stun.chat.bilibili.com:3478). The Chinese servers are there because routing rules often send them direct; asking only an overseas server can miss the leak.
  2. Each connection creates a data channel and an offer to start candidate gathering, and keeps the first srflx address and the first host address. It stops when gathering completes, or after 4 seconds if a STUN server doesn’t answer.
  3. Each srflx IP is compared with every exit the page found: the IP that opened the site, the IPs claude.ai and chatgpt.com saw, and the IPv4-only and IPv6-only exits. It compares the IPs themselves, not countries.
  • If an overseas STUN server (Cloudflare, Google) returns an IP that matches none of those exits, it’s flagged red as “Leaks another IP”: UDP isn’t going through the proxy, which is typical of system-proxy mode.
  • If only the China-based STUN servers (Xiaomi, Bilibili) return another IP, it’s flagged amber as “China STUN goes direct”. The overseas servers see your proxy exit, so UDP is already proxied; your routing rules treat the China-based STUN domains as direct. Only a site that deliberately asks a China-based STUN server can read that IP, so it costs half the points.
  • Either way, the page looks up the IP’s country and network, adds it to “Who sees which of your IPs”, and lists the matching fix under “How to fix”.
  • All srflx IPs match an exit: “Consistent”. No STUN server answered: “No leak”. WebRTC missing or disabled: “WebRTC is unsupported or disabled”, also counted as no leak.
  • A .local host address is shown as hidden by the browser (normal). A real local IP is displayed as a note and doesn’t count as a leak.
How IP Judge rates WebRTCIt asks four STUN servers at once, Cloudflare and Google overseas and Xiaomi and Bilibili in China, and compares each IP with every exit the page found. Another IP from an overseas server is red; another IP only from the China-based servers is amber; all IPs matching an exit is consistent; no answers is no leak. How IP Judge rates WebRTC Four STUN servers at once OverseasCloudflare, Google In ChinaXiaomi, Bilibili Each IP vs every exit: same IP, not same country Verdicts Leaks another IP Overseas STUN sees another IP; UDP isn’t proxied China STUN goes direct Only China STUN sees another IP; half the points Consistent All IPs match an exit No leak No STUN server answered Claude score: red costs 12 points, amber 6.
The China-based servers are there because routing rules often send them direct; asking only an overseas server can miss the leak.

In the Claude score, a WebRTC leak costs 12 of the 20 points in the Leaks section (6 if only China-based STUN servers leak); in the Muse sign-up score it costs 10 of 15 (5). These are IP Judge’s own weights, not published platform rules — see the Method page.

What each browser offers

Chrome and Edge

  • Google publishes an official extension, WebRTC Network Limiter (developer: Google Ireland, Ltd.; still listed as of this writing, last updated October 2023). By default it stops WebRTC from using private IPs and public IPs on interfaces that don’t carry web traffic. With a system proxy you also need its option to disable non-proxied UDP, which is off by default and set on the extension’s Options page. The store listing warns that since most proxies don’t handle UDP, this effectively turns UDP off, and calls may lag or lose quality.
  • On managed machines, Chrome’s WebRtcIPHandling policy (Chrome 91+) set to disable_non_proxied_udp only uses UDP when a configured proxy supports it; WebRtcIPHandlingUrl (Chrome 133+) sets it per site. Edge’s equivalent is WebRtcLocalhostIpHandling (Edge 77+ on Windows and macOS), where DisableNonProxiedUdp means TCP unless the proxy supports UDP; it needs a browser restart.
  • If the check shows a real local IP in Chrome, the WebRtcLocalIpsAllowedUrls policy may list the site, or chrome://flags/#enable-webrtc-hide-local-ips-with-mdns may be disabled.

Firefox

The controls live in about:config: type about:config in the address bar, accept the warning, search for the preference and double-click a true/false value to toggle it (Mozilla’s guide). A 2025 Mozilla Connect idea asking for a WebRTC toggle in Settings is still marked “New idea”.

  • media.peerconnection.ice.default_address_only limits candidates to the default-route interface; media.peerconnection.ice.no_host removes local addresses from candidates (Mozilla wiki).
  • Also set media.peerconnection.ice.proxy_only_if_behind_proxy to true. In Firefox’s source, the extension API’s disable_non_proxied_udp is exactly these three set to true.
  • media.peerconnection.enabled set to false turns off RTCPeerConnection entirely (MDN); sites that need in-browser calls stop working.

Safari

Per WebKit, Safari doesn’t give ordinary pages your local addresses but does give them srflx candidates, so it leaks the public IP in system proxy mode just the same. We found no Apple documentation of a user-facing WebRTC switch. The developer setting “Disable ICE Candidate Restrictions” turns off host-candidate filtering according to WebKit; it is for testing, so leave it off. Safari users mostly rely on the network side, below.

Proxy apps: system proxy vs TUN mode

The goal is for WebRTC’s UDP to leave through the same exit as your page traffic, or not leave at all.

  1. In system proxy mode STUN always goes direct. Either switch to TUN mode, or disable non-proxied UDP in the browser as above.
  2. In TUN mode, check that your line forwards UDP. If it doesn’t, make sure UDP is dropped rather than sent direct.
  3. Check that your rules don’t send STUN servers — especially ones in China — direct.
  4. Re-run the check on the home page. All four STUN rows should show your exit IP or “no response”.

For how to read the IP each AI site sees, see Which IP do ChatGPT and Claude actually see? The DNS side of the same problem is covered in DNS leaks.

FAQ

The WebRTC IP is in the same country as my exit. Is that still a leak?

IP Judge compares IPs, so any address that matches none of your exits is flagged, even in the same country. Look at the network the page shows: if it’s your home ISP, your real IP is leaking; if it’s another proxy line, your UDP is taking a different exit, which is worth making consistent too.

My local address shows as a long .local name. Is something wrong?

No. The browser replaced your local IP with an mDNS name, so pages can’t see your real LAN address.

Does granting a site camera or microphone access change anything?

Yes. Chrome, Firefox and Safari all relax host-candidate protection for sites with that permission, which is why a video-call site can see your local IP.

Isn’t it easier to just turn WebRTC off?

It is, but in-browser voice and video calls stop working, and the check will show WebRTC as unsupported or disabled. Routing UDP through the proxy is the cleaner fix; restrict the browser when you can’t.

Which kind of IP do you have?

Check my IP for free