Selenium WebDriver Datacenter Proxy Setup: Python, Node.js & Java
Datacenter proxies hit 99.88% success at 0.38s median response. Full Selenium WebDriver proxy setup in Python, Node.js, and Java with rotation and auth.
Table of Contents
- Why Are Datacenter Proxies the Right Choice for Selenium Automation?
- How Do You Configure a Datacenter Proxy in Selenium with Python?
- How Do You Set a Proxy in Selenium with Node.js?
- How Do You Configure a Selenium Proxy in Java?
- How Do You Handle Authenticated Proxies in Selenium?
- How Do You Rotate Proxies Across Selenium Sessions?
- How Do You Verify Your Proxy Is Active in Selenium?
- Wrapping Up
-
Why Are Datacenter Proxies the Right Choice for Selenium Automation?
Datacenter Proxies with Selenium WebDriver: Python, Node.js, and Java
Datacenter proxies are the most practical choice for Selenium automation at scale. They hit a 99.88% median infrastructure success rate with a 0.38-second median response time and cost roughly $0.70 per GB — seven times cheaper than residential alternatives (ProxyWay Proxy Market Research 2024).
Selenium WebDriver 4 has a built-in proxy capability that works across every browser it supports. The API looks slightly different in each language, but the underlying
Proxyobject is the same. This tutorial walks through the complete setup in Python, Node.js, and Java: basic configuration, authentication, proxy rotation, and verification. Every code block is ready to copy into a real project.Key Takeaways
- Selenium 4 uses
ChromeOptions/FirefoxOptions— the oldDesiredCapabilitiesproxy pattern is deprecated - Datacenter proxies average 0.38s response time and $0.70/GB, making them 7× cheaper than residential IPs (ProxyWay 2024)
- Authenticated proxies in Chrome require a browser extension; Firefox handles credentials natively via profile or proxy URL
- Proxy rotation means a
driver.quit()+ reinitialise cycle — you can't hot-swap an active session's proxy - Always verify the active IP with
httpbin.org/ipbefore running production logic
Browser-based automation is heavier than raw HTTP scraping. Every Selenium session loads a full Chrome or Firefox instance, renders JavaScript, and downloads assets. The proxy tier amplifies or absorbs that overhead.
Datacenter proxies perform well here because they're hosted on dedicated servers in colocation facilities with high-bandwidth uplinks. They're always online, they respond quickly, and they're cheap enough to run at volume. The ProxyWay 2024 benchmark puts the rotating datacenter median at a 99.88% success rate and 0.38 seconds median response time — the fastest participant (Bright Data) completed requests in 0.26 seconds. At $0.70/GB average, you get 10× the throughput budget compared to residential proxies for the same spend.
The tradeoff is detectability. Datacenter IPs are registered to hosting providers, not ISPs, and anti-bot systems know this. They're appropriate for targets without aggressive bot detection: internal testing, QA automation, price monitoring on cooperative sites, and geo-testing. For targets that specifically block datacenter ASNs, a residential or ISP proxy is the right call.
Proxy cost vs. response time (rotating proxies, ProxyWay 2024): ┌─────────────────────┬────────────┬──────────────┐ │ Type │ Avg $/GB │ Median RTT │ ├─────────────────────┼────────────┼──────────────┤ │ Rotating datacenter │ $0.70 │ 0.38 s │ │ Residential │ $4.90 │ 0.41 s │ │ Mobile │ $9.80 │ 0.88 s │ └─────────────────────┴────────────┴──────────────┘ Source: ProxyWay Proxy Market Research 2024[CITATION CAPSULE] "With a median success rate of 99.88%, rotating datacenter proxies very rarely fail. The median response time was 0.38 seconds. Rotating datacenter proxies cost $0.70 on average at 100 GB of data — seven times cheaper than residential and over 14 times cheaper than mobile proxy networks." — ProxyWay Proxy Market Research 2024
datacenter vs. residential proxy comparison
- Selenium 4 uses
-
How Do You Configure a Datacenter Proxy in Selenium with Python?
Selenium's Python bindings use the
selenium.webdriver.common.proxy.Proxyclass to define proxy settings, then pass the result toChromeOptionsorFirefoxOptions.Chrome:
import os from selenium import webdriver from selenium.webdriver.common.proxy import Proxy, ProxyType PROXY_HOST = "dc.example.com" PROXY_PORT = "7000" proxy = Proxy() proxy.proxy_type = ProxyType.MANUAL proxy.http_proxy = f"{PROXY_HOST}:{PROXY_PORT}" proxy.ssl_proxy = f"{PROXY_HOST}:{PROXY_PORT}" options = webdriver.ChromeOptions() options.Proxy = proxy # Headless for CI/CD environments options.add_argument("--headless=new") options.add_argument("--no-sandbox") options.add_argument("--disable-dev-shm-usage") driver = webdriver.Chrome(options=options) driver.get("https://httpbin.org/ip") print(driver.find_element("tag name", "body").text) driver.quit()Firefox accepts the same
Proxyobject viaFirefoxOptions:from selenium import webdriver from selenium.webdriver.common.proxy import Proxy, ProxyType proxy = Proxy() proxy.proxy_type = ProxyType.MANUAL proxy.http_proxy = "dc.example.com:7000" proxy.ssl_proxy = "dc.example.com:7000" proxy.ftp_proxy = "dc.example.com:7000" options = webdriver.FirefoxOptions() options.proxy = proxy driver = webdriver.Firefox(options=options) driver.get("https://httpbin.org/ip") print(driver.find_element("tag name", "pre").text) driver.quit()Two things to keep in mind with the Python API:
- Set both
http_proxyandssl_proxy. Ifssl_proxyis missing, HTTPS sites won't route through the proxy — a common silent failure. You'll see your real IP in the response rather than an error, which makes it hard to notice. --headless=new(Chrome 112+) is the modern headless flag. The old--headlessflag triggers the legacy headless mode, which behaves differently with proxy settings on some versions.
selenium headless Chrome configuration
- Set both
-
How Do You Set a Proxy in Selenium with Node.js?
The
selenium-webdrivernpm package usesCapabilitiesand aproxyconfiguration object. Selenium 4 structures this differently from the oldDesiredCapabilitiesapproach.Chrome:
const { Builder, Capabilities } = require('selenium-webdriver'); const chrome = require('selenium-webdriver/chrome'); const PROXY_HOST = 'dc.example.com'; const PROXY_PORT = '7000'; const proxyStr = `${PROXY_HOST}:${PROXY_PORT}`; const options = new chrome.Options(); options.setProxy({ proxyType: 'manual', httpProxy: proxyStr, sslProxy: proxyStr, }); // Headless options.addArguments('--headless=new', '--no-sandbox', '--disable-dev-shm-usage'); async function main() { const driver = await new Builder() .forBrowser('chrome') .setChromeOptions(options) .build(); try { await driver.get('https://httpbin.org/ip'); const body = await driver.findElement({ tagName: 'body' }); console.log(await body.getText()); } finally { await driver.quit(); } } main();Firefox via the
firefoxmodule:const { Builder } = require('selenium-webdriver'); const firefox = require('selenium-webdriver/firefox'); const options = new firefox.Options(); options.setPreference('network.proxy.type', 1); // 1 = Manual options.setPreference('network.proxy.http', 'dc.example.com'); options.setPreference('network.proxy.http_port', 7000); options.setPreference('network.proxy.ssl', 'dc.example.com'); options.setPreference('network.proxy.ssl_port', 7000); options.setPreference('network.proxy.no_proxies_on', ''); async function main() { const driver = await new Builder() .forBrowser('firefox') .setFirefoxOptions(options) .build(); try { await driver.get('https://httpbin.org/ip'); const pre = await driver.findElement({ tagName: 'pre' }); console.log(await pre.getText()); } finally { await driver.quit(); } } main();The Firefox approach uses direct
setPreferencecalls because Firefox exposes proxy config through user preferences. Thenetwork.proxy.typevalue of1is the constant for manual proxy mode —0is no proxy,2is PAC URL,4is auto-detect.[UNIQUE INSIGHT] Chrome's
setProxyin Node.js silently ignores the proxy on HTTPS sites if onlyhttpProxyis set. Always set bothhttpProxyandsslProxyto the same endpoint — the names are misleading becausesslProxycontrols HTTPS tunnelling, not just SSL-native traffic.
-
How Do You Configure a Selenium Proxy in Java?
Java uses
org.openqa.selenium.Proxyand thesetCapabilitymethod onChromeOptions. Add the Maven dependency for Selenium 4 before you start:<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.20.0</version> </dependency>Chrome:
import org.openqa.selenium.Proxy; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; public class ProxyExample { public static void main(String[] args) { String proxyAddress = "dc.example.com:7000"; Proxy proxy = new Proxy(); proxy.setHttpProxy(proxyAddress); proxy.setSslProxy(proxyAddress); ChromeOptions options = new ChromeOptions(); options.setCapability("proxy", proxy); options.addArguments("--headless=new", "--no-sandbox"); WebDriver driver = new ChromeDriver(options); try { driver.get("https://httpbin.org/ip"); System.out.println(driver.findElement( org.openqa.selenium.By.tagName("body")).getText()); } finally { driver.quit(); } } }Firefox:
import org.openqa.selenium.Proxy; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; public class FirefoxProxyExample { public static void main(String[] args) { String proxyAddress = "dc.example.com:7000"; Proxy proxy = new Proxy(); proxy.setHttpProxy(proxyAddress); proxy.setSslProxy(proxyAddress); proxy.setFtpProxy(proxyAddress); FirefoxOptions options = new FirefoxOptions(); options.setCapability("proxy", proxy); WebDriver driver = new FirefoxDriver(options); try { driver.get("https://httpbin.org/ip"); System.out.println(driver.findElement( org.openqa.selenium.By.tagName("pre")).getText()); } finally { driver.quit(); } } }The
setCapability("proxy", proxy)call is the Selenium 4 standard. Some older tutorials usesetProxy(proxy)directly onChromeOptions— this was valid in Selenium 3 but is deprecated in Selenium 4 and may not behave consistently across browser versions.[CITATION CAPSULE] "A proxy server for automation scripts with Selenium could be helpful for capturing network traffic, mocking backend calls, and accessing required websites under complex network topologies or strict corporate restrictions. Selenium WebDriver provides a way to proxy settings via the Proxy capability." — Selenium WebDriver Official Documentation
-
How Do You Handle Authenticated Proxies in Selenium?
Most commercial datacenter proxy services require username/password authentication. The handling differs significantly between Chrome and Firefox.
Firefox accepts credentials directly in the proxy URL via profile preferences:
# Python — Firefox with authenticated proxy from selenium import webdriver import os user = os.environ["PROXY_USER"] pwd = os.environ["PROXY_PASS"] host = "dc.example.com" port = 7000 profile = webdriver.FirefoxProfile() profile.set_preference("network.proxy.type", 1) profile.set_preference("network.proxy.http", host) profile.set_preference("network.proxy.http_port", port) profile.set_preference("network.proxy.ssl", host) profile.set_preference("network.proxy.ssl_port", port) # Firefox prompts for credentials — pre-fill via network.proxy credentials profile.set_preference("signon.autologin.proxy", True) options = webdriver.FirefoxOptions() options.profile = profile driver = webdriver.Firefox(options=options)Chrome does not support proxy authentication natively through
ChromeOptions. The standard workaround is a tiny browser extension that intercepts the authentication challenge:import os import zipfile import string import tempfile from selenium import webdriver def make_proxy_auth_extension(host, port, user, pwd): manifest = """{ "version": "1.0.0", "manifest_version": 2, "name": "Proxy Auth", "permissions": ["proxy", "tabs", "unlimitedStorage", "storage", "<all_urls>", "webRequest", "webRequestBlocking"], "background": {"scripts": ["background.js"]}, "minimum_chrome_version": "22.0.0" }""" background = string.Template(""" var config = { mode: "fixed_servers", rules: { singleProxy: {scheme:"http", host:"$host", port:parseInt($port)}, bypassList: ["localhost"] } }; chrome.proxy.settings.set({value:config, scope:"regular"}, function(){}); function callbackFn(details) { return {authCredentials: {username:"$user", password:"$pwd"}}; } chrome.webRequest.onAuthRequired.addListener( callbackFn, {urls:["<all_urls>"]}, ["blocking"] ); """).substitute(host=host, port=port, user=user, pwd=pwd) tmp = tempfile.mktemp(suffix=".zip") with zipfile.ZipFile(tmp, "w") as zp: zp.writestr("manifest.json", manifest) zp.writestr("background.js", background) return tmp ext = make_proxy_auth_extension( host=os.environ["PROXY_HOST"], port=os.environ["PROXY_PORT"], user=os.environ["PROXY_USER"], pwd=os.environ["PROXY_PASS"], ) options = webdriver.ChromeOptions() options.add_extension(ext) driver = webdriver.Chrome(options=options) driver.get("https://httpbin.org/ip") print(driver.find_element("tag name", "body").text) driver.quit()The extension approach works reliably across Chrome versions. One practical note: Chrome in headless mode (prior to Chrome 112) doesn't load extensions. If you're on a headless CI pipeline, use Firefox for authenticated proxy sessions — it handles credentials natively.
[UNIQUE INSIGHT] The extension ZIP is temporary but its path is referenced by the
ChromeOptionsobject, so cleanup must happen afterdriver.quit(), not before. In long-running rotation loops, accumulating temp files from uncleaned extension ZIPs is a common source of disk exhaustion that doesn't surface until hours into a run.Chrome headless extension support
-
How Do You Rotate Proxies Across Selenium Sessions?
Selenium WebDriver doesn't support hot-swapping a proxy in an active session. The proxy is set at session start through
ChromeOptions/FirefoxOptionsand persists for the lifetime of that driver instance.Rotation means creating a new driver with a new proxy for each logical scraping task:
import os import random from selenium import webdriver from selenium.webdriver.common.proxy import Proxy, ProxyType PROXY_LIST = [ "dc1.example.com:7000", "dc2.example.com:7000", "dc3.example.com:7000", ] def create_driver(proxy_address: str) -> webdriver.Chrome: proxy = Proxy() proxy.proxy_type = ProxyType.MANUAL proxy.http_proxy = proxy_address proxy.ssl_proxy = proxy_address options = webdriver.ChromeOptions() options.Proxy = proxy options.add_argument("--headless=new") options.add_argument("--no-sandbox") options.add_argument("--disable-dev-shm-usage") return webdriver.Chrome(options=options) def scrape_url(url: str, proxy_address: str) -> str: driver = create_driver(proxy_address) try: driver.get(url) return driver.find_element("tag name", "body").text finally: driver.quit() urls = [f"https://example.com/product/{i}" for i in range(30)] for i, url in enumerate(urls): proxy = PROXY_LIST[i % len(PROXY_LIST)] result = scrape_url(url, proxy) print(f"{proxy} → {url}: {len(result)} bytes")For backconnect rotating proxies, the endpoint address never changes — the provider assigns a fresh IP per request internally. In this case you only need one
PROXY_LISTentry and can skip the rotation loop entirely:BACKCONNECT_PROXY = "rotate.dc.example.com:9000" for url in urls: result = scrape_url(url, BACKCONNECT_PROXY)Starting and quitting browser instances for every URL is expensive. In production, batch tasks by session: keep a driver alive for N pages, then rotate:
BATCH_SIZE = 10 for batch_start in range(0, len(urls), BATCH_SIZE): proxy = random.choice(PROXY_LIST) driver = create_driver(proxy) try: for url in urls[batch_start:batch_start + BATCH_SIZE]: driver.get(url) # process page... finally: driver.quit()
-
How Do You Verify Your Proxy Is Active in Selenium?
Misconfigured proxies fail silently.
requests.get()raises an error on connection failure, butdriver.get()often loads an error page without throwing an exception — your code continues, logging your real IP.The simplest verification is hitting
httpbin.org/ipand asserting the returned IP is not your machine's public IP:import json import requests from selenium import webdriver from selenium.webdriver.common.proxy import Proxy, ProxyType def get_my_public_ip() -> str: return requests.get("https://httpbin.org/ip", timeout=10).json()["origin"] def verify_proxy(driver: webdriver.Chrome) -> dict: driver.get("https://httpbin.org/ip") body = driver.find_element("tag name", "body").text data = json.loads(body) return data real_ip = get_my_public_ip() proxy = Proxy() proxy.proxy_type = ProxyType.MANUAL proxy.http_proxy = "dc.example.com:7000" proxy.ssl_proxy = "dc.example.com:7000" options = webdriver.ChromeOptions() options.Proxy = proxy options.add_argument("--headless=new") driver = webdriver.Chrome(options=options) result = verify_proxy(driver) proxy_ip = result.get("origin", "unknown") if proxy_ip == real_ip: print(f"WARNING: proxy not active — browser is using real IP {real_ip}") else: print(f"Proxy confirmed: {proxy_ip} (real IP hidden)") driver.quit()Run this check at the start of every session in production code. The overhead is a single HTTP request — negligible against the cost of running hundreds of tasks without proxy coverage.
For batch jobs, log the proxy IP on the first request of each session and compare it across the run. A proxy rotation that silently fails leaves you cycling through the same IP — detectable by sorting the IP log and looking for unexpected repetition.
Proxy verification checklist: ✅ proxy_ip != real_ip ✅ proxy_ip matches expected CIDR or provider ASN ✅ HTTPS test URL returns 200 (not an error page) ✅ ssl_proxy and http_proxy both set (not just one)
-
Wrapping Up
Selenium WebDriver's proxy setup is consistent across Python, Node.js, and Java — the same
Proxyobject model, the samehttp_proxy+ssl_proxyrule, the same session-scoped limitation. The language differences are syntactic rather than conceptual.Datacenter proxies fit most Selenium automation well: at 99.88% success rate and $0.70/GB, they're fast and cheap enough to run at the kind of volume browser-based automation demands. The two gotchas worth remembering — always set both
http_proxyandssl_proxy, and verify the active IP before running production logic — save hours of debugging silent misconfiguration later.
Datacenter Proxies with Selenium WebDriver: Python, Node.js, and Java
Datacenter proxies are the most practical choice for Selenium automation at scale. They hit a 99.88% median infrastructure success rate with a 0.38-second median response time and cost roughly $0.70 per GB — seven times cheaper than residential alternatives (ProxyWay Proxy Market Research 2024).
Selenium WebDriver 4 has a built-in proxy capability that works across every browser it supports. The API looks slightly different in each language, but the underlying Proxy object is the same. This tutorial walks through the complete setup in Python, Node.js, and Java: basic configuration, authentication, proxy rotation, and verification. Every code block is ready to copy into a real project.
Key Takeaways
- Selenium 4 uses
ChromeOptions/FirefoxOptions— the oldDesiredCapabilitiesproxy pattern is deprecated- Datacenter proxies average 0.38s response time and $0.70/GB, making them 7× cheaper than residential IPs (ProxyWay 2024)
- Authenticated proxies in Chrome require a browser extension; Firefox handles credentials natively via profile or proxy URL
- Proxy rotation means a
driver.quit()+ reinitialise cycle — you can't hot-swap an active session's proxy- Always verify the active IP with
httpbin.org/ipbefore running production logic
Table of Contents
- Why Are Datacenter Proxies the Right Choice for Selenium Automation?
- How Do You Configure a Datacenter Proxy in Selenium with Python?
- How Do You Set a Proxy in Selenium with Node.js?
- How Do You Configure a Selenium Proxy in Java?
- How Do You Handle Authenticated Proxies in Selenium?
- How Do You Rotate Proxies Across Selenium Sessions?
- How Do You Verify Your Proxy Is Active in Selenium?
- FAQ
Why Are Datacenter Proxies the Right Choice for Selenium Automation?
Browser-based automation is heavier than raw HTTP scraping. Every Selenium session loads a full Chrome or Firefox instance, renders JavaScript, and downloads assets. The proxy tier amplifies or absorbs that overhead.
Datacenter proxies perform well here because they're hosted on dedicated servers in colocation facilities with high-bandwidth uplinks. They're always online, they respond quickly, and they're cheap enough to run at volume. The ProxyWay 2024 benchmark puts the rotating datacenter median at a 99.88% success rate and 0.38 seconds median response time — the fastest participant (Bright Data) completed requests in 0.26 seconds. At $0.70/GB average, you get 10× the throughput budget compared to residential proxies for the same spend.
The tradeoff is detectability. Datacenter IPs are registered to hosting providers, not ISPs, and anti-bot systems know this. They're appropriate for targets without aggressive bot detection: internal testing, QA automation, price monitoring on cooperative sites, and geo-testing. For targets that specifically block datacenter ASNs, a residential or ISP proxy is the right call.
Proxy cost vs. response time (rotating proxies, ProxyWay 2024):
┌─────────────────────┬────────────┬──────────────┐
│ Type │ Avg $/GB │ Median RTT │
├─────────────────────┼────────────┼──────────────┤
│ Rotating datacenter │ $0.70 │ 0.38 s │
│ Residential │ $4.90 │ 0.41 s │
│ Mobile │ $9.80 │ 0.88 s │
└─────────────────────┴────────────┴──────────────┘
Source: ProxyWay Proxy Market Research 2024
[CITATION CAPSULE] "With a median success rate of 99.88%, rotating datacenter proxies very rarely fail. The median response time was 0.38 seconds. Rotating datacenter proxies cost $0.70 on average at 100 GB of data — seven times cheaper than residential and over 14 times cheaper than mobile proxy networks." — ProxyWay Proxy Market Research 2024
[INTERNAL-LINK: datacenter vs. residential proxy comparison → proxy type evaluation guide]
How Do You Configure a Datacenter Proxy in Selenium with Python?
Selenium's Python bindings use the selenium.webdriver.common.proxy.Proxy class to define proxy settings, then pass the result to ChromeOptions or FirefoxOptions.
Chrome:
import os
from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType
PROXY_HOST = "dc.example.com"
PROXY_PORT = "7000"
proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = f"{PROXY_HOST}:{PROXY_PORT}"
proxy.ssl_proxy = f"{PROXY_HOST}:{PROXY_PORT}"
options = webdriver.ChromeOptions()
options.Proxy = proxy
# Headless for CI/CD environments
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()
Firefox accepts the same Proxy object via FirefoxOptions:
from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType
proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = "dc.example.com:7000"
proxy.ssl_proxy = "dc.example.com:7000"
proxy.ftp_proxy = "dc.example.com:7000"
options = webdriver.FirefoxOptions()
options.proxy = proxy
driver = webdriver.Firefox(options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "pre").text)
driver.quit()
Two things to keep in mind with the Python API:
- Set both
http_proxyandssl_proxy. Ifssl_proxyis missing, HTTPS sites won't route through the proxy — a common silent failure. You'll see your real IP in the response rather than an error, which makes it hard to notice. --headless=new(Chrome 112+) is the modern headless flag. The old--headlessflag triggers the legacy headless mode, which behaves differently with proxy settings on some versions.
[INTERNAL-LINK: selenium headless Chrome configuration → Selenium browser options guide]
How Do You Set a Proxy in Selenium with Node.js?
The selenium-webdriver npm package uses Capabilities and a proxy configuration object. Selenium 4 structures this differently from the old DesiredCapabilities approach.
Chrome:
const { Builder, Capabilities } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');
const PROXY_HOST = 'dc.example.com';
const PROXY_PORT = '7000';
const proxyStr = `${PROXY_HOST}:${PROXY_PORT}`;
const options = new chrome.Options();
options.setProxy({
proxyType: 'manual',
httpProxy: proxyStr,
sslProxy: proxyStr,
});
// Headless
options.addArguments('--headless=new', '--no-sandbox', '--disable-dev-shm-usage');
async function main() {
const driver = await new Builder()
.forBrowser('chrome')
.setChromeOptions(options)
.build();
try {
await driver.get('https://httpbin.org/ip');
const body = await driver.findElement({ tagName: 'body' });
console.log(await body.getText());
} finally {
await driver.quit();
}
}
main();
Firefox via the firefox module:
const { Builder } = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');
const options = new firefox.Options();
options.setPreference('network.proxy.type', 1); // 1 = Manual
options.setPreference('network.proxy.http', 'dc.example.com');
options.setPreference('network.proxy.http_port', 7000);
options.setPreference('network.proxy.ssl', 'dc.example.com');
options.setPreference('network.proxy.ssl_port', 7000);
options.setPreference('network.proxy.no_proxies_on', '');
async function main() {
const driver = await new Builder()
.forBrowser('firefox')
.setFirefoxOptions(options)
.build();
try {
await driver.get('https://httpbin.org/ip');
const pre = await driver.findElement({ tagName: 'pre' });
console.log(await pre.getText());
} finally {
await driver.quit();
}
}
main();
The Firefox approach uses direct setPreference calls because Firefox exposes proxy config through user preferences. The network.proxy.type value of 1 is the constant for manual proxy mode — 0 is no proxy, 2 is PAC URL, 4 is auto-detect.
[UNIQUE INSIGHT] Chrome's
setProxyin Node.js silently ignores the proxy on HTTPS sites if onlyhttpProxyis set. Always set bothhttpProxyandsslProxyto the same endpoint — the names are misleading becausesslProxycontrols HTTPS tunnelling, not just SSL-native traffic.
How Do You Configure a Selenium Proxy in Java?
Java uses org.openqa.selenium.Proxy and the setCapability method on ChromeOptions. Add the Maven dependency for Selenium 4 before you start:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.20.0</version>
</dependency>
Chrome:
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class ProxyExample {
public static void main(String[] args) {
String proxyAddress = "dc.example.com:7000";
Proxy proxy = new Proxy();
proxy.setHttpProxy(proxyAddress);
proxy.setSslProxy(proxyAddress);
ChromeOptions options = new ChromeOptions();
options.setCapability("proxy", proxy);
options.addArguments("--headless=new", "--no-sandbox");
WebDriver driver = new ChromeDriver(options);
try {
driver.get("https://httpbin.org/ip");
System.out.println(driver.findElement(
org.openqa.selenium.By.tagName("body")).getText());
} finally {
driver.quit();
}
}
}
Firefox:
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
public class FirefoxProxyExample {
public static void main(String[] args) {
String proxyAddress = "dc.example.com:7000";
Proxy proxy = new Proxy();
proxy.setHttpProxy(proxyAddress);
proxy.setSslProxy(proxyAddress);
proxy.setFtpProxy(proxyAddress);
FirefoxOptions options = new FirefoxOptions();
options.setCapability("proxy", proxy);
WebDriver driver = new FirefoxDriver(options);
try {
driver.get("https://httpbin.org/ip");
System.out.println(driver.findElement(
org.openqa.selenium.By.tagName("pre")).getText());
} finally {
driver.quit();
}
}
}
The setCapability("proxy", proxy) call is the Selenium 4 standard. Some older tutorials use setProxy(proxy) directly on ChromeOptions — this was valid in Selenium 3 but is deprecated in Selenium 4 and may not behave consistently across browser versions.
[CITATION CAPSULE] "A proxy server for automation scripts with Selenium could be helpful for capturing network traffic, mocking backend calls, and accessing required websites under complex network topologies or strict corporate restrictions. Selenium WebDriver provides a way to proxy settings via the Proxy capability." — Selenium WebDriver Official Documentation
[INTERNAL-LINK: Selenium 4 migration guide → upgrading from Selenium 3 DesiredCapabilities]
How Do You Handle Authenticated Proxies in Selenium?
Most commercial datacenter proxy services require username/password authentication. The handling differs significantly between Chrome and Firefox.
Firefox accepts credentials directly in the proxy URL via profile preferences:
# Python — Firefox with authenticated proxy
from selenium import webdriver
import os
user = os.environ["PROXY_USER"]
pwd = os.environ["PROXY_PASS"]
host = "dc.example.com"
port = 7000
profile = webdriver.FirefoxProfile()
profile.set_preference("network.proxy.type", 1)
profile.set_preference("network.proxy.http", host)
profile.set_preference("network.proxy.http_port", port)
profile.set_preference("network.proxy.ssl", host)
profile.set_preference("network.proxy.ssl_port", port)
# Firefox prompts for credentials — pre-fill via network.proxy credentials
profile.set_preference("signon.autologin.proxy", True)
options = webdriver.FirefoxOptions()
options.profile = profile
driver = webdriver.Firefox(options=options)
Chrome does not support proxy authentication natively through ChromeOptions. The standard workaround is a tiny browser extension that intercepts the authentication challenge:
import os
import zipfile
import string
import tempfile
from selenium import webdriver
def make_proxy_auth_extension(host, port, user, pwd):
manifest = """{
"version": "1.0.0",
"manifest_version": 2,
"name": "Proxy Auth",
"permissions": ["proxy", "tabs", "unlimitedStorage",
"storage", "<all_urls>", "webRequest",
"webRequestBlocking"],
"background": {"scripts": ["background.js"]},
"minimum_chrome_version": "22.0.0"
}"""
background = string.Template("""
var config = {
mode: "fixed_servers",
rules: {
singleProxy: {scheme:"http", host:"$host", port:parseInt($port)},
bypassList: ["localhost"]
}
};
chrome.proxy.settings.set({value:config, scope:"regular"}, function(){});
function callbackFn(details) {
return {authCredentials: {username:"$user", password:"$pwd"}};
}
chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls:["<all_urls>"]},
["blocking"]
);
""").substitute(host=host, port=port, user=user, pwd=pwd)
tmp = tempfile.mktemp(suffix=".zip")
with zipfile.ZipFile(tmp, "w") as zp:
zp.writestr("manifest.json", manifest)
zp.writestr("background.js", background)
return tmp
ext = make_proxy_auth_extension(
host=os.environ["PROXY_HOST"],
port=os.environ["PROXY_PORT"],
user=os.environ["PROXY_USER"],
pwd=os.environ["PROXY_PASS"],
)
options = webdriver.ChromeOptions()
options.add_extension(ext)
driver = webdriver.Chrome(options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()
The extension approach works reliably across Chrome versions. One practical note: Chrome in headless mode (prior to Chrome 112) doesn't load extensions. If you're on a headless CI pipeline, use Firefox for authenticated proxy sessions — it handles credentials natively.
[UNIQUE INSIGHT] The extension ZIP is temporary but its path is referenced by the
ChromeOptionsobject, so cleanup must happen afterdriver.quit(), not before. In long-running rotation loops, accumulating temp files from uncleaned extension ZIPs is a common source of disk exhaustion that doesn't surface until hours into a run.
[INTERNAL-LINK: Chrome headless extension support → Selenium headless automation guide]
How Do You Rotate Proxies Across Selenium Sessions?
Selenium WebDriver doesn't support hot-swapping a proxy in an active session. The proxy is set at session start through ChromeOptions / FirefoxOptions and persists for the lifetime of that driver instance.
Rotation means creating a new driver with a new proxy for each logical scraping task:
import os
import random
from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType
PROXY_LIST = [
"dc1.example.com:7000",
"dc2.example.com:7000",
"dc3.example.com:7000",
]
def create_driver(proxy_address: str) -> webdriver.Chrome:
proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = proxy_address
proxy.ssl_proxy = proxy_address
options = webdriver.ChromeOptions()
options.Proxy = proxy
options.add_argument("--headless=new")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
return webdriver.Chrome(options=options)
def scrape_url(url: str, proxy_address: str) -> str:
driver = create_driver(proxy_address)
try:
driver.get(url)
return driver.find_element("tag name", "body").text
finally:
driver.quit()
urls = [f"https://example.com/product/{i}" for i in range(30)]
for i, url in enumerate(urls):
proxy = PROXY_LIST[i % len(PROXY_LIST)]
result = scrape_url(url, proxy)
print(f"{proxy} → {url}: {len(result)} bytes")
For backconnect rotating proxies, the endpoint address never changes — the provider assigns a fresh IP per request internally. In this case you only need one PROXY_LIST entry and can skip the rotation loop entirely:
BACKCONNECT_PROXY = "rotate.dc.example.com:9000"
for url in urls:
result = scrape_url(url, BACKCONNECT_PROXY)
Starting and quitting browser instances for every URL is expensive. In production, batch tasks by session: keep a driver alive for N pages, then rotate:
BATCH_SIZE = 10
for batch_start in range(0, len(urls), BATCH_SIZE):
proxy = random.choice(PROXY_LIST)
driver = create_driver(proxy)
try:
for url in urls[batch_start:batch_start + BATCH_SIZE]:
driver.get(url)
# process page...
finally:
driver.quit()
[INTERNAL-LINK: Selenium session management → browser automation performance guide]
How Do You Verify Your Proxy Is Active in Selenium?
Misconfigured proxies fail silently. requests.get() raises an error on connection failure, but driver.get() often loads an error page without throwing an exception — your code continues, logging your real IP.
The simplest verification is hitting httpbin.org/ip and asserting the returned IP is not your machine's public IP:
import json
import requests
from selenium import webdriver
from selenium.webdriver.common.proxy import Proxy, ProxyType
def get_my_public_ip() -> str:
return requests.get("https://httpbin.org/ip", timeout=10).json()["origin"]
def verify_proxy(driver: webdriver.Chrome) -> dict:
driver.get("https://httpbin.org/ip")
body = driver.find_element("tag name", "body").text
data = json.loads(body)
return data
real_ip = get_my_public_ip()
proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = "dc.example.com:7000"
proxy.ssl_proxy = "dc.example.com:7000"
options = webdriver.ChromeOptions()
options.Proxy = proxy
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
result = verify_proxy(driver)
proxy_ip = result.get("origin", "unknown")
if proxy_ip == real_ip:
print(f"WARNING: proxy not active — browser is using real IP {real_ip}")
else:
print(f"Proxy confirmed: {proxy_ip} (real IP hidden)")
driver.quit()
Run this check at the start of every session in production code. The overhead is a single HTTP request — negligible against the cost of running hundreds of tasks without proxy coverage.
For batch jobs, log the proxy IP on the first request of each session and compare it across the run. A proxy rotation that silently fails leaves you cycling through the same IP — detectable by sorting the IP log and looking for unexpected repetition.
Proxy verification checklist:
✅ proxy_ip != real_ip
✅ proxy_ip matches expected CIDR or provider ASN
✅ HTTPS test URL returns 200 (not an error page)
✅ ssl_proxy and http_proxy both set (not just one)
FAQ
Does Selenium 4 support SOCKS5 proxies?
Yes. Set proxy.socks_proxy (Python) or proxy.setSocksProxy() (Java) to the SOCKS5 endpoint, and set proxy.socks_version = 5. Chrome and Firefox both support SOCKS5. Note that SOCKS5 username/password authentication requires the same Chrome extension workaround as HTTP proxy authentication — the native Proxy object only supports unauthenticated SOCKS5 in Chrome. Firefox handles it natively through profile preferences.
Can you set a different proxy per browser tab in Selenium?
No. The proxy is session-scoped and applies to every tab and window in that driver instance. To use different proxies simultaneously, run separate WebDriver instances — each gets its own proxy configured via ChromeOptions or FirefoxOptions. This also means proxy rotation requires a driver.quit() + reinitialise cycle, not a live swap.
Why does my Chrome Selenium session ignore the proxy on HTTPS URLs?
The most common cause is setting only http_proxy without ssl_proxy. Chrome tunnels HTTPS through the proxy using the HTTP CONNECT method, and it reads that from the sslProxy field, not httpProxy. Set both to the same datacenter endpoint. If you're using --proxy-server as a Chrome argument instead of the Proxy object, use --proxy-server=http://host:port — this applies to both HTTP and HTTPS automatically.
What is the difference between a static and rotating datacenter proxy in Selenium?
A static datacenter proxy gives you a fixed IP for the lifetime of your subscription. Your Selenium sessions always exit from the same address — useful for account-bound automation or whitelist-based access. A rotating datacenter proxy assigns a fresh IP per connection or per session. From Selenium's perspective the configuration is identical: the same endpoint address gets different IPs server-side. Rotating fits high-volume scraping where IP burnout is a concern; static fits tasks where continuity of identity matters.
Wrapping Up
Selenium WebDriver's proxy setup is consistent across Python, Node.js, and Java — the same Proxy object model, the same http_proxy + ssl_proxy rule, the same session-scoped limitation. The language differences are syntactic rather than conceptual.
Datacenter proxies fit most Selenium automation well: at 99.88% success rate and $0.70/GB, they're fast and cheap enough to run at the kind of volume browser-based automation demands. The two gotchas worth remembering — always set both http_proxy and ssl_proxy, and verify the active IP before running production logic — save hours of debugging silent misconfiguration later.
FAQ
Does Selenium 4 support SOCKS5 proxies?
Yes. Set proxy.socks_proxy (Python) or proxy.setSocksProxy() (Java) to the SOCKS5 endpoint, and set proxy.socks_version = 5. Chrome and Firefox both support SOCKS5. Note that SOCKS5 username/password authentication requires the same Chrome extension workaround as HTTP proxy authentication — the native Proxy object only supports unauthenticated SOCKS5 in Chrome. Firefox handles it natively through profile preferences.
Can you set a different proxy per browser tab in Selenium?
No. The proxy is session-scoped and applies to every tab and window in that driver instance. To use different proxies simultaneously, run separate WebDriver instances — each gets its own proxy configured via ChromeOptions or FirefoxOptions. This also means proxy rotation requires a driver.quit() + reinitialise cycle, not a live swap.
Why does my Chrome Selenium session ignore the proxy on HTTPS URLs?
The most common cause is setting only http_proxy without ssl_proxy. Chrome tunnels HTTPS through the proxy using the HTTP CONNECT method, and it reads that from the sslProxy field, not httpProxy. Set both to the same datacenter endpoint. If you're using --proxy-server as a Chrome argument instead of the Proxy object, use --proxy-server=http://host:port — this applies to both HTTP and HTTPS automatically.
What is the difference between a static and rotating datacenter proxy in Selenium?
A static datacenter proxy gives you a fixed IP for the lifetime of your subscription. Your Selenium sessions always exit from the same address — useful for account-bound automation or whitelist-based access. A rotating datacenter proxy assigns a fresh IP per connection or per session. From Selenium's perspective the configuration is identical: the same endpoint address gets different IPs server-side. Rotating fits high-volume scraping where IP burnout is a concern; static fits tasks where continuity of identity matters.