WebRTC Leak Prevention
Prevent WebRTC IP leaks by controlling ICE behavior and candidate exposure under proxy usage.
Prerequisites
- BotBrowser binary with a valid profile loaded via
--bot-profile. - A proxy server configured via
--proxy-server(recommended for full protection).
Quick Start
BotBrowser provides WebRTC protection by default through SDP and ICE candidate control. For additional control over ICE server endpoints, use the --bot-webrtc-ice flag:
import { chromium } from "playwright-core";
const browser = await chromium.launch({
executablePath: process.env.BOTBROWSER_EXEC_PATH,
headless: true,
args: [
`--bot-profile=${process.env.BOT_PROFILE_PATH}`,
"--proxy-server=socks5://user:[email protected]:1080",
"--bot-webrtc-ice=google",
],
});
const page = await browser.newPage();
await page.goto("https://browserleaks.com/webrtc");
await browser.close();How It Works
How BotBrowser Protects Against WebRTC Leaks
WebRTC can expose your real IP addresses even when using a proxy. BotBrowser prevents this at the browser engine level.
BotBrowser implements protection at the browser engine level:
SDP Control. SDP offers and answers present consistent IPv4 and IPv6 address information matching your configured identity.
ICE Candidate Control. ICE candidates present a consistent network topology. Local IP addresses are not exposed through RTCPeerConnection events.
When a proxy cannot carry datagrams, the default mode keeps unproxied traffic from leaving the host and presents the proxy address in candidate data. Use --bot-webrtc=real only when direct traffic is intended. This behavior is verified on BotBrowser 156; other release lines carry the same source change but were not compiled for this verification.
Why no loopback (127.0.0.1 / ::1) candidates appear
You cannot disable loopback candidates with a flag, because BotBrowser never emits them to page JavaScript. Stock Chromium gathers a host candidate for every local interface, and that list includes loopback when ICE gathering runs without a proxy or with iceTransportPolicy: "all". BotBrowser generates the candidate list from the profile’s network identity instead: host candidates carry the declared proxy addresses, and loopback, link-local, and private interface addresses are not part of that list. Chrome’s mDNS candidate obfuscation (<uuid>.local) plays no role here, because there is no local address left to obfuscate.
Verify it from page JavaScript by gathering candidates on a page that is already behind the proxy:
const pc = new RTCPeerConnection({ iceServers: [] });
pc.createDataChannel("probe");
const seen = new Set();
pc.onicecandidate = e => {
if (!e.candidate) return;
seen.add(e.candidate.candidate);
};
await pc.setLocalDescription(await pc.createOffer());
await new Promise(r => setTimeout(r, 3000));
console.log([...seen].join("\n"));
console.log("loopback leaked:", /(^| )127\.\d+\.\d+\.\d+|(^| )::1( |$)/.test([...seen].join(" ")));If loopback leaked prints true, the page is not running with the proxy you expect. Socket-level scan probes are a separate concern and are covered by Port Protection.
STUN/TURN Consistency. STUN and TURN responses reflect your configured network identity. When combined with UDP-over-SOCKS5 (ENT Tier3), STUN probes themselves are tunneled through the proxy.
When a proxy has only one public address family, declare the unavailable family with --proxy-ip=ipv4_none,<ipv6> or --proxy-ip=<ipv4>,ipv6_none. This keeps WebRTC candidate handling aligned with the declared proxy identity.
ICE Server Control
The --bot-webrtc-ice flag (ENT Tier1) controls which STUN and TURN endpoints are visible to page JavaScript:
Presets:
# Use Google's public STUN servers (consistent with standard Chrome behavior)
--bot-webrtc-ice=googleCustom servers:
# Specify custom STUN and TURN servers
--bot-webrtc-ice="custom:stun:stun.example.com:19302,turn:turn.example.com:3478"Common Scenarios
Profile-based WebRTC configuration
Use the profile’s built-in WebRTC settings:
--bot-webrtc=profileThis applies the WebRTC configuration defined in your profile file, providing consistent behavior across sessions with the same profile.
Disabling WebRTC entirely
If your use case does not require WebRTC, you can disable it:
--bot-webrtc=disabledThis prevents all WebRTC-related API calls from functioning, which eliminates any possibility of IP disclosure through this channel.
Per-context WebRTC configuration
Different BrowserContexts can have different WebRTC settings:
// Puppeteer
const client = await browser.target().createCDPSession();
// Context 1: WebRTC with Google STUN
const ctx1 = await browser.createBrowserContext();
await client.send("BotBrowser.setBrowserContextFlags", {
browserContextId: ctx1._contextId,
botbrowserFlags: [
"--bot-profile=path/to/profile.enc",
"--bot-webrtc-ice=google",
],
});
// Context 2: WebRTC disabled
const ctx2 = await browser.createBrowserContext();
await client.send("BotBrowser.setBrowserContextFlags", {
browserContextId: ctx2._contextId,
botbrowserFlags: [
"--bot-profile=path/to/profile.enc",
"--bot-webrtc=disabled",
],
});Combined with UDP-over-SOCKS5
With ENT Tier3, STUN probes are automatically tunneled through the SOCKS5 proxy when it supports UDP. This means ICE presets are often unnecessary because STUN responses already reflect the proxy’s IP:
# UDP (QUIC/STUN) auto-tunneled when the SOCKS5 proxy supports UDP associate
--proxy-server=socks5://user:[email protected]:1080See UDP over SOCKS5 for details.
Verifying WebRTC Protection
To verify protection is active, visit BrowserLeaks WebRTC test and confirm that only the proxy IP (or no IP) is visible, and no local or real IPs appear in the results.
Troubleshooting / FAQ
| Problem | Solution |
|---|---|
| Real IP appears in WebRTC test | Ensure proxy is set via --proxy-server, not framework options. Add --bot-webrtc-ice=google for ICE control. |
| WebRTC completely non-functional | Check if --bot-webrtc=disabled is set. Change to profile or real if WebRTC is needed. |
| ICE candidates show unexpected IPs | Use --bot-webrtc-ice=google (ENT Tier1) or a custom server list to control which STUN endpoints are queried. |
| STUN probes not going through proxy | STUN uses UDP. If your proxy does not support UDP, use --bot-webrtc-ice (ENT Tier1) to control ICE servers. UDP proxy tunneling itself is an ENT Tier3 capability. |
Next Steps
- DNS Leak Prevention. Prevent DNS queries from leaking outside the proxy tunnel.
- UDP over SOCKS5. Tunnel QUIC and STUN traffic through the proxy.
- Proxy Configuration. Basic proxy setup and supported protocols.
- Port Protection. Protect local service ports from being scanned.
- CLI Flags Reference. Complete list of all available flags.
Related documentation: Advanced Features: WebRTC Leak Protection | CLI Flags Reference
Legal Disclaimer & Terms of Use • Responsible Use Guidelines. BotBrowser is for authorized fingerprint protection and privacy research only.
Related BotBrowser blog: WebRTC network identity and privacy