Selenium Proxy Authentication: Why Chrome Ignores Your Credentials and What Actually Works
Selenium sets a proxy through browser options, and for an unauthenticated or IP-whitelisted proxy a single `--proxy-server` argument is enough. Username and password are the hard part: Chrome silently discards credentials in that flag, raises a native login dialog WebDriver cannot interact with, and the two classic fixes — Selenium Wire and a side-loaded extension — have both stopped being reliable. What still works is IP whitelisting, a small local forwarder that adds the credentials, or answering the challenge through the DevTools protocol.
- selenium
- python
- automation
- proxy authentication

Table of contents
This is the deep-dive for authenticated proxies. If your proxy is whitelisted and you only need the configuration, the Selenium integration page has the copy-paste version.
The baseline that works without credentials
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://PROXY_HOST:PROXY_PORT")
driver = webdriver.Chrome(options=options)
driver.get("https://api.ipify.org?format=json")
print(driver.find_element("tag name", "body").text) # the proxy's IP
driver.quit()Add user:pass@ to that URL and nothing visibly changes — the browser opens, the page fails, and depending on the version you see a login prompt, a blank page or ERR_TUNNEL_CONNECTION_FAILED. Chrome treats proxy credentials as something a human types into a dialog, and that dialog lives outside the page where WebDriver has no reach.
Which approach to use
| Approach | Works in 2026 | Best for | Catch |
|---|---|---|---|
| IP whitelisting | Yes | Fixed servers and CI runners | Breaks when your public IP changes |
| Local forwarder | Yes | Laptops, Docker, Chrome and Firefox alike | One extra process per identity |
DevTools Fetch.continueWithAuth | Yes, Chromium only | Staying inside Python | Event handling via BiDi is still evolving |
| Side-loaded extension | Only on Chromium / Chrome for Testing | Legacy suites | Branded Chrome no longer loads it |
| Selenium Wire | No | — | Archived; breaks on current Python and Selenium |
Option 1: IP whitelisting
Register the public IP of the machine running Selenium in your proxy dashboard, and the proxy accepts its connections without a username or password. The baseline code above then works unchanged. This is the right answer for a VPS, a dedicated scraping box or a CI runner with a static egress address. See IP whitelisting for how it compares to credentials.
Whitelisting ties the proxy to your address, not your session. If a laptop moves between networks or a cloud instance is recycled onto a new IP, requests start failing with 407 and nothing in the error says why. Check what the proxy sees first.
Option 2: a local forwarder that adds the credentials
Run a tiny proxy on 127.0.0.1 with no authentication, and have it forward to the real proxy with credentials attached. Chrome talks to localhost without needing a password, and the forwarder handles the 407. GOST is a single static binary that does exactly this:
# Listen locally without auth, forward upstream with auth
gost -L http://127.0.0.1:8080 -F http://USERNAME:PASSWORD@PROXY_HOST:PROXY_PORTfrom selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://127.0.0.1:8080")
driver = webdriver.Chrome(options=options)The forwarder only relays the CONNECT tunnel — it does not decrypt HTTPS, so no certificate needs installing. Bind it to 127.0.0.1 rather than 0.0.0.0; an open unauthenticated relay on a public interface is an invitation for strangers to spend your bandwidth.
Option 3: answering the challenge through DevTools
Chromium can hand the authentication challenge to your code. Enabling the DevTools Fetch domain with handleAuthRequests makes the browser emit Fetch.authRequired when the proxy asks for credentials, and replying with Fetch.continueWithAuth supplies them. This keeps everything inside one Python process.
The catch is that it needs an event listener, and driver.execute_cdp_cmd can only send commands, not receive events. Recent Selenium 4 releases expose the listener through their BiDi and network APIs, but those are still marked as evolving. If you take this route, pin the Selenium version and add a test that loads an IP echo page through the proxy, so an upgrade cannot break it silently.
Why the old fixes stopped working
- Selenium Wire intercepted traffic through its own embedded proxy and injected the credentials. The project was archived in early 2024 and its dependencies no longer install cleanly on current Python.
- The generated extension — a Manifest file plus a
webRequest.onAuthRequiredlistener, zipped and loaded with--load-extension— was the standard trick for years. Recent branded Chrome releases stopped honouring that flag. It still works on Chromium and Chrome for Testing, which is worth knowing if an old suite suddenly broke after a Chrome update.
Whitelist once, skip the workaround
ISP proxies from €1.80/IP with IP-whitelist or username authentication — one stable residential-registered address per browser. Residential from €1.20/GB.
Firefox
Firefox takes its proxy from preferences, set on the options object in Selenium 4. It also refuses to accept credentials this way, so the forwarder or whitelisting still applies.
from selenium import webdriver
options = webdriver.FirefoxOptions()
options.set_preference("network.proxy.type", 1)
options.set_preference("network.proxy.http", "127.0.0.1")
options.set_preference("network.proxy.http_port", 8080)
options.set_preference("network.proxy.ssl", "127.0.0.1")
options.set_preference("network.proxy.ssl_port", 8080)
driver = webdriver.Firefox(options=options)Rotation: one identity per driver
A Chrome instance keeps its proxy for its whole lifetime, so rotation in Selenium means one driver per identity. With a gateway that assigns the exit from the username, give each worker its own forwarder and session tag:
import subprocess
import uuid
from selenium import webdriver
def start_identity(port: int):
tag = uuid.uuid4().hex[:8]
upstream = f"http://USERNAME-session-{tag}:PASSWORD@PROXY_HOST:PROXY_PORT"
relay = subprocess.Popen(["gost", "-L", f"http://127.0.0.1:{port}", "-F", upstream])
options = webdriver.ChromeOptions()
options.add_argument(f"--proxy-server=http://127.0.0.1:{port}")
return webdriver.Chrome(options=options), relay
driver, relay = start_identity(8081)
try:
driver.get("https://api.ipify.org")
finally:
driver.quit()
relay.terminate()Keep the identity stable for the life of any logged-in task; switching exit mid-session is a stronger bot signal than any header. The trade-offs are covered in rotating vs sticky sessions.
A proxy does not hide WebDriver
A clean IP solves the network half of detection. Selenium-driven Chrome still sets navigator.webdriver, ships automation flags and has a recognisable fingerprint, and sites that check those will block you regardless of the exit. For account work, pair each proxy with a separate profile in an anti-detect browser; for scraping, Playwright is usually less work, since it handles proxy credentials natively and gives each context its own proxy.
Sources
Frequently asked questions
How do I use a proxy with username and password in Selenium?
Chrome ignores credentials in the --proxy-server argument, so either whitelist your machine's IP with the proxy provider, run a local forwarder on 127.0.0.1 that adds the credentials upstream, or answer the Fetch.authRequired DevTools event with Fetch.continueWithAuth.
Why does Chrome ignore proxy credentials in Selenium?
Chrome is designed to collect proxy credentials through a native login dialog, not from the command line. That dialog sits outside the page, so WebDriver cannot fill it, and the user:pass part of the proxy URL is discarded.
Is Selenium Wire still usable?
Not for new work. The project was archived in 2024 and no longer installs reliably on current Python and Selenium versions. A local forwarder such as GOST replaces its proxy-authentication role.
How do I rotate proxies in Selenium?
Each browser instance keeps one proxy, so start one driver per identity. With a gateway that selects the exit from the username, vary a session tag per driver, and keep it constant for the duration of any logged-in task.
Does Selenium support SOCKS5 proxies?
Yes. Chrome accepts --proxy-server=socks5://host:port and Firefox has network.proxy.socks preferences. Chrome does not support SOCKS5 authentication at all, so SOCKS5 with a password needs whitelisting or a forwarder.
Should I use Selenium or Playwright for proxy work?
Playwright accepts proxy credentials directly and supports a different proxy per browser context, which removes most of the work described here. Selenium remains the practical choice when you already maintain a large suite built on it.
The seamless team runs residential, ISP and datacenter proxy infrastructure and writes these guides from day-to-day operational experience.
Ready to try seamless proxies?
Residential, ISP and datacenter proxies with no data expiry.
Browse PlansKeep reading
Playwright Proxies: Authentication, Per-Context Rotation and Real Geo Testing
One browser, many identities: set the proxy per context, keep locale and timezone honest, and stop leaking the fact that your headless Chrome is headless.
AutomationPuppeteer Proxies: Why Chromium Ignores Your Password, and What to Do About It
The most-searched Puppeteer proxy problem has a one-line answer and three architectural consequences nobody mentions.
Troubleshooting407 Proxy Authentication Required: Every Cause and Its Fix
The one proxy error that is entirely on your side of the connection — and the handful of clients that cause it even when your credentials are perfect.
