Back to Integrations
Integration Guide

Selenium Proxy Integration

Jun 11, 2026 10 min read Databay Research Team

Set up Databay residential and datacenter proxies in Selenium for both Chrome and Firefox, with honest coverage of the authentication problem: browsers ignore proxy credentials passed from WebDriver, so this guide walks through IP whitelisting, Selenium Wire and a credential-supplying Chrome extension, plus rotation patterns, common errors and timeout tuning.

Selenium Proxy Integration

What Is Selenium

Selenium is the longest-established browser automation framework: WebDriver bindings exist for Python, Java, C#, Ruby and JavaScript, and the same script can drive Chrome, Firefox, Edge and Safari. That breadth is why so much scraping and testing infrastructure is built on it. For proxy work, though, Selenium has one structural quirk you need to understand up front: WebDriver can tell a browser which proxy to use, but it has no standard way to supply proxy credentials, because the username/password prompt is browser UI that WebDriver does not script. Everything in this guide flows from that constraint, and all three workarounds below are used in production every day.

Connecting Selenium to Databay Proxies

Databay's gateway is gw.databay.co:8888; the pool, country and session are chosen with flags in the username, such as USER-zone-residential or USER-zone-datacenter. With Selenium you have three honest options for getting those credentials to the gateway: whitelist your server's IP so no credentials are needed, use Selenium Wire to inject authentication from a local proxy layer, or load a small browser extension that answers the auth challenge. IP whitelisting is the cleanest if your egress IP is static; the other two follow below.

Chrome Setup

Pointing Chrome at the gateway is one argument:

from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument('--proxy-server=http://gw.databay.co:8888')

driver = webdriver.Chrome(options=options)
driver.get('https://httpbin.org/ip')
print(driver.find_element('tag name', 'body').text)
driver.quit()

This works as-is only when your machine's IP is whitelisted in the Databay dashboard, because Chrome strips any credentials embedded in the --proxy-server URL and Selenium cannot type into the resulting auth popup. If you run from servers with stable IPs, whitelist them and stop here; it is the simplest production setup. To target the datacenter pool instead of residential, nothing changes on the Chrome side; the pool is a property of your credentials or whitelist configuration, not of the browser flags.

Firefox Setup

Firefox takes its proxy from preferences rather than a command-line flag:

from selenium import webdriver

options = webdriver.FirefoxOptions()
options.set_preference('network.proxy.type', 1)
options.set_preference('network.proxy.http', 'gw.databay.co')
options.set_preference('network.proxy.http_port', 8888)
options.set_preference('network.proxy.ssl', 'gw.databay.co')
options.set_preference('network.proxy.ssl_port', 8888)

driver = webdriver.Firefox(options=options)
driver.get('https://httpbin.org/ip')

The same caveat applies: there is no Firefox preference that supplies proxy credentials, and the master-password tricks that circulate in old forum posts are not reliable across versions. With Firefox your realistic options are IP whitelisting or Selenium Wire; the extension approach in this guide is Chrome-specific.

Authenticated Proxies with Selenium Wire

Selenium Wire extends the Python bindings with a local man-in-the-middle proxy that handles upstream authentication for you, so credential-based access works without whitelisting:

from seleniumwire import webdriver

seleniumwire_options = {
    'proxy': {
        'http': 'http://USER-zone-residential:PASS@gw.databay.co:8888',
        'https': 'http://USER-zone-residential:PASS@gw.databay.co:8888'
    }
}

driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get('https://httpbin.org/ip')

Two things to know before adopting it. First, the project is no longer actively maintained, although it remains widely deployed and pinned versions continue to work; weigh that against your maintenance appetite. Second, because it decrypts HTTPS locally to do its job, browsers see Selenium Wire's own certificate; that is by design and local-only, but it means certificate errors you hit are usually about trusting the local CA, not about Databay's gateway. A useful bonus: driver.proxy can be reassigned at runtime, which makes Selenium Wire the only option here that can switch credentials without restarting the browser.

Authentication via a Chrome Extension

The third route is a tiny unpacked extension that sets the proxy and answers the auth challenge from inside Chrome. A Manifest V3 version needs two files. manifest.json:

{
  "manifest_version": 3,
  "name": "Databay Proxy Auth",
  "version": "1.0",
  "permissions": ["proxy", "webRequest", "webRequestAuthProvider"],
  "host_permissions": ["<all_urls>"],
  "background": { "service_worker": "background.js" }
}

and background.js:

chrome.proxy.settings.set({
  value: {
    mode: 'fixed_servers',
    rules: {
      singleProxy: { scheme: 'http', host: 'gw.databay.co', port: 8888 }
    }
  },
  scope: 'regular'
});

chrome.webRequest.onAuthRequired.addListener(
  (details, callback) => {
    callback({
      authCredentials: {
        username: 'USER-zone-residential',
        password: 'PASS'
      }
    });
  },
  { urls: ['<all_urls>'] },
  ['asyncBlocking']
);

Load it with options.add_argument('--load-extension=/path/to/extension'). Note that extensions do not load in Chrome's old headless mode; use the new headless implementation (--headless=new) or a virtual display. Generate the two files per worker if each worker needs different credentials, since the values are baked into the extension at load time.

Proxy Rotation Patterns

Selenium has no per-tab proxy concept: the proxy belongs to the browser process. Rotation therefore happens at driver granularity, which fits naturally with how a rotating gateway works. Databay's gateway assigns exit IPs per connection unless you pin one, so the controlling lever is the sessionId flag: USER-zone-residential-sessionId-abc123 keeps one exit IP for the whole driver lifetime, and a fresh id on the next driver gets a fresh IP. Add -countryCode-us (or another country code) to pin geography. The standard worker loop looks like this with Selenium Wire:

import random, string
from seleniumwire import webdriver

def fresh_session_options():
    sid = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
    upstream = f'http://USER-zone-residential-sessionId-{sid}:PASS@gw.databay.co:8888'
    return {'proxy': {'http': upstream, 'https': upstream}}

for batch in url_batches:
    driver = webdriver.Chrome(seleniumwire_options=fresh_session_options())
    try:
        for url in batch:
            driver.get(url)
            # ... extract ...
    finally:
        driver.quit()

One sticky session per driver, one driver per batch of work, a new session id when a batch ends or a block appears. Avoid rotating faster than that: a browser page load opens many parallel connections, and an unpinned rotating session can deliver a single page from several IPs at once, which is a detection signal in itself. The trade-offs between sticky and rotating behaviour are covered in static vs rotating proxies.

Common Errors and Fixes

Most Selenium proxy failures fall into four buckets, and each has a distinctive signature.

HTTP 407 Proxy Authentication Required

With plain Selenium plus --proxy-server, a 407 (or a hanging auth popup in headed mode) means credentials never reached the gateway, which is expected: Chrome discards credentials in the proxy URL and WebDriver cannot answer the prompt. Switch to one of the three auth mechanisms above. With Selenium Wire, a 407 means the upstream credentials in seleniumwire_options are wrong, the zone flag is misspelled, or a special character in the password needs URL-encoding inside the proxy URL. With the extension, check that the extension actually loaded (it will not in old headless mode) and that the credentials baked into background.js are current. In every case, validate credentials outside the browser first:

curl -x http://USER-zone-residential:PASS@gw.databay.co:8888 https://httpbin.org/ip

If curl succeeds, the account is fine and the failure is in how credentials are being delivered to the browser.

ERR_TUNNEL_CONNECTION_FAILED

Chrome shows ERR_TUNNEL_CONNECTION_FAILED (Firefox: "The proxy server is refusing connections") when the CONNECT tunnel for an HTTPS site cannot be established. Verify the endpoint is exactly gw.databay.co:8888, then check the username flags: an invalid zone or malformed country code can make the gateway refuse the tunnel rather than return a clean 407. If curl through the same proxy works but the browser does not, look at what differs: a stale driver binary, a corporate firewall blocking the browser but not curl, or an extension that failed to apply its proxy settings before the first navigation. A one-second wait after driver startup before the first get() gives an auth extension's service worker time to register.

TLS and Certificate Errors

Databay's gateway tunnels HTTPS without terminating it, so genuine certificate errors rarely originate at the proxy. The big exception in a Selenium context is Selenium Wire, which by design decrypts traffic locally and presents its own certificate; its driver classes configure Chrome to accept that automatically, but hardened images or custom flags can break it, producing warnings on every page. If you are not using Selenium Wire and still see certificate errors, suspect corporate TLS interception on your own network or a genuinely broken target site. options.set_capability('acceptInsecureCerts', True) exists as an escape hatch and is reasonable for staging environments with self-signed certificates, but leaving it on for production scraping hides real interception warnings.

Timeouts and Slow Pages

Residential exits add latency on every connection a page opens, and Selenium's defaults assume a fast direct line. Three settings cover it:

driver.set_page_load_timeout(60)

options = webdriver.ChromeOptions()
options.page_load_strategy = 'eager'  # return at DOMContentLoaded

The eager page-load strategy makes driver.get() return once the DOM is parsed instead of waiting for every image and tracking pixel, which both speeds up scripts and cuts metered proxy bandwidth. Pair it with explicit waits (WebDriverWait) for the specific elements you need rather than raising the global timeout further. If one driver's session times out repeatedly while others are healthy, treat it as a slow exit IP: discard the session id and start a fresh driver instead of tuning around it.

Best Practices for Selenium with Proxies

  • Whitelist where you can. If your workers have static egress IPs, IP whitelisting removes the entire credential problem and works identically for Chrome and Firefox.
  • One driver, one identity. Pin each driver to its own sticky sessionId and keep cookies, session and exit IP aligned for the driver's lifetime.
  • Rotate on evidence. Swap session ids when you hit 403s, 429s or CAPTCHAs, not on a timer; an unblocked IP is an asset.
  • Trim page weight. The eager load strategy and disabling images via preferences reduce both runtime and bandwidth spend on metered residential traffic.
  • Remember IP is only half the story. Selenium leaves automation fingerprints that rotation cannot hide; how sites detect headless browsers explains what targets actually check.
  • Choose the right pool per target. Datacenter for speed and volume on permissive targets, residential where IP reputation is scored; the decision factors are laid out in residential vs datacenter proxies.

Frequently Asked Questions

Why can't Selenium just pass a proxy username and password to Chrome?
Proxy authentication in a browser is a UI prompt, and WebDriver deliberately cannot interact with browser-level dialogs. Chrome also strips credentials embedded in the --proxy-server URL. Selenium's own Proxy class has username fields only for SOCKS, and Chrome ignores even those for HTTP proxies. That is why production setups use IP whitelisting, Selenium Wire, or an extension that answers the auth challenge.
Can I change the proxy without restarting the browser?
With plain Selenium, no: the proxy is fixed for the browser process lifetime, so rotation means a new driver. With Selenium Wire you can reassign driver.proxy at runtime, which switches the upstream credentials, and with a Databay sticky session that effectively switches the exit IP without a restart.
Does Selenium support SOCKS5 proxies?
Yes. Chrome accepts --proxy-server=socks5://host:port and Firefox has equivalent network.proxy.socks preferences. Databay supports both HTTP and SOCKS5. Note that Chrome does not support SOCKS authentication, so for credential-based access over SOCKS5 you still need whitelisting; most Selenium setups simply use the HTTP gateway instead.
Is Selenium Wire safe to use if it is unmaintained?
It remains widely used and pinned versions are stable, but it no longer receives fixes, and it decrypts HTTPS locally as part of how it injects authentication. Many teams accept that trade-off for scraping workloads; if you would rather avoid it, the extension approach or IP whitelisting achieves authentication with vanilla Selenium.
Should I use residential or datacenter proxies with Selenium?
Datacenter proxies are faster and cheaper and suit high-volume work against targets without aggressive bot defence. Residential proxies exit through real consumer connections and survive IP-reputation filtering far better, so use them for protected targets, logins and geo-sensitive pages. The zone is a username flag, so switching pools requires no Selenium code changes.

Start Using Databay Proxies Today

Set up residential, datacenter, or mobile proxies in minutes. Pay as you go with no commitments.

Start Using Rotating Proxies Today

Join 8,000+ users using Databay's rotating proxy infrastructure for web scraping, data collection, and automation. Access 34M+ residential, datacenter, and mobile IPs across 200+ countries from a flat $0.55/GB (Flex), pay-as-you-go. No monthly commitment, no connection limits - start collecting data in minutes.