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)
Metadata
Release files for selenium-proxy-tools 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| selenium_proxy_tools-0.2.0.tar.gz | 13.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| selenium_proxy_tools-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 23.2 kB
Release files / selenium_proxy_tools-0.2.0.tar.gz
| Download URL | selenium_proxy_tools-0.2.0.tar.gz |
|---|---|
| Size | 13.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3673c98a0cad12f61a64375a786ae862d39afffa3983c869d66093e805e23ee3
|
|
BLAKE2b-256 checksum How to use checksums |
354517aad4b03d1e3f7853053682307195528faf6fe5bef28f999b6290fc9d7c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency logRelease files / selenium_proxy_tools-0.2.0-py3-none-any.whl
| Download URL | selenium_proxy_tools-0.2.0-py3-none-any.whl |
|---|---|
| Size | 10.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6ec16bbb01b08b1266283a17ff6c777a52008a39539120cad7071caa89b365f8
|
|
BLAKE2b-256 checksum How to use checksums |
4dbf44963326c3e6a84f4e0f30474b597d1993872c892f471fb461af40c7f6be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency logSecurity for selenium-proxy-tools 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for selenium_proxy_tools-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 19, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.