Authenticated & rotating proxies for Chrome-based browser automation (Selenium, SeleniumBase, undetected-chromedriver, Playwright). Handles authenticated SOCKS5/SOCKS4 and HTTP/HTTPS proxies and proxy pools via a local relay.
Project description
selenium-proxy-tools
Authenticated & rotating proxies made easy for Chrome-based browser automation
— Selenium, SeleniumBase,
undetected-chromedriver,
Playwright, or plain requests.
Zero third-party dependencies. Standard library only.
Why?
Proxies are a constant source of pain in browser automation:
| Problem | Chrome / Selenium out of the box | With selenium-proxy-tools |
|---|---|---|
| Authenticated SOCKS5/SOCKS4 | ❌ impossible — Chrome can't auth SOCKS at all | ✅ |
| Authenticated HTTP/HTTPS | ⚠️ needs a hand-built MV3 extension per session | ✅ |
| Rotating pool / round-robin | ❌ roll your own | ✅ built in |
| DNS leaks | ⚠️ | ✅ remote DNS via SOCKS5 |
It works by running a tiny local, no-auth HTTP proxy on a background thread that forwards every connection through your real upstream proxy. You just point the browser at the local address — no flags, no extensions, no external tools.
Chrome ──▶ 127.0.0.1:<port> (local, no auth)
│
▼
your authenticated / rotating upstream proxy ──▶ the internet
Install
pip install selenium-proxy-tools
Quick start
SeleniumBase
from seleniumbase import SB
from selenium_proxy_tools import ProxyRelay
with ProxyRelay("socks5://user:pass@host:1080") as relay:
# relay.proxy -> "127.0.0.1:<port>" (exactly what SeleniumBase expects)
with SB(uc=True, proxy=relay.proxy) as sb:
sb.open("https://api.ipify.org?format=json")
print(sb.get_text("body"))
undetected-chromedriver / plain Selenium
import undetected_chromedriver as uc
from selenium_proxy_tools import ProxyRelay
# Works the same for an authenticated HTTP proxy: "http://user:pass@host:8080"
with ProxyRelay("socks5://user:pass@host:1080") as relay:
options = uc.ChromeOptions()
options.add_argument(f"--proxy-server={relay.url}") # http://127.0.0.1:<port>
driver = uc.Chrome(options=options)
driver.get("https://api.ipify.org?format=json")
print(driver.find_element("tag name", "body").text)
driver.quit()
Rotating pool
from selenium_proxy_tools import ProxyRelay
pool = [
"socks5://user:pass@a.example.com:1080",
"http://user:pass@b.example.com:8080", # mix schemes freely
"socks5://user:pass@c.example.com:1080",
]
with ProxyRelay(pool, rotation="roundrobin") as relay: # or rotation="random"
with SB(uc=True, proxy=relay.proxy) as sb:
... # each new connection exits through the next upstream
requests / verify the exit IP
import requests
from selenium_proxy_tools import ProxyRelay
with ProxyRelay("http://user:pass@host:8080") as relay:
print(requests.get("https://api.ipify.org", proxies={"https": relay.url}).text)
print("exit IP:", relay.exit_ip())
More runnable examples in examples/.
Supported upstreams
| Scheme | Auth | Notes |
|---|---|---|
socks5:// |
✅ user/pass (RFC 1929) | remote DNS (no leaks) |
socks4:// |
✅ userid | socks4a remote DNS |
http:// / https:// |
✅ Basic | CONNECT + absolute-form |
Accepted formats: scheme://user:pass@host:port, scheme://host:port,
host:port:user:pass (assumes SOCKS5), host:port.
API
ProxyRelay(upstream, listen_host="127.0.0.1", listen_port=0, rotation=None)
upstream is one proxy or a list of them. rotation is None, "roundrobin",
or "random".
| Member | Description |
|---|---|
.start(timeout=10.0) |
Start; blocks until bound. Returns self. |
.stop() |
Stop and release the local port. |
.proxy |
"127.0.0.1:<port>" — for SeleniumBase / uc proxy=. |
.url |
"http://127.0.0.1:<port>" — for --proxy-server=, requests, Playwright. |
.port |
The chosen local port (None until started). |
.exit_ip(timeout=20) |
The public IP currently seen through the relay. |
| context manager | with ProxyRelay(...) as relay: starts on enter, stops on exit. |
SocksProxyRelay is a backwards-compatible alias of ProxyRelay.
Also exported: parse_upstream(str) -> UpstreamProxy and
get_exit_ip(proxy, timeout=20).
Manual lifecycle (reuse one relay across many browsers):
relay = ProxyRelay("socks5://user:pass@host:1080").start()
try:
... # use relay.proxy / relay.url as many times as you like
finally:
relay.stop()
How it works
- Binds a local
asyncioTCP server on127.0.0.1(ephemeral port by default), running its own event loop on a daemon thread — so it plays nicely inside ordinary synchronous Selenium code. - Speaks the HTTP proxy protocol locally:
CONNECTfor HTTPS tunnels, absolute-form for plain HTTP. - Opens each connection through the selected upstream: SOCKS5 (user/pass),
SOCKS4/4a, or HTTP/HTTPS (
CONNECT+Proxy-Authorization), then pipes bytes both ways.
FAQ
Does the local proxy need a password? No — it listens on loopback only and isn't reachable from outside your machine.
HTTP and HTTPS both work? Yes. HTTPS goes through CONNECT (end-to-end
encrypted; the relay only tunnels bytes).
Do I need pysocks, pproxy, or anything else? No — standard library only.
Rotating residential proxies? Either give a pool and use rotation=, or
if your provider rotates behind a fixed host:port, just keep one relay — each
connection exits via whatever IP the upstream currently serves.
Development
git clone https://github.com/SAKMZ/selenium-proxy-tools
cd selenium-proxy-tools
python -m unittest discover -s tests -v
The suite spins up local SOCKS5-auth and HTTP-auth proxy servers, so the full relay path (auth + rotation) is exercised without touching the network.
License
MIT © Saif Ali (SAKMZ)
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 selenium_proxy_tools-0.2.0.tar.gz.
File metadata
- Download URL: selenium_proxy_tools-0.2.0.tar.gz
- Upload date:
- Size: 13.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3673c98a0cad12f61a64375a786ae862d39afffa3983c869d66093e805e23ee3
|
|
| MD5 |
9f86959d31157d500005a608e7a7b53c
|
|
| BLAKE2b-256 |
354517aad4b03d1e3f7853053682307195528faf6fe5bef28f999b6290fc9d7c
|
Provenance
The following attestation bundles were made for selenium_proxy_tools-0.2.0.tar.gz:
Publisher:
publish.yml on SAKMZ/selenium-proxy-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
selenium_proxy_tools-0.2.0.tar.gz -
Subject digest:
3673c98a0cad12f61a64375a786ae862d39afffa3983c869d66093e805e23ee3 - Sigstore transparency entry: 2201469504
- Sigstore integration time:
-
Permalink:
SAKMZ/selenium-proxy-tools@ea1686577d225c797f512af4bdcda867beea409d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/SAKMZ
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ea1686577d225c797f512af4bdcda867beea409d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file selenium_proxy_tools-0.2.0-py3-none-any.whl.
File metadata
- Download URL: selenium_proxy_tools-0.2.0-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ec16bbb01b08b1266283a17ff6c777a52008a39539120cad7071caa89b365f8
|
|
| MD5 |
d1db29ebf5e19035b5ad2129c8801ecb
|
|
| BLAKE2b-256 |
4dbf44963326c3e6a84f4e0f30474b597d1993872c892f471fb461af40c7f6be
|
Provenance
The following attestation bundles were made for selenium_proxy_tools-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on SAKMZ/selenium-proxy-tools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
selenium_proxy_tools-0.2.0-py3-none-any.whl -
Subject digest:
6ec16bbb01b08b1266283a17ff6c777a52008a39539120cad7071caa89b365f8 - Sigstore transparency entry: 2201469614
- Sigstore integration time:
-
Permalink:
SAKMZ/selenium-proxy-tools@ea1686577d225c797f512af4bdcda867beea409d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/SAKMZ
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ea1686577d225c797f512af4bdcda867beea409d -
Trigger Event:
workflow_dispatch
-
Statement type: