Proxies & geo

Capium runs locally, so it uses your egress by default. Point a session at any proxy you control, and let geoip align the network-facing surfaces to that exit.

Use a proxy

Pass a proxy URL to proxy=. Credentials in the userinfo are handed to the binary, which parses them itself (preemptive HTTP Proxy-Authorization), avoiding Playwright's CDP proxy-auth path. The canonical form is scheme://user:pass@host:port.

proxy.py
from capium import launch_context

# HTTP/HTTPS with inline credentials.
browser, ctx, page = launch_context(
    seed=200123, platform="linux",
    proxy="http://user:pass@host:port",
    url="https://example.com",
)

SOCKS5

SOCKS5 is supported natively, with or without authentication. Authenticated SOCKS5 uses the RFC 1929 username/password handshake, and geoip works over it just like HTTP.

socks5.py
# SOCKS5, with or without auth. Credentials use RFC 1929 in the
# handshake; geoip works over SOCKS5 too.
launch_context(seed=200123, proxy="socks5://user:pass@host:port")
launch_context(seed=200123, proxy="socks5://host:port")            # no auth

Align geo with geoip

A proxy exit in one country with a timezone and WebRTC IP from another is a tell. geoip=True resolves the exit and pins the WebRTC IP, in-browser timezone, language and geolocation coordinates to match. This is the coherence engine, keep it on whenever you route through a proxy.

geoip.py
# geoip pins the WebRTC IP, timezone and geolocation to the proxy exit,
# so the whole identity tells one coherent story.
browser, ctx, page = launch_context(
    seed=200123, platform="linux",
    proxy="http://user:pass@host:port",
    geoip=True,
    url="https://example.com",
)

Verify there are no leaks

Before you trust a session, confirm the network-facing surfaces agree. The WebRTC IP should equal your exit, and the timezone should match the exit's region rather than your host.

leak_check.py
# Verify nothing leaks: the WebRTC IP should equal the exit, and the
# timezone should match the exit's region (not your host's).
browser, ctx, page = launch_context(seed=200123, proxy="http://user:pass@host:port",
                                    geoip=True, url="https://browserleaks.com/webrtc")
print(page.evaluate("() => Intl.DateTimeFormat().resolvedOptions().timeZone"))
browser.close()

Fine control

You can also set these by hand with --fingerprint-webrtc-ip, --timezone, locale= and --fingerprint-location. Use a persistent context with a stable seed and a sticky proxy to keep one account's identity consistent across runs, see Async & persistent sessions and the parameter reference.