Skip to main content

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

tests PyPI Python License: MIT

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 asyncio TCP server on 127.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: CONNECT for 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

selenium_proxy_tools-0.2.0.tar.gz (13.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

selenium_proxy_tools-0.2.0-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

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

Hashes for selenium_proxy_tools-0.2.0.tar.gz
Algorithm Hash digest
SHA256 3673c98a0cad12f61a64375a786ae862d39afffa3983c869d66093e805e23ee3
MD5 9f86959d31157d500005a608e7a7b53c
BLAKE2b-256 354517aad4b03d1e3f7853053682307195528faf6fe5bef28f999b6290fc9d7c

See more details on using hashes here.

Provenance

The following attestation bundles were made for selenium_proxy_tools-0.2.0.tar.gz:

Publisher: publish.yml on SAKMZ/selenium-proxy-tools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file selenium_proxy_tools-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for selenium_proxy_tools-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6ec16bbb01b08b1266283a17ff6c777a52008a39539120cad7071caa89b365f8
MD5 d1db29ebf5e19035b5ad2129c8801ecb
BLAKE2b-256 4dbf44963326c3e6a84f4e0f30474b597d1993872c892f471fb461af40c7f6be

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page