fix(python): send an IPv6 WebRTC address to setWebRTCIPv6

The per-context init script passed every webrtc_ip, IPv6 included, to
window.setWebRTCIPv4(), and never called setWebRTCIPv6(). An IPv6 address
(given directly, or resolved as a proxy's exit IP) was stored as the
context's IPv4 value and the IPv6 slot stayed empty. The script now picks
the setter by address family, and an address that is neither raises
InvalidIP instead of being passed through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jake Writer
2026-09-25 20:34:17 -06:00
co-authored by Claude Opus 5.5
parent 46e5c8d1a4
commit 0bbd15246f
5 changed files with 30 additions and 4 deletions
+1 -1
View File
@@ -204,7 +204,7 @@ async def AsyncNewContext(
preset: A fingerprint preset dict to use. If None, fpgen draws a new identity.
os: Target OS for the drawn identity ("windows", "macos", "linux").
ff_version: Firefox major version to claim in the UA. Defaults to the browser's own.
webrtc_ip: IPv4 address to spoof for WebRTC ICE candidates.
webrtc_ip: IPv4 or IPv6 address to spoof for WebRTC ICE candidates.
proxy: Per-context proxy (Playwright format: {"server": "...", "username": "...", "password": "..."}).
Unless webrtc_ip and timezone_id are both given, they are looked up from the
proxy's exit IP; InvalidIP is raised if that lookup fails.
+4 -1
View File
@@ -11,6 +11,7 @@ from random import Random, choice, randint, randrange
from typing import Any, Dict, FrozenSet, List, Optional, Set, Tuple
from camoufox._warnings import FallbackWarning
from camoufox.ip import valid_ipv4, validate_ip
from camoufox.pkgman import load_yaml
from camoufox.webgl import sample_webgl
@@ -1759,8 +1760,10 @@ def _build_init_script(values: Dict[str, Any]) -> str:
# WebRTC IP
ip = values.get('webrtcIP')
if ip:
validate_ip(ip)
fn_name = 'setWebRTCIPv4' if valid_ipv4(ip) else 'setWebRTCIPv6'
lines.append(
f' if (typeof w.setWebRTCIPv4 === "function") w.setWebRTCIPv4({_json.dumps(ip)});'
f' if (typeof w.{fn_name} === "function") w.{fn_name}({_json.dumps(ip)});'
)
else:
lines.append(
+1 -1
View File
@@ -182,7 +182,7 @@ def NewContext(
preset: A fingerprint preset dict to use. If None, fpgen draws a new identity.
os: Target OS for the drawn identity ("windows", "macos", "linux").
ff_version: Firefox major version to claim in the UA. Defaults to the browser's own.
webrtc_ip: IPv4 address to spoof for WebRTC ICE candidates.
webrtc_ip: IPv4 or IPv6 address to spoof for WebRTC ICE candidates.
proxy: Per-context proxy (Playwright format: {"server": "...", "username": "...", "password": "..."}).
Unless webrtc_ip and timezone_id are both given, they are looked up from the
proxy's exit IP; InvalidIP is raised if that lookup fails.
+23
View File
@@ -0,0 +1,23 @@
"""The per-context init script hands a WebRTC IP to the setter for its family."""
import pytest
from camoufox.exceptions import InvalidIP
from camoufox.fingerprints import _build_init_script
def test_ipv4_goes_to_the_ipv4_setter():
script = _build_init_script({"webrtcIP": "203.0.113.7"})
assert 'w.setWebRTCIPv4("203.0.113.7")' in script
assert "setWebRTCIPv6(" not in script
def test_ipv6_goes_to_the_ipv6_setter():
script = _build_init_script({"webrtcIP": "2001:db8::7"})
assert 'w.setWebRTCIPv6("2001:db8::7")' in script
assert "2001:db8::7" not in script.split("setWebRTCIPv6")[0]
def test_an_invalid_address_is_refused():
with pytest.raises(InvalidIP):
_build_init_script({"webrtcIP": "not-an-ip"})