Your VPN says you're anonymous. Your browser says otherwise.
WebRTC (Web Real-Time Communication) enables seamless video calls and peer-to-peer communication right in your browser—no plugins required. The problem? It can bypass your VPN and leak your real IP address to any website you visit. Even with a premium VPN running, a simple JavaScript command can expose your actual location through WebRTC's STUN server requests.
In this guide, I'll show you exactly how WebRTC leaks work under the hood, how to test if you're vulnerable, and most importantly—how to lock down your browser across Chrome, Firefox, Safari, and other major browsers. We'll also build a custom leak detection tool so you understand exactly what's happening behind the scenes.
What Is a WebRTC Leak?
WebRTC leaks happen when your browser reveals your real IP address through WebRTC functionality, even while connected to a VPN or proxy. This occurs because WebRTC needs to exchange IP addresses directly between peers to establish connections—it's not a bug, it's how the protocol works.
Here's the technical breakdown: When you join a video call or visit a WebRTC-enabled site, your browser queries STUN (Session Traversal Utilities for NAT) servers to discover your public IP address and local network interfaces. These requests happen outside the normal HTTP stack, which means they bypass most VPN tunnels and don't show up in your browser's developer console.
The real kicker? These STUN requests are accessible to JavaScript. Any website can run a few lines of code to enumerate your network interfaces and collect both your local IP addresses (like 192.168.1.x) and your public IP address—the one your ISP assigned you.
// This is essentially what websites use to detect your IPs
function detectIPs() {
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
pc.createDataChannel('');
pc.createOffer()
.then(offer => pc.setLocalDescription(offer));
pc.onicecandidate = (ice) => {
if (!ice || !ice.candidate) return;
const candidate = ice.candidate.candidate;
console.log('IP detected:', candidate);
};
}
When this code runs, it creates a peer connection and starts gathering ICE (Interactive Connectivity Establishment) candidates. Each candidate contains an IP address—your local IPs, your public IP, and if you're on a VPN, potentially both your VPN IP and your real ISP-assigned IP.
Why WebRTC Leaks Matter
The severity depends on your threat model. If you're using a VPN to access region-locked content, a WebRTC leak completely defeats the purpose. The streaming service can see your real location. For privacy-conscious users, it's worse—advertisers and trackers can correlate your real identity across VPN sessions.
There are two types of WebRTC leaks:
Persistent vanilla leaks: These happen even before you grant camera or microphone permissions. Any website can extract your IP addresses using just JavaScript. This is the severe type—you're exposed the moment you load a page.
Permission-based leaks: These occur only after you grant a website access to your camera or microphone. Less severe, but still problematic if you're trying to maintain anonymity.
Most modern browsers (Chrome, Firefox, Edge, Opera) are vulnerable to persistent leaks because they enable WebRTC by default. Safari is slightly better—it requires permission before exposing IPs—but it's not immune.
Testing for WebRTC Leaks
Before fixing anything, you need to know if you're leaking. Here's a reliable test:
- Disconnect your VPN and note your real IP address (Google "what is my IP")
- Connect to your VPN and verify it's working (check your IP again—it should be different)
- Visit a WebRTC leak test site like
browserleaks.com/webrtc
oripleak.net
- If you see your original ISP-assigned IP address in the results, you have a leak
The test works by running the JavaScript code I showed earlier. It creates a peer connection, collects ICE candidates, and displays all discovered IP addresses. If your real IP shows up alongside (or instead of) your VPN's IP, the leak is confirmed.
You can also build your own leak detector. Here's a more complete implementation:
async function checkWebRTCLeak() {
const ips = new Set();
const pc = new RTCPeerConnection({
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun1.l.google.com:19302' }
]
});
// Create a dummy data channel to trigger ICE gathering
pc.createDataChannel('leak-test');
// Create an offer to start gathering candidates
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// Listen for ICE candidates
pc.onicecandidate = (event) => {
if (!event || !event.candidate) {
// Gathering complete
displayResults(ips);
pc.close();
return;
}
const candidate = event.candidate.candidate;
const ipMatch = candidate.match(/(\d{1,3}\.){3}\d{1,3}/);
if (ipMatch) {
ips.add(ipMatch[0]);
}
};
// Set a timeout in case ICE gathering stalls
setTimeout(() => {
displayResults(ips);
pc.close();
}, 3000);
}
function displayResults(ips) {
console.log('Detected IP addresses:');
ips.forEach(ip => {
const isLocal = ip.startsWith('192.168.') ||
ip.startsWith('10.') ||
ip.startsWith('172.');
console.log(`${ip} ${isLocal ? '(local)' : '(public)'}`);
});
}
This script enumerates all IP addresses WebRTC can discover. Local addresses (192.168.x.x, 10.x.x.x) aren't a privacy concern—they're not routable on the internet. Public IP addresses are the problem.
Browser-Specific Prevention Methods
Different browsers handle WebRTC differently. Here's how to lock down each one.
Firefox
Firefox gives you the most control. You can completely disable WebRTC at the protocol level:
- Type
about:config
in the address bar and press Enter - Click "Accept the Risk and Continue" on the warning page
- Search for
media.peerconnection.enabled
- Double-click the preference to toggle it to
false
That's it. WebRTC is now completely disabled. No extensions, no workarounds—just pure browser-level blocking.
The trade-off? Sites that require WebRTC (like Google Meet, Discord, or Zoom web clients) will stop working. For most people, this is too aggressive. A better approach is to use Firefox's built-in privacy settings:
media.peerconnection.ice.default_address_only = true
media.peerconnection.ice.no_host = true
Set both of these to true
in about:config
. This prevents WebRTC from enumerating all your network interfaces while keeping the functionality alive. Websites will only see your default public IP (which should be your VPN's IP if you're connected).
Chrome and Chromium-based Browsers
Chrome doesn't have a built-in way to disable WebRTC. You need an extension. The official solution is Google's own "WebRTC Network Limiter," but it has limitations.
Better options include:
WebRTC Leak Prevent: This extension controls Chrome's hidden webRTCIPHandlingPolicy
setting. Install it from the Chrome Web Store, then configure it based on your setup:
- If you're using a system-level VPN: Set policy to "Use the default public interface only" (default)
- If you're using a browser extension VPN or proxy: Set policy to "Disable non-proxied UDP"
The extension works by modifying Chrome's privacy API:
// This is what the extension does under the hood
chrome.privacy.network.webRTCIPHandlingPolicy.set({
value: 'disable_non_proxied_udp'
});
This forces WebRTC to route all traffic through your proxy or VPN. If no proxy is configured, WebRTC effectively stops working.
uBlock Origin: The popular ad blocker also includes WebRTC leak prevention. Go to Settings → Privacy → Enable "Prevent WebRTC from leaking local IP addresses." This blocks ICE candidate gathering by shimming the WebRTC API.
Safari
Safari handles WebRTC more securely than other browsers. By default, it doesn't expose your IP addresses to websites without permission. However, once you grant camera or microphone access, the leak potential exists.
To disable WebRTC in Safari (macOS only):
- Open Safari and go to Preferences
- Click the "Advanced" tab
- Enable "Show Develop menu in menu bar"
- Go to Develop → Experimental Features
- Uncheck "Enable WebRTC mDNS ICE candidates"
On iOS, Apple removed the WebRTC disable option in iOS 12+. Your only option is using a VPN that specifically advertises WebRTC leak protection, like NordVPN or ExpressVPN.
Edge
Microsoft Edge (Chromium-based) is similar to Chrome. Use the same WebRTC Leak Prevent extension from the Microsoft Store.
For legacy Edge (pre-Chromium), there's a built-in setting:
- Type
about:flags
in the address bar - Scroll to "Hide my local IP address over WebRTC connections"
- Toggle it on
Opera
Opera has native support for WebRTC leak prevention:
- Go to Settings → Privacy & Security
- Scroll to the "WebRTC" section
- Select "Disable non-proxied UDP"
This forces WebRTC to route through proxies only, effectively blocking leaks for VPN users.
Advanced: VPN-Level Protection
The most foolproof solution? Choose a VPN that handles WebRTC leaks at the network level.
Quality VPNs like NordVPN, ExpressVPN, and Surfshark route WebRTC traffic through their encrypted tunnels, ensuring your real IP never escapes. Their browser extensions can also forcibly disable WebRTC when activated.
Here's what to look for in a VPN:
- Advertised WebRTC protection: Check if they explicitly mention WebRTC leak prevention
- Browser extensions: Desktop apps often miss WebRTC traffic; browser extensions have better control
- Firewall rules: Some VPNs install firewall rules that block all non-VPN traffic, including WebRTC
Test any VPN after connecting. Just because they claim protection doesn't mean they deliver it.
Building Custom Protection (Advanced)
If you're building a web app and want to prevent your users from accidentally leaking IPs, you can't disable WebRTC for them—but you can detect when it's being used maliciously.
Here's a Content Security Policy (CSP) approach to limit WebRTC:
<meta http-equiv="Content-Security-Policy"
content="connect-src 'self' https://yourapp.com">
This CSP directive restricts WebRTC connections to only your domain. It won't prevent leaks entirely, but it stops third-party scripts from establishing peer connections to external STUN servers.
For more aggressive blocking, you can monkey-patch the WebRTC API:
// Disable WebRTC entirely on your page
(function() {
if (window.RTCPeerConnection) {
window.RTCPeerConnection = undefined;
}
if (window.mozRTCPeerConnection) {
window.mozRTCPeerConnection = undefined;
}
if (window.webkitRTCPeerConnection) {
window.webkitRTCPeerConnection = undefined;
}
})();
This immediately disables WebRTC for any scripts running on your page. It's a nuclear option—legitimate WebRTC features (like video calls) will break—but it's effective.
A middle-ground approach is to intercept and log WebRTC usage:
// Shim the WebRTC API to monitor usage
const OriginalRTCPeerConnection = window.RTCPeerConnection;
window.RTCPeerConnection = function(config) {
console.warn('WebRTC connection attempted with config:', config);
// Optionally block connections to unknown STUN servers
if (config && config.iceServers) {
config.iceServers = config.iceServers.filter(server => {
const url = server.urls || server.url;
// Only allow your trusted STUN servers
return url.includes('yourtrustedserver.com');
});
}
return new OriginalRTCPeerConnection(config);
};
This approach lets you whitelist trusted STUN servers while blocking potentially malicious ones.
The Enterprise Approach
For organizations managing hundreds of browsers, manual configuration doesn't scale. You need group policies.
Chrome/Chromium enterprise policy:
{
"WebRTCIPHandlingPolicy": "default_public_interface_only"
}
Deploy this via Group Policy (Windows) or configuration profiles (macOS):
Windows: Computer Configuration → Policies → Administrative Templates → Google → Google Chrome → WebRTC
macOS: Deploy a configuration profile with the policy key
For Firefox in enterprise:
// policies.json
{
"policies": {
"Permissions": {
"Microphone": {
"BlockNewRequests": true
},
"Camera": {
"BlockNewRequests": true
}
}
}
}
Place this in /etc/firefox/policies/
(Linux) or the appropriate location for your OS.
What About Mobile?
Mobile browsers are trickier. iOS Safari can't disable WebRTC in newer versions, and Chrome on Android doesn't support extensions.
Your options:
Android: Install Firefox and disable WebRTC using about:config
(same steps as desktop). Or use a VPN app with built-in WebRTC protection.
iOS: Use a VPN that routes WebRTC traffic through its tunnel. Browser-level protection isn't possible.
Some antidetect browsers like AdsPower offer mobile solutions with WebRTC spoofing, but these are specialized tools aimed at multi-account management rather than everyday browsing.
Testing Your Protection
After implementing any fix, verify it works:
- Connect to your VPN
- Visit
browserleaks.com/webrtc
- Check the "Public IP Address" section
You should see:
- Your VPN's IP address (good)
- No IP addresses at all (also good—WebRTC is blocked)
You should NOT see:
- Your real ISP-assigned IP address (leak confirmed)
- Both your VPN IP and real IP (leak confirmed)
Local IP addresses (192.168.x.x, 10.x.x.x, 172.16-31.x.x) appearing is normal and not a privacy concern.
The Reality of WebRTC Leaks in 2025
Here's the truth: there's no perfect solution. You can disable WebRTC entirely and break half the web, or you can accept some level of exposure when using WebRTC features.
The best approach is layered:
- Use a VPN with WebRTC protection: This catches most leaks automatically
- Install a browser extension: Adds an extra layer for browser-level blocking
- Adjust browser settings: Disable WebRTC if you don't use video calling
- Test regularly: Browser updates can reset settings or introduce new vulnerabilities
WebRTC leaks were first publicly disclosed in 2015, and they're still a problem in 2025. Browser vendors haven't fully addressed it because WebRTC's peer-to-peer nature requires IP exchange—you can't have true P2P communication without revealing some networking information.
The fundamental issue is that WebRTC prioritizes connectivity over privacy. It's designed to establish connections even in restrictive network environments, which means it tries every possible path—including revealing your real IP.
Until browsers implement better privacy controls by default (like Safari's permission-based approach), WebRTC leaks will remain a persistent threat. The good news? Now you know how to defend against them.
Wrapping Up
WebRTC leaks expose your real IP address even when using a VPN. They happen because WebRTC's peer-to-peer architecture requires IP address exchange, and these requests bypass normal network security.
The fix depends on your browser: Firefox users can disable it entirely via about:config
, Chrome users need extensions like WebRTC Leak Prevent, and Safari users should rely on VPN-level protection. Mobile users have limited options—Firefox on Android works, but iOS is locked down.
Test your protection regularly at browserleaks.com/webrtc. If you see your real IP while connected to a VPN, you're leaking.
The most robust solution is combining a VPN that handles WebRTC traffic (like NordVPN or ExpressVPN) with browser-level blocking via extensions or settings. Defense in depth matters—one layer might fail, but multiple layers keep you protected.
Remember: WebRTC isn't inherently bad. It powers video calls, screen sharing, and real-time collaboration. The problem is that most browsers enable it by default without adequate privacy safeguards. Take control of your browser's WebRTC settings, and you'll close a significant privacy hole that most users don't even know exists.