ProxyHat residential proxies for nodriver (undetected Chrome) — CDP proxy auth, sticky sessions, geo-targeting, rotation.
Project description
nodriver-proxyhat
Route nodriver — the successor to undetected-chromedriver — through ProxyHat residential proxies. Authenticated gateway proxies wired straight into nodriver over CDP, plus a sticky residential IP pinned for the whole session, geo-targeting, and rotation.
Why
Chrome's --proxy-server flag can't carry a username and password, so pointing an undetected browser at a credentialed residential gateway normally means a manual CDP dance. And running a real browser from a datacenter IP gets flagged, CAPTCHA-walled, and blocked anyway — exactly what you're using nodriver to avoid.
nodriver-proxyhat fixes both. It plugs ProxyHat's residential IPs (50M+ across 148+ countries) into nodriver and handles gateway auth the CDP way nodriver is built for: it enables the Fetch domain and answers the proxy's Fetch.authRequired challenge with your credentials. One pinned residential IP per session by default, so cookies and fingerprint stay consistent while your script works.
Install
pip install nodriver-proxyhat nodriver
nodriver is a peer dependency — bring your own version (and its Chrome). The proxyhat_browser_args() / proxyhat_auth() helpers work without it; proxyhat_browser() needs nodriver installed.
Quick start
import nodriver as uc
from nodriver_proxyhat import proxyhat_browser
async def main():
# An API key (PROXYHAT_API_KEY) auto-selects an active residential sub-user:
browser = await proxyhat_browser(country="us") # sticky US IP for the whole session
page = await browser.get("https://httpbin.org/ip")
print(await page.get_content())
browser.stop()
uc.loop().run_until_complete(main())
Get an API key at proxyhat.com.
proxyhat_browser(...) calls nodriver.start(...) for you and forwards any extra keyword arguments (headless, user_data_dir, browser_args, …) unchanged.
Credentials
Pass them explicitly or via environment variables — options win over env:
| Option | Env var | Notes |
|---|---|---|
api_key |
PROXYHAT_API_KEY |
Auto-selects an active sub-user with remaining traffic |
sub_user |
PROXYHAT_SUBUSER |
Pick a specific sub-user by uuid or name (with an API key) |
username |
PROXYHAT_USERNAME |
Explicit gateway proxy_username (skips the API) |
password |
PROXYHAT_PASSWORD |
Explicit gateway proxy_password |
Targeting
await proxyhat_browser(
country="us", # ISO code or "any" (default)
region="california",
city="new_york",
filter="high", # AI IP-quality tier
sticky="30m", # session lifetime (default); sticky=False rotates every request
headless=True, # any extra kwarg is forwarded to nodriver.start
)
The same targeting keyword arguments work on proxyhat_auth(...).
Sticky IP per session (default)
A browser session takes many steps against the same site — logging in, clicking, scrolling. If the exit IP changed mid-session the site would see a user teleporting between cities and block it. So this package is sticky by default: one residential IP is pinned for the whole session (sticky="30m", renewed as you work), keeping cookies and fingerprint coherent.
Want a fresh IP on every request instead (e.g. many independent one-shot fetches)? Turn stickiness off:
await proxyhat_browser(country="us", sticky=False) # rotating residential IP per connection
Set a custom lifetime with sticky="2h".
How authentication works
nodriver takes the proxy host/port from --proxy-server=gate.proxyhat.com:8080, but a residential gateway also needs a username (the ProxyHat targeting string) and password. Since the flag can't carry them, proxyhat_browser uses nodriver's raw Chrome DevTools Protocol access instead:
- it enables the Fetch domain on the main tab with
handle_auth_requests=True; - it registers a
Fetch.authRequiredhandler that answers with your targeting username + sub-user password viaFetch.continueWithAuth(ProvideCredentials); - it resumes every other paused request with
Fetch.continueRequest(enabling Fetch pauses all requests, so non-auth ones must be continued too).
The targeting username (e.g. <user>-country-us-sid-<id>-ttl-30m) is built by the official proxyhat SDK, so a sticky session mints a single session id shared across the run.
This is the HTTP gateway (port 8080) — CDP proxy auth answers the HTTP proxy's basic-auth challenge.
Wiring it yourself
Prefer to drive nodriver.start() your way? Grab the launch flag and the resolved credentials and wire the CDP handler yourself:
import nodriver as uc
from nodriver import cdp
from nodriver_proxyhat import proxyhat_auth, proxyhat_browser_args, enable_proxy_auth
async def main():
username, password = proxyhat_auth(country="de", sticky="1h")
browser = await uc.start(browser_args=proxyhat_browser_args() + ["--headless=new"])
# enable_proxy_auth does the Fetch.enable + authRequired dance for you:
await enable_proxy_auth(browser.main_tab, username, password)
page = await browser.get("https://httpbin.org/ip")
print(await page.get_content())
browser.stop()
uc.loop().run_until_complete(main())
proxyhat_browser_args() returns ["--proxy-server=gate.proxyhat.com:8080"]; proxyhat_auth() returns the (username, password) for a Fetch.authRequired handler.
License
MIT © ProxyHat
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nodriver_proxyhat-0.1.0.tar.gz.
File metadata
- Download URL: nodriver_proxyhat-0.1.0.tar.gz
- Upload date:
- Size: 12.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cb11170119595d979787ea06d78ae57e7a2ba662a833b7f92ba736fb004bdbf
|
|
| MD5 |
c0cec3b9ccf201f337173cc41c98249e
|
|
| BLAKE2b-256 |
80e40642115dbce103467c1a455bb0418d93ae42d92854e7b49942c355d734dc
|
Provenance
The following attestation bundles were made for nodriver_proxyhat-0.1.0.tar.gz:
Publisher:
ci.yml on ProxyHatCom/nodriver-proxyhat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nodriver_proxyhat-0.1.0.tar.gz -
Subject digest:
6cb11170119595d979787ea06d78ae57e7a2ba662a833b7f92ba736fb004bdbf - Sigstore transparency entry: 2165372732
- Sigstore integration time:
-
Permalink:
ProxyHatCom/nodriver-proxyhat@e4b974b40bf817c383fa39b6d37e97d44e48be8c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ProxyHatCom
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@e4b974b40bf817c383fa39b6d37e97d44e48be8c -
Trigger Event:
push
-
Statement type:
File details
Details for the file nodriver_proxyhat-0.1.0-py3-none-any.whl.
File metadata
- Download URL: nodriver_proxyhat-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4a475cf4b442d78c267a4d72eaf241ac4916300214565380b67eb6a16d0429a
|
|
| MD5 |
dfb2572cd78b9f50fc412d3bb6e6c123
|
|
| BLAKE2b-256 |
972d82379f04be23f22f24f78f5058c56729c8da0c1b0010e604b9be48926993
|
Provenance
The following attestation bundles were made for nodriver_proxyhat-0.1.0-py3-none-any.whl:
Publisher:
ci.yml on ProxyHatCom/nodriver-proxyhat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nodriver_proxyhat-0.1.0-py3-none-any.whl -
Subject digest:
c4a475cf4b442d78c267a4d72eaf241ac4916300214565380b67eb6a16d0429a - Sigstore transparency entry: 2165372749
- Sigstore integration time:
-
Permalink:
ProxyHatCom/nodriver-proxyhat@e4b974b40bf817c383fa39b6d37e97d44e48be8c -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ProxyHatCom
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@e4b974b40bf817c383fa39b6d37e97d44e48be8c -
Trigger Event:
push
-
Statement type: