Selenium Rotating Proxy: Rotate IPs in Selenium WebDriver (Beginner's Guide)
A beginner-friendly guide to rotating proxies in Selenium WebDriver. Set up a proxy list, handle authentication, verify IP changes, and know when a dedicated WireGuard gateway from NordLayer is the smarter choice.
Overview
Selenium WebDriver does not rotate proxies on its own. When you scrape or test at scale, a single IP address quickly hits rate limits, geo-blocks, or CAPTCHAs. This tutorial shows you how to assign a proxy to Selenium, rotate through a list of proxies, verify that the IP actually changed, and decide when a dedicated WireGuard gateway (such as NordLayer) is a better fit than a rotating proxy pool.
Why rotate proxies in Selenium?
- Avoid IP-based rate limits and temporary bans.
- Access content that is only available in specific regions.
- Test how your site or app behaves from different locations.
- Distribute requests so one IP does not look like a bot.
Rotation strategies
Choose a strategy based on how many requests you need and how long each session must stay alive.
- List-based rotation — cycle through a fixed list of proxies. Simple and free, but each proxy is reused.
- Random rotation — pick a random proxy for each session. Reduces predictable patterns.
- Round-robin — use proxies in order. Good for even distribution.
- Sticky session — keep the same proxy for a login or checkout flow, then switch.
- Rotating gateway — a single endpoint that rotates IPs for you on the provider side. Less code, but less control.
For many small projects, a random pick from a list is enough. For production scraping, consider a managed rotating proxy service or a dedicated WireGuard gateway for stable, non-rotating access.
Prerequisites
- Python 3.8 or newer.
- Google Chrome or Mozilla Firefox installed.
- A proxy list (HTTP, HTTPS, or SOCKS5) or a rotating proxy subscription.
- Basic familiarity with running Python scripts.
Steps
-
Install Selenium and a WebDriver manager.
Install Selenium and a helper that downloads the correct browser driver automatically.
pip install selenium webdriver-manager -
Prepare your proxy list.
Create a list of proxies in Python. Use the full scheme so Selenium knows how to connect.
PROXIES = [ 'http://user:[email protected]:8080', 'http://proxy2.example.com:8080', 'socks5://proxy3.example.com:1080', ]If your proxies require username and password, see Step 4 before you continue.
-
Configure a single proxy in Selenium (Chrome).
Pass the proxy to Chrome with the
--proxy-serverargument.from selenium import webdriver from selenium.webdriver.chrome.options import Options from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service proxy = 'http://proxy2.example.com:8080' options = Options() options.add_argument(f'--proxy-server={proxy}') options.add_argument('--headless=new') driver = webdriver.Chrome( service=Service(ChromeDriverManager().install()), options=options ) driver.get('https://api.ipify.org?format=json') print(driver.page_source) driver.quit()Chrome does not accept credentials inside the
--proxy-serverstring. If your proxy needs authentication, use IP whitelisting or switch to Firefox (Step 4). -
Handle proxy authentication.
Firefox profiles can send proxy credentials. This is useful for beginner-friendly setups without extra libraries.
from selenium import webdriver from selenium.webdriver.firefox.options import Options proxy_host = 'proxy2.example.com' proxy_port = 8080 options = Options() options.set_preference('network.proxy.type', 1) options.set_preference('network.proxy.http', proxy_host) options.set_preference('network.proxy.http_port', proxy_port) options.set_preference('network.proxy.ssl', proxy_host) options.set_preference('network.proxy.ssl_port', proxy_port) driver = webdriver.Firefox(options=options) driver.get('https://api.ipify.org?format=json') print(driver.page_source) driver.quit()For SOCKS5 with authentication, the simplest beginner path is to ask your proxy provider for IP-whitelisted access. That way you never embed a password in your script.
-
Rotate proxies per session.
Create a fresh WebDriver with a randomly chosen proxy for each URL or task. Always quit the driver when done.
import random from selenium import webdriver from selenium.webdriver.chrome.options import Options from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.service import Service PROXIES = [ 'http://proxy1.example.com:8080', 'http://proxy2.example.com:8080', 'socks5://proxy3.example.com:1080', ] def get_driver(): proxy = random.choice(PROXIES) options = Options() options.add_argument(f'--proxy-server={proxy}') options.add_argument('--headless=new') return webdriver.Chrome( service=Service(ChromeDriverManager().install()), options=options ) urls = [ 'https://example.com/page-1', 'https://example.com/page-2', ] for url in urls: driver = get_driver() try: driver.get(url) print(driver.title) finally: driver.quit()This pattern is easy to read, but starting a new browser for every request is slow. For larger jobs, run several drivers in parallel or use a rotating gateway endpoint. If you need a stable, non-rotating IP for logins or admin panels, jump to Step 7.
-
Verify the IP address changed.
Never assume the proxy worked. Check the egress IP before you scrape.
import json from selenium import webdriver from selenium.webdriver.chrome.options import Options options = Options() options.add_argument('--proxy-server=http://proxy2.example.com:8080') options.add_argument('--headless=new') driver = webdriver.Chrome(options=options) driver.get('https://api.ipify.org?format=json') body = driver.find_element('tag name', 'body').text ip_info = json.loads(body) print(ip_info['ip']) driver.quit()If the printed IP matches your real IP, the proxy is not being used. Check the proxy format and authentication.
-
Choose between rotating proxies and a dedicated WireGuard gateway.
Rotating proxies are ideal for anonymous, high-volume requests. But some tasks need the opposite: a stable, business-grade IP that stays the same for every request.
Use a dedicated WireGuard gateway, such as NordLayer, when you need:
- A consistent egress IP for team members or automated jobs.
- Encrypted tunnels instead of per-app proxy settings.
- Fast onboarding for a small team without maintaining proxy lists.
- A separate network path for internal tools, staging sites, or rank tracking from one region.
NordLayer provides business-grade WireGuard VPN tunnels with dedicated gateways and flat monthly billing. It is not a rotating proxy pool, so use it for sessions that must stay on one IP. Use rotating proxies when each request should come from a different address.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Proxy connection refused | Wrong host, port, or scheme | Verify the proxy string includes http:// or socks5:// |
| 407 Proxy Authentication Required | Missing credentials | Use IP whitelisting or a Firefox profile with authentication |
| WebDriver session not created | Browser/driver version mismatch | Update Selenium and webdriver-manager |
| Requests still show your real IP | Proxy not applied | Confirm --proxy-server is set before driver.get() |
| CAPTCHA or block page | Too many requests or a flagged proxy | Slow down, rotate more carefully, or use residential/ISP IPs |
| SOCKS5 proxy fails in Chrome | Chrome does not support proxy auth for SOCKS5 in the argument | Use Firefox or an authenticated corporate tunnel such as NordLayer |
Summary
- Selenium does not rotate proxies automatically; you assign one per browser session.
- For beginners, start with a small proxy list, random selection, and a fresh driver per task.
- Firefox profiles handle proxy authentication more easily than Chrome.
- Always verify the egress IP with a service like ipify before trusting the proxy.
- Rotating proxies are best for distributed, anonymous scraping.
- A dedicated WireGuard gateway like NordLayer is better when you need a stable, encrypted, business-grade IP for teams and long-lived sessions.