Blog

WebRTC leak test: run it and read the result

A WebRTC leak test lists the addresses a web page can read from your browser. Run it in three states, learn which rows matter, and see what a VPN leaves alone.

Published October 29, 2026 · 11 minutes read

Key takeaways

  • WebRTC test pages list two ICE candidate kinds that matter: host rows from your device and server-reflexive rows from a STUN server, the public one.
  • At Working, with data flowing both ways, our Linux run read only the exit's IPv4 and IPv6 addresses as public candidates.
  • With local-address hiding off, the host row showed the tunnel's own address at Working and a private LAN-class address with the tunnel down.
  • A VPN does not change the browser's WebRTC policy, the host rows it exposes or what a page can read after a permission grant.
On this page (10)

A WebRTC leak test shows the addresses a web page can read from your browser: host rows from your device and a public IP address row from a STUN server, which reports your public address. A public row equal to your own network's, while the VPN shows Working, is the finding. Everything else on the list needs reading, not panic.

WebRTC is the W3C WebRTC standard for real-time communication in browsers: video calls, screen sharing and direct data transfer between two browsers. To connect them it has to learn your addresses, and a page script can ask for the same list. That list is what a test page prints.

What is a WebRTC leak?

A WebRTC leak is an address that a page reads through WebRTC and that you did not expect with the VPN on. The page opens a connection object (RTCPeerConnection), and the browser gathers ICE candidates: the addresses a peer could use to reach you. RFC 8445 defines ICE, and each candidate has a type.

Candidate typeWhere it comes fromWhat a page learnsReading with the VPN on
HostA network interface on your deviceA local address, or a random .local nameNot public. Check the class, not the digits
Host, mDNSThe same interface, hidden behind a generated nameOnly the name, which changes between sessionsExpected in a default browser
Server-reflexive (srflx)A STUN server's replyThe public address the server sawShould be the exit's, not your network's
RelayA TURN serverThe relay's addressOnly if the page supplies one

The server-reflexive row comes from a STUN binding request (RFC 8489): the browser sends a UDP packet to a STUN server, and the server replies with the source address it saw. MDN's connectivity guide describes that exchange. So the public row is simply the address of whichever network carried that packet.

Host candidates used to print the real local address. The IETF mDNS ICE candidates draft describes concealing them behind a generated Multicast DNS (mDNS) name, so a page sees a random name ending in .local and not the address. That draft is why most test pages today show names where older write-ups showed 192.168 addresses.

How do I test for a WebRTC leak?

Run the test three times and write down the candidate classes each time. What you need: the ForestVPN app, one WebRTC test page and a second browser. Public pages such as browserleaks.com and dnsleaktest.com show this list; we did not run either for this post, and name them only as the kind of tool to use.

  1. Tunnel down. With the VPN off, open the test and note each row's class: mDNS name, private address, or public. The public row is your own network's address. This is your baseline.
  2. Tunnel up. Turn the app on and wait for Working (connection verdict), which means data flows both ways (see connection status). Idle is not a fault, only a quiet app, but send some traffic before you test. If the app shows something else, start with VPN connected but no internet or VPN not connecting.
  3. Kill switch on, tunnel down (Windows and Linux only). Switch the kill switch on and disconnect. On these two systems the block stays while the tunnel is down, so the STUN packet has nowhere to go and seeing no public row is the pass. On a Mac, iPhone or Android a manual disconnect is not a drop and does not test the kill switch: the app disarms when you disconnect, or on Android blocks only while it runs. The kill switch is never absolute: system services can still go around the tunnel on some platforms, as the kill switch page says.

Start in a desktop browser, then repeat step 2 in a second browser, since each browser has its own WebRTC settings. On Android, run steps 1 and 2 in your browser the same way, and see the Android section below for what to switch on. Open a fresh tab for each run, because a cached page can pass for a new result.

What did our WebRTC leak test show with the VPN on and off?

In our run on the published Linux client, a page script saw no public candidate other than the exit's address at the Working verdict, and the physical adapter supplied none. With the kill switch on and the tunnel down, no public candidate appeared at all.

How this was tested

Product
ForestVPN Linux desktop client, published .deb
Version
the Linux package current on 2026-10-29
System
Ubuntu 26.04 LTS, GNOME, one network adapter, home-lab VM
Checked
Runs
3
Not tested

Three connects on 2026-10-29 from a lab VM on the Free plan, no account. Firefox (current stable snap) and Chromium (current stable snap), headless, a fresh profile per run, no camera or microphone permission asked or granted. A local test page opened an RTCPeerConnection with a data channel against two public STUN servers and collected candidates for 8 seconds; addresses were classified and masked inside the VM, so no address is saved.

A second variant per browser turned local-address hiding off (Firefox preference media.peerconnection.ice.obfuscate_host_addresses set to false; Chromium started with --disable-features=WebRtcHideLocalIpsWithMdns). Exit: Frankfurt only.

The lab line itself already leaves from Germany, so the public row was judged against what a trace endpoint reported from inside the VM in each state, not against a different country. One probe set ended at Blocked after handshake and one at Degraded because the lab line policed traffic, and no result depends on them.

Codes and verdicts this post maps: net.working (Working), net.idle (Idle), net.degraded (Degraded) and net.blocked_after_handshake (Blocked after handshake).

Not tested: Android, Windows, macOS, a router, iOS, the third-party test pages themselves, a real (non-headless) browser window, candidates after a camera or microphone grant, a browser extension, Firefox fingerprint resistance, and IPv6-only networks.

StateApp verdictHost rows (mDNS names)Public IPv4 rowsPublic IPv6 rows
Tunnel downOff (disconnected)2 / 11 / 10 / 0
Up, kill switch offWorking, then Degraded4 / 22 / 12 / 1
Up, kill switch onWorking4 / 21 / 11 / 1
Kill switch on, tunnel downOff (disconnected)2 / 10 / 00 / 0

Firefox lists a UDP and a TCP host row, which is why its host count is higher. The public IPv4 row was the exit's address at Working, and the tunnel-down row was the lab line's own. Every public row, in all four states, matched the address that the trace endpoint reported in that state.

Chromium, default settings, 2026-10-29: host rows, public IPv4 rows and public IPv6 rows in each state. Firefox counts are in the table.

What does a WebRTC test show with local-address hiding off?

With local-address hiding off, the host row showed a private LAN-class address when the tunnel was down, one per transport, and at Working it showed the tunnel interface's own address in the 100.64 range plus an IPv6 link-local address. No private LAN-class row from the physical adapter appeared at Working in either browser, in either variant.

Two earlier probe sets, at the Blocked-after-handshake and Degraded verdicts, showed the same classes. The kill switch on and the tunnel down gave host rows and no public row, because STUN could not leave. A public IPv6 row at Working matched the exit's IPv6 address; for that class see IPv6 leaks.

How do I read WebRTC test results?

Read each row by its class: a public row at the exit's address is expected, a public row equal to your own network's is a leak, and a local row is not public at all. The table below gives the reading for the three cases you meet.

You seeReading while the verdict is WorkingWhat to do
Public row equal to the exit's addressExpected: the STUN packet left through the tunnelNothing
Public row equal to your own network's addressA leak: the packet reached the STUN server outside the tunnelReconnect, wait for Working, rerun; then check browser policy and IPv6
A .local name or a private LAN addressNot public. A site learns your network layout, not your locationKeep the mDNS default; see the browser section
A public IPv6 rowCompare it with the exit's IPv6 address, not your network'sSee IPv6 leaks

Compare with your step 1 list, not with the digits you remember. If your network's public address is on the list at Working and your IPv4 address page is clean, trust the WebRTC list: STUN is UDP the browser sends itself, and it can take a different path from the page request.

DNS is a different check. A WebRTC page does not show which resolver answered you, and the help page on DNS leaks and Tor covers it.

Why does my VPN not stop a WebRTC leak?

A VPN picks the network path your packets take. It does not rewrite what the browser decides to reveal, so four things sit outside it.

  • Host candidates. Your device's own interfaces are still listed. With the tunnel up the list names the tunnel interface, not the physical one; with the tunnel down it names the LAN.
  • Browser policy. The browser decides which candidates a page may see. Chrome documents policies for this on its privacy API page: default, default_public_and_private_interfaces, default_public_interface_only and disable_non_proxied_udp.
  • A route the tunnel does not cover. If the default route leaves a gap, such as an IPv6 path, the STUN packet takes it. The check for that is the step 2 rerun at Working, plus the IPv6 leaks post.
  • Permission-gated lists. After a camera or microphone grant, the browser may stop hiding host addresses behind mDNS names, as the IETF mDNS draft describes. We did not test a grant.

The honest limit: a VPN protects the path, not the page. Showing fewer details is a browser job, and that comes next.

Which browser settings change what WebRTC shows?

Settings decide the host rows and whether WebRTC runs at all. The ones to know are three, and none of them is a tunnel setting.

SettingEffectCost
Default (mDNS host names)Host rows show a random .local nameNone for calls
Local-address hiding off (Firefox media.peerconnection.ice.obfuscate_host_addresses = false; Chromium flag WebRtcHideLocalIpsWithMdns)Host rows show the real local addressA page learns your network layout
Public-interface-only policy (Chrome's default_public_interface_only)One of four WebRTC IP handling policies on Chrome's page, which does not describe each value; we did not run itSome direct peer connections may not form
WebRTC off (Firefox media.peerconnection.enabled = false)No candidates; the test shows nothingIn-browser calls and screen sharing stop

The first two rows are the variants of our run, and they are the only settings we measured. The last two are documented settings we did not run, so we describe them and say nothing about how they behave on your machine. Change them in the browser's own settings, not in the VPN.

Browser extensions that block WebRTC exist, and we name none. Test one the same way as the VPN: three states, read the classes, rerun after an update.

Is blocking WebRTC a good idea?

Usually not, unless you never use it anyway. Turning WebRTC off with a preference such as media.peerconnection.enabled stops the candidates, and it stops everything built on it too: browser video calls, screen sharing and some in-page file transfer.

The better order is: keep the mDNS default, confirm the public row at Working, and block only if a test still shows your own network's address after you reconnect. Then you have a real finding, not a habit. A blocked feature also hides the evidence: with WebRTC off the test shows nothing, and you cannot tell whether the tunnel was fine.

Does a WebRTC leak happen on Android?

It can, since Android browsers expose the same WebRTC API, but we did not run Android for this post. The only Android build in our lab was not a store-installed published one, so we state nothing about Android results.

What you can do is the same test. Run it with the VPN off, then at Working, in your browser. For drops, the Android app blocks traffic only while ForestVPN is running; turn on Always-on VPN with Block connections without VPN in the system settings to cover a disconnect, as the help page on Always-on VPN, battery and Private DNS explains. For IPv6, the page on networks, IPv6, DNS and MTU lists what to check.

What should I remember about WebRTC leak tests?

Read classes, not digits. A public row equal to the exit's address is the expected result at Working, a public row equal to your own network's is the finding, and local rows are your network layout. The VPN decides the path; the browser decides what a page can see.

Questions and answers

What is a WebRTC leak?

An address a page reads from your browser through WebRTC that you did not expect with the VPN on, usually a public one from your own network.

How do I test for a WebRTC leak?

Open a WebRTC test page with the VPN off, then again at Working, and compare the public rows.

Does a VPN stop WebRTC leaks?

It sets the path of the STUN packet, so the public row becomes the exit's. Browser settings stay yours to change.

Is a local IP address in the result a leak?

No. Local rows are private or .local names, so a page learns your network layout, not your location.

Is blocking WebRTC a good idea?

Rarely. It breaks in-browser calls and screen sharing, and it hides the evidence you wanted.

Does a WebRTC leak happen on Android?

It can, as the API is the same, but we did not run Android for this post.

Sources

  1. W3C: WebRTC 1.0, Real-Time Communication Between Browsers (read October 29, 2026)
  2. RFC 8445: Interactive Connectivity Establishment (ICE) (read October 29, 2026)
  3. RFC 8489: Session Traversal Utilities for NAT (STUN) (read October 29, 2026)
  4. IETF draft: Using Multicast DNS to protect privacy when exposing ICE candidates (read October 29, 2026)
  5. MDN: Lifetime of a WebRTC session (connectivity) (read October 29, 2026)
  6. MDN: RTCIceCandidate type (read October 29, 2026)
  7. Chrome for Developers: chrome.privacy API (webRTCIPHandlingPolicy) (read October 29, 2026)
  8. browserleaks.com: WebRTC leak test (read October 29, 2026)
  9. dnsleaktest.com: WebRTC leak test (read October 29, 2026)

How this was made

Drafted with AI assistance from the cited standards and vendor documentation, ForestVPN's feature pages and our own lab run of the published Linux client on 2026-10-29, then checked by automated gates and an editor.

All posts

Back to top

Ask us anything