How to Use Proxies with Selenium in 2026: Complete Guide

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-manager

Java 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-wire

Basic 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:8080

Connect 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:

NeedSolution
Basic unauthenticated proxy--proxy-server Chrome arg
Authenticated proxy (headed)Chrome extension approach
Authenticated proxy (headless)Selenium Wire
Dynamic proxy switchingSelenium Wire
SOCKS5 proxy--proxy-server=socks5:// or Selenium Wire
Parallel proxy rotationSelenium Grid or multiple driver instances
Firefox proxyFirefox preferences

For cost planning, use the proxy cost calculator. To test your browser automation fingerprint, visit the browser fingerprint tester.


Related Reading

Scroll to Top