Camoufox takes a proxy as Playwright's proxy dict, with server, username and password. What it adds is geoip=True: it looks up the proxy's exit IP and sets the browser's location, timezone, locale and WebRTC address to match. That lookup runs once per proxy URL for the whole Python process. So geoip only stays right while the browser keeps the IP that was looked up: one sticky line per browser, never a rotating one. We read every setting on this page in Camoufox's Python library 0.5.6, released on 6 September 2026, and in Playwright 1.62, which it runs on.
Why would Camoufox need a proxy?
Camoufox changes the browser's fingerprint, not its address. On a server, every site still sees a hosting IP. We tested what the address alone changes, on 19 September 2026: plain requests to thirteen sites, twice from our server and twice through a residential line. A residential IP changed the answer at four of them: Zillow, Instagram, Reddit and DuckDuckGo. Indeed, Glassdoor, Amazon and Booking refused both. That test sent plain requests, not a browser. The table per site is on our OpenClaw page.
A proxy brings its own risk. A browser whose clock says New York while its IP sits in Frankfurt does not look like a real visitor. Camoufox's own warning says a geolocation that does not match the IP "can lead to detection", and geoip exists to prevent it.
How do I give Camoufox a proxy?
Install the geoip extra first, which adds a GeoIP database of 40.7 MB:
pip install -U "camoufox[geoip]"
Then pass the proxy as a dict, with the login in its own keys:
from camoufox.sync_api import Camoufox
with Camoufox(
proxy={
"server": "http://GATEWAY_HOST:GATEWAY_PORT",
"username": "USERNAME",
"password": "PASSWORD",
},
geoip=True,
) as browser:
page = browser.new_page()
page.goto("https://example.com")
Camoufox hands the dict to Playwright unchanged, so Playwright's rules decide what works:
| You pass | What happens |
|---|---|
http:// server with username and password keys | works |
http://user:pass@host:port as the server | the login is dropped |
socks5://host:port without a login | works |
socks5:// with a username or password | refused |
socks://host:port | sent to Firefox as an HTTP proxy |
The refusal reads "Browser does not support socks5 proxy authentication". Playwright only tells Firefox a proxy is SOCKS when the server starts with socks5://, so write that, not socks://. For a line with a login, use its HTTP address.
A proxy without geoip raises a LeakWarning: "When using a proxy, it is heavily recommended that you pass geoip=True". Camoufox's code notes that i_know_what_im_doing cannot silence this one.
What does geoip=True do with the proxy?
Three steps, before the browser starts:
- It sends a request through the proxy to a public IP service: api.ipify.org first, then five fallbacks.
- It looks that IP up in its GeoIP database.
- It sets longitude, latitude, timezone, country and locale, and the WebRTC address unless WebRTC is blocked.
The catch sits in step 1. The answer is cached for the life of the Python process, keyed by the proxy URL. A rotating line keeps the same URL while its exit IP changes, so every later request comes from IPs the lookup never saw. Pinning one country does not fix that for a country with several timezones.
Three more details decide the result:
- A manual timezone wins. Since the Firefox 152 builds, a
timezoneor locale you set inconfigis kept, and geoip only fills in what is missing. - The database decides, not the label. geoip reads the IP's location from its own data, and a site may use other data. In one report geoip set "America/Chicago" while a checker placed the same IP in "America/Phoenix". In another, a line sold as Thailand turned out to be, in a contributor's words, "a Lithuanian IP with a fake geolocation record".
- A failed lookup stops the launch. If none of the six services answers through the proxy, Camoufox raises
InvalidIP: Failed to get IP address. Pass the exit IP yourself, asgeoip="203.0.113.7", to skip the lookup.
What about WebRTC?
WebRTC can reveal an address behind the proxy. With geoip on, Camoufox writes the proxy's IP into WebRTC instead. A leak of the real IP behind a proxy on Firefox 146 builds was fixed in July 2026, in browser release v152.0.4-beta.26 and Python library 0.5.3, so update if you run anything older. block_webrtc=True switches WebRTC off entirely, but one user reports that a browser with WebRTC blocked gets flagged on many platforms. A related WebRTC issue is still open, reported on 13 September 2026.
Which proxy type fits Camoufox?
Residential, sticky, one line per browser. The line should hold its IP for longer than the browser runs, so the lookup and every page see the same address. When a browser ends, start the next one on a new line: a new URL gets a new lookup. block_images=True saves traffic, which Camoufox's docs say "can help save your proxy usage".
HProxy residential gateways fit this pattern. Generate sticky lines with the plan API: each line gets its own session, and Residential Premium and Plus hold the IP for the duration you ask for. A sticky IP can still change early if its device leaves the network, so restart that browser on a fresh line. On a server with a fixed IP you can also allow that IP on a Residential Premium plan, up to 150 per plan, and use a sticky port with no password in the dict. An allowed IP takes no country or city targeting. The residential proxies page lists the plans.
What breaks when the proxy is on?
- "When using a proxy, it is heavily recommended that you pass geoip=True". Install the geoip extra and pass
geoip=True. - "Please install the geoip extra to use this feature". Run
pip install camoufox[geoip]. - "Failed to get IP address". The lookup got no answer through the proxy. Check the login and the line, or pass the exit IP as
geoip. - 407 Proxy Authentication Required. The login sits inside the server value, or it is wrong. On our gateways a 407 means a wrong password or a line from another plan. Our 407 guide walks through it.
- "Browser does not support socks5 proxy authentication". Use the HTTP line.
- A SOCKS proxy does nothing. The server says
socks://. Writesocks5://. - A timezone check fails. You run a rotating line, or the IP's location records disagree. Give each browser one sticky line.
- A WebRTC test shows your own IP. Update to a July 2026 build or newer.
What this page does not cover
We read Camoufox's Python library 0.5.6, its docs and Playwright 1.62. We did not run Camoufox. The browser's own C++ patches we know only from the issue threads. The blocking test used plain requests from one server IP and one residential line, over one afternoon. How often a rotating line's timezone differs from the cached lookup depends on the pool, so we give the mechanism, not a rate. Camoufox ships a browser beta every few weeks, so we will read these settings again by 19 October 2026.
Where to go from here
Proxies for Scrapling covers a scraping framework that used Camoufox as its engine until version 0.3.13. Proxies for Playwright MCP explains the Playwright proxy rules in more depth. Sticky vs rotating sessions explains the choice above, and how websites detect proxies covers the checks a timezone mismatch trips.
Sources
- The Python library README, launch options (utils.py), the public IP lookup (ip.py), warnings.yml, geolocation.py and pyproject.toml. daijro/camoufox, tag v152.0.4-beta.31 (Python library 0.5.6), 6 September 2026.
- GeoIP & Proxy Support, and Usage. Camoufox documentation, camoufox.com, read 19 September 2026.
- normalizeProxySettings and the Firefox proxy options. Playwright source code, release v1.62.0.
- Issues #538, #589, #676, #774, #368, #57, #42 and #5. Camoufox issue tracker, 2024 to 2026.
- Plans, IP whitelist and sticky sessions; errors; the proxy API. HProxy documentation, hproxy.com/docs, 19 September 2026.
- Our own test of 19 September 2026: plain GET requests to 13 sites and 3 controls, two runs from our server and two through a residential line of our own house plan, with curl 8.5.0. Raw output is kept in the research folder of our OpenClaw page.


