How to Use Proxies with Selenium in 2026: Complete Guide
Selenium is the most established browser automation framework, with support across Python, Java, C#, Ruby, and JavaScript. Despite newer alternatives, Selenium remains the standard for QA testing and is still heavily used for web scraping. Proxy integration is essential for both use cases — testing from different locations or scraping without getting blocked.
This guide covers proxy configuration for Selenium 4+ in Python and Java, including advanced setups with Selenium Wire and authenticated proxy handling.
Why You Need Proxies with Selenium
Selenium drives a real browser, so websites see a legitimate browser fingerprint. But your IP address is still exposed, and that is where problems start:
- Rate limiting: After a few hundred requests from the same IP, most sites throttle or block
- Geo-restrictions: Testing localized content requires IPs from target countries
- IP reputation: Datacenter IPs are often pre-flagged by anti-bot systems
- Parallel testing: Multiple Selenium instances from one IP raise red flags
Use our proxy cost calculator to estimate bandwidth requirements for your test suite or scraping project.
Prerequisites
Python Setup
- Python 3.9+
- Selenium 4.x
- ChromeDriver or GeckoDriver matching your browser version
pip install selenium webdriver-managerJava Setup
- Java 17+
- Selenium 4.x via Maven or Gradle
- ChromeDriver or GeckoDriver
<!-- Maven dependency -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.20.0</version>
</dependency>Basic Proxy Configuration
Python — Chrome with Proxy
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
options = Options()
options.add_argument("--proxy-server=http://proxy.example.com:8080")
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()Python — Firefox with Proxy
Firefox uses a different proxy configuration through preferences:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service
from webdriver_manager.firefox import GeckoDriverManager
options = Options()
options.set_preference("network.proxy.type", 1)
options.set_preference("network.proxy.http", "proxy.example.com")
options.set_preference("network.proxy.http_port", 8080)
options.set_preference("network.proxy.ssl", "proxy.example.com")
options.set_preference("network.proxy.ssl_port", 8080)
options.set_preference("network.proxy.no_proxies_on", "localhost,127.0.0.1")
service = Service(GeckoDriverManager().install())
driver = webdriver.Firefox(service=service, options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()Java — Chrome with Proxy
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
public class ProxyExample {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.setHttpProxy("proxy.example.com:8080");
proxy.setSslProxy("proxy.example.com:8080");
ChromeOptions options = new ChromeOptions();
options.setProxy(proxy);
WebDriver driver = new ChromeDriver(options);
driver.get("https://httpbin.org/ip");
System.out.println(driver.findElement(org.openqa.selenium.By.tagName("body")).getText());
driver.quit();
}
}Java — Firefox with Proxy
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
public class FirefoxProxyExample {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.setHttpProxy("proxy.example.com:8080");
proxy.setSslProxy("proxy.example.com:8080");
FirefoxOptions options = new FirefoxOptions();
options.setProxy(proxy);
WebDriver driver = new FirefoxDriver(options);
driver.get("https://httpbin.org/ip");
System.out.println(driver.findElement(org.openqa.selenium.By.tagName("body")).getText());
driver.quit();
}
}SOCKS5 Proxy Configuration
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--proxy-server=socks5://proxy.example.com:1080")
driver = webdriver.Chrome(options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()Authenticated Proxy Handling
Selenium does not natively support proxy authentication for HTTP proxies with Chrome. The workaround is a Chrome extension that automatically fills in credentials.
Python — Chrome Extension for Proxy Auth
import zipfile
import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def create_proxy_auth_extension(proxy_host, proxy_port, proxy_user, proxy_pass, scheme="http"):
"""Create a Chrome extension for proxy authentication."""
manifest_json = """{
"version": "1.0.0",
"manifest_version": 2,
"name": "Proxy Auth Extension",
"permissions": [
"proxy",
"tabs",
"unlimitedStorage",
"storage",
"<all_urls>",
"webRequest",
"webRequestBlocking"
],
"background": {
"scripts": ["background.js"]
}
}"""
background_js = """
var config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "%s",
host: "%s",
port: parseInt(%s)
},
bypassList: ["localhost"]
}
};
chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
function callbackFn(details) {
return {
authCredentials: {
username: "%s",
password: "%s"
}
};
}
chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls: ["<all_urls>"]},
['blocking']
);
""" % (scheme, proxy_host, proxy_port, proxy_user, proxy_pass)
ext_path = "/tmp/proxy_auth_extension.zip"
with zipfile.ZipFile(ext_path, "w") as zp:
zp.writestr("manifest.json", manifest_json)
zp.writestr("background.js", background_js)
return ext_path
# Create the extension
ext_path = create_proxy_auth_extension(
proxy_host="proxy.example.com",
proxy_port="8080",
proxy_user="your_username",
proxy_pass="your_password"
)
# Launch Chrome with the extension
options = Options()
options.add_extension(ext_path)
driver = webdriver.Chrome(options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()
# Cleanup
os.remove(ext_path)Note: This extension approach does not work in headless mode with Chrome. For headless authenticated proxy, use Selenium Wire (covered below).
Firefox — Proxy Authentication with Profile
Firefox handles proxy auth differently. You can pre-configure it with a profile:
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
options = Options()
options.set_preference("network.proxy.type", 1)
options.set_preference("network.proxy.http", "proxy.example.com")
options.set_preference("network.proxy.http_port", 8080)
options.set_preference("network.proxy.ssl", "proxy.example.com")
options.set_preference("network.proxy.ssl_port", 8080)
# For Firefox, use an extension or Selenium Wire for authenticated proxies
driver = webdriver.Firefox(options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()Selenium Wire for Advanced Proxy Control
Selenium Wire extends Selenium with the ability to inspect, modify, and intercept requests. It also provides clean proxy authentication support:
pip install selenium-wireBasic Authenticated Proxy with Selenium Wire
from seleniumwire import webdriver
options = {
"proxy": {
"http": "http://username:password@proxy.example.com:8080",
"https": "http://username:password@proxy.example.com:8080",
"no_proxy": "localhost,127.0.0.1"
}
}
driver = webdriver.Chrome(seleniumwire_options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
# Access request details
for request in driver.requests:
if request.response:
print(f"{request.url} -> {request.response.status_code}")
driver.quit()SOCKS5 Proxy with Selenium Wire
from seleniumwire import webdriver
options = {
"proxy": {
"http": "socks5://username:password@proxy.example.com:1080",
"https": "socks5://username:password@proxy.example.com:1080",
}
}
driver = webdriver.Chrome(seleniumwire_options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()Dynamic Proxy Switching with Selenium Wire
One of Selenium Wire’s best features is the ability to change proxies mid-session without restarting the browser:
from seleniumwire import webdriver
driver = webdriver.Chrome()
# First request with proxy 1
driver.proxy = {
"http": "http://user:pass@proxy1.example.com:8080",
"https": "http://user:pass@proxy1.example.com:8080"
}
driver.get("https://httpbin.org/ip")
print("Proxy 1:", driver.find_element("tag name", "body").text)
# Switch to proxy 2 without restarting
driver.proxy = {
"http": "http://user:pass@proxy2.example.com:8080",
"https": "http://user:pass@proxy2.example.com:8080"
}
driver.get("https://httpbin.org/ip")
print("Proxy 2:", driver.find_element("tag name", "body").text)
driver.quit()Proxy Rotation with Selenium
Round-Robin Rotation
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import itertools
proxies = [
"http://proxy1.example.com:8080",
"http://proxy2.example.com:8080",
"http://proxy3.example.com:8080",
]
proxy_cycle = itertools.cycle(proxies)
urls = [
"https://example.com/page1",
"https://example.com/page2",
"https://example.com/page3",
"https://example.com/page4",
"https://example.com/page5",
]
for url in urls:
proxy = next(proxy_cycle)
options = Options()
options.add_argument(f"--proxy-server={proxy}")
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)
try:
driver.get(url)
print(f"[{proxy}] {url}: {driver.title}")
except Exception as e:
print(f"[{proxy}] {url}: ERROR - {e}")
finally:
driver.quit()Rotation with Selenium Wire (Reuse Browser)
from seleniumwire import webdriver
import random
proxies = [
{"http": "http://user:pass@proxy1.example.com:8080", "https": "http://user:pass@proxy1.example.com:8080"},
{"http": "http://user:pass@proxy2.example.com:8080", "https": "http://user:pass@proxy2.example.com:8080"},
{"http": "http://user:pass@proxy3.example.com:8080", "https": "http://user:pass@proxy3.example.com:8080"},
]
driver = webdriver.Chrome()
urls = [f"https://example.com/page{i}" for i in range(1, 11)]
for url in urls:
driver.proxy = random.choice(proxies)
try:
driver.get(url)
print(f"{url}: {driver.title}")
except Exception as e:
print(f"{url}: ERROR - {e}")
driver.quit()Proxy Rotation with Selenium Grid
For large-scale parallel testing with different proxies, Selenium Grid 4 can distribute tests across nodes, each configured with a different proxy.
docker-compose.yml for Grid with Proxy Nodes
version: "3"
services:
hub:
image: selenium/hub:4.20
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
chrome-us:
image: selenium/node-chrome:4.20
depends_on:
- hub
environment:
- SE_EVENT_BUS_HOST=hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- SE_NODE_MAX_SESSIONS=4
- SE_OPTS=--proxy-server=http://us-proxy.example.com:8080
chrome-uk:
image: selenium/node-chrome:4.20
depends_on:
- hub
environment:
- SE_EVENT_BUS_HOST=hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- SE_NODE_MAX_SESSIONS=4
- SE_OPTS=--proxy-server=http://uk-proxy.example.com:8080Connect to Grid with proxy awareness
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
# The proxy is set at the Grid node level, so no additional config needed here
driver = webdriver.Remote(
command_executor="http://localhost:4444/wd/hub",
options=options
)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()Headless Mode Proxy Considerations
Headless Chrome with proxies works well, but there are caveats:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless=new")
options.add_argument("--proxy-server=http://proxy.example.com:8080")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
# Important: Set window size in headless mode
options.add_argument("--window-size=1920,1080")
# Set a real user-agent (headless Chrome has a different default)
options.add_argument(
"--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
)
driver = webdriver.Chrome(options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()Key headless issues:
- The Chrome extension approach for proxy auth does NOT work in headless mode. Use Selenium Wire instead.
- Headless Chrome sends a different user-agent string. Always override it.
- Some anti-bot systems detect headless mode via JavaScript. Use
--disable-blink-features=AutomationControlled.
Verify your headless configuration against the browser fingerprint tester to check for leaks.
Edge Browser Proxy Configuration
Microsoft Edge uses the same Chromium engine, so proxy configuration is identical:
from selenium import webdriver
from selenium.webdriver.edge.options import Options
from selenium.webdriver.edge.service import Service
from webdriver_manager.microsoft import EdgeChromiumDriverManager
options = Options()
options.add_argument("--proxy-server=http://proxy.example.com:8080")
service = Service(EdgeChromiumDriverManager().install())
driver = webdriver.Edge(service=service, options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()Troubleshooting Common Issues
Proxy Not Working — Page Loads Without Proxy
Cause: The proxy argument format is wrong or the proxy is being bypassed for the target URL.
Fix: Double-check the format. For Chrome, use --proxy-server=http://host:port. Do not include credentials in the URL (use the extension method or Selenium Wire).
ERR_TUNNEL_CONNECTION_FAILED with HTTPS Sites
Cause: The proxy does not support CONNECT tunneling for HTTPS.
Fix: Use a proxy that supports HTTPS tunneling, or use Selenium Wire which handles this transparently.
WebDriver Exception: Session Not Created
Cause: ChromeDriver version mismatch with Chrome browser.
Fix: Use webdriver-manager to auto-download the correct driver:
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=options)Selenium Wire SSL Errors
Cause: Selenium Wire uses a man-in-the-middle proxy for request interception, which can cause SSL certificate warnings.
Fix: Add this option:
seleniumwire_options = {
"proxy": {...},
"verify_ssl": False
}Slow Performance with Proxy
Cause: The proxy server has high latency or bandwidth limitations.
Fix:
- Use datacenter proxies for speed-critical tasks
- Disable image loading:
options.add_argument("--blink-settings=imagesEnabled=false") - Reduce page load timeout:
driver.set_page_load_timeout(15)
Memory Issues with Many Driver Instances
Cause: Not calling driver.quit() properly.
Fix: Always use try/finally or context managers:
try:
driver = webdriver.Chrome(options=options)
driver.get(url)
# ... do work ...
finally:
driver.quit()Summary
Selenium’s proxy support varies by browser and requires workarounds for authentication with Chrome. Here is the recommended approach based on your needs:
| Need | Solution |
|---|---|
| Basic unauthenticated proxy | --proxy-server Chrome arg |
| Authenticated proxy (headed) | Chrome extension approach |
| Authenticated proxy (headless) | Selenium Wire |
| Dynamic proxy switching | Selenium Wire |
| SOCKS5 proxy | --proxy-server=socks5:// or Selenium Wire |
| Parallel proxy rotation | Selenium Grid or multiple driver instances |
| Firefox proxy | Firefox preferences |
For cost planning, use the proxy cost calculator. To test your browser automation fingerprint, visit the browser fingerprint tester.
- How to Use Proxies with cURL in 2026: Complete Guide
- How to Use Proxies with Node.js Axios in 2026: Complete Guide
- Best Proxies for Amazon 2026: Complete Guide
- Best Proxies for Discord 2026: Bot Hosting & Account Management
- Best Proxies for eBay 2026: Complete Guide
- Best Proxies for Netflix 2026: Geo-Unblocking & Catalog Access
- How to Use Proxies with cURL in 2026: Complete Guide
- How to Use Proxies with Node.js Axios in 2026: Complete Guide
- Best Proxies for Amazon 2026: Complete Guide
- Best Proxies for Discord 2026: Bot Hosting & Account Management
- Best Proxies for eBay 2026: Complete Guide
- Best Proxies for Netflix 2026: Geo-Unblocking & Catalog Access
- How to Use Proxies with cURL in 2026: Complete Guide
- How to Use Proxies with Node.js Axios in 2026: Complete Guide
- Best Proxies for Amazon 2026: Complete Guide
- Best Proxies for Discord 2026: Bot Hosting & Account Management
- Best Proxies for eBay 2026: Complete Guide
- Best Proxies for Netflix 2026: Geo-Unblocking & Catalog Access
Related Reading
- How to Use Proxies with cURL in 2026: Complete Guide
- How to Use Proxies with Node.js Axios in 2026: Complete Guide
- Best Proxies for Amazon 2026: Complete Guide
- Best Proxies for Discord 2026: Bot Hosting & Account Management
- Best Proxies for eBay 2026: Complete Guide
- Best Proxies for Netflix 2026: Geo-Unblocking & Catalog Access