Mobile Proxies for Selenium and Puppeteer
A complete setup guide for using mobile proxies with Selenium and Puppeteer: Chrome authentication methods, SeleniumBase, proxy-chain for rotation, sticky vs rotating sessions, browser fingerprint considerations, and solutions to the most common proxy configuration problems including the SOCKS5 authentication limitation and selenium-wire compatibility.
Browser automation is one of the most demanding proxy use cases. Selenium and Puppeteer both drive real browser instances, which means browser sessions expose a range of browser and network signals that detection systems can evaluate together. A datacenter IP can increase the likelihood of additional scrutiny even when the browser session itself is well configured.
Mobile carrier IPs sit in ASN ranges shared by large numbers of real subscribers. Because blocking them can affect real users, platforms may apply less aggressive pre-emptive restrictions to these ranges than to datacenter IPs. A mobile carrier IP can provide a stronger network reputation baseline than a typical datacenter IP, although detection systems still evaluate it alongside other signals.
This guide covers how to configure mobile proxies with Selenium and Puppeteer, including authentication approaches, IP rotation, sticky sessions, and solutions to common setup problems.
Why Use Mobile Proxies with Selenium and Puppeteer?
Most browser automation targets have some form of bot detection. The detection surface can include IP reputation, TLS characteristics, HTTP header patterns, JavaScript environment checks, and behavioral signals. Proxies primarily address the IP reputation layer.
A datacenter IP can carry a higher baseline risk score before any behavioral analysis runs. For defended targets, mobile carrier IPs can therefore be a practical alternative when network reputation is an important factor. For workflows where a session needs to survive multiple pages, maintain a login, or complete a multi-step flow, the starting reputation of the IP matters.
Mobile Proxies vs Datacenter Proxies for Browser Automation
| Factor | Mobile Proxy | Datacenter Proxy |
|---|---|---|
| IP reputation baseline | Generally higher (carrier ASN) | Lower (hosting ASN) |
| Pre-emptive blocking risk | Generally lower | Generally higher |
| CGNAT shared pool | Yes | No |
| Session stability (sticky) | Good | Medium |
| Cost per GB | Higher | Lower |
| Best for | Defended targets, social, checkout | Unprotected targets |
How to Use a Mobile Proxy with Selenium
Selenium drives browsers through the WebDriver protocol. Proxy authentication in Chrome via Selenium has known limitations that can affect how credentials are passed, depending on the driver and browser setup.
The Chrome Authentication Challenge
Chrome's handling of proxy authentication through Selenium's standard ChromeOptions can be inconsistent depending on the driver version and setup. Common approaches include IP whitelisting, SeleniumBase's built-in proxy parameter, or a browser extension for proxy authentication.
If your provider whitelists your server's IP address, Chrome can connect to the proxy without requiring proxy credentials. This is a clean approach for production deployments where your server has a fixed public IP.
from selenium import webdriver from selenium.webdriver.chrome.options import Options options = Options() # No credentials are needed when your server IP is whitelisted. options.add_argument("--proxy-server=http://gate.powerproxy.io:8000") driver = webdriver.Chrome(options=options) driver.get("https://httpbin.org/ip") print(driver.page_source) driver.quit()
SeleniumBase is a Selenium wrapper that provides built-in proxy parameter handling and can simplify authenticated proxy configuration.
pip install seleniumbase
from seleniumbase import Driver driver = Driver(proxy="user:pass@gate.powerproxy.io:8000") driver.get("https://httpbin.org/ip") print(driver.page_source) driver.quit()
Replace user and pass with the credentials provided by your proxy provider.
If you are using vanilla Selenium and cannot use IP whitelisting or SeleniumBase, a browser extension can handle proxy authentication. Because Chrome's extension platform has evolved, the exact implementation depends on the Chrome version and extension architecture being used. For most users, IP whitelisting or SeleniumBase is the simpler option and requires less maintenance.
selenium-wire was previously popular for intercepting Selenium traffic and configuring proxies. It is no longer actively maintained and may not be compatible with current Python package versions. If you encounter import errors or runtime failures with selenium-wire, use IP whitelisting, SeleniumBase, or a browser-level authentication approach instead.
How to Use a Mobile Proxy with Puppeteer
Puppeteer drives Chrome and Chromium-based browsers through the Chrome DevTools Protocol. Proxy configuration is generally straightforward because Puppeteer exposes browser launch arguments directly and provides page.authenticate() for HTTP proxy credentials.
The simplest setup, useful when your IP is whitelisted or when the proxy endpoint does not require credentials:
const puppeteer = require("puppeteer"); (async () => { const browser = await puppeteer.launch({ args: ["--proxy-server=http://gate.powerproxy.io:8000"] }); const page = await browser.newPage(); await page.goto("https://httpbin.org/ip"); console.log(await page.content()); await browser.close(); })();
For HTTP proxies requiring a username and password, call page.authenticate() before navigating to the target page:
const puppeteer = require("puppeteer"); (async () => { const browser = await puppeteer.launch({ args: ["--proxy-server=http://gate.powerproxy.io:8000"] }); const page = await browser.newPage(); await page.authenticate({ username: "your_username", password: "your_password" }); await page.goto("https://httpbin.org/ip"); console.log(await page.content()); await browser.close(); })();
The proxy-chain library can convert an authenticated upstream proxy into a local unauthenticated endpoint. Whether each new connection receives a different carrier IP depends on how your PowerProxy endpoint is configured for rotation. The proxy-chain library handles the local proxy connection and authentication layer; it does not determine IP assignment.
npm install proxy-chain
const puppeteer = require("puppeteer"); const proxyChain = require("proxy-chain"); (async () => { const upstreamProxy = "http://user:pass@gate.powerproxy.io:8000"; const localProxy = await proxyChain.anonymizeProxy(upstreamProxy); const browser = await puppeteer.launch({ args: [`--proxy-server=${localProxy}`] }); try { const page = await browser.newPage(); await page.goto("https://httpbin.org/ip"); console.log(await page.content()); } finally { await browser.close(); await proxyChain.closeAnonymizedProxy(localProxy, true); } })();
Chromium does not support username and password authentication over SOCKS5 in the same way it supports HTTP proxy authentication. For authenticated proxy connections in Puppeteer, use an HTTP proxy endpoint. SOCKS5 can be used in configurations where authentication is handled through IP whitelisting or another supported access method.
Rotating Mobile Proxies with Selenium and Puppeteer
IP rotation for browser automation works differently from rotation in a plain HTTP requests library. Each browser instance maintains its own session state, including cookies, local storage, cache, and other browser data. Changing the IP during an active session without considering the associated session state can create inconsistencies that detection systems may evaluate.
Rotation Strategy for Selenium
A straightforward approach is to launch a new browser instance for each isolated task. Whether each new connection receives a different carrier IP depends on how your PowerProxy endpoint is configured for rotation.
from seleniumbase import Driver def run_task_with_rotation(url): # Each Driver() call creates a fresh browser instance. # IP assignment depends on your PowerProxy rotation configuration. driver = Driver(proxy="user:pass@gate.powerproxy.io:8000") try: driver.get(url) return driver.page_source finally: driver.quit()
Rotation Strategy for Puppeteer
Create a new browser connection for each isolated task rather than changing the proxy identity in the middle of an active session:
const puppeteer = require("puppeteer"); const proxyChain = require("proxy-chain"); async function runWithFreshProxy(url) { const upstreamProxy = "http://user:pass@gate.powerproxy.io:8000"; const localProxy = await proxyChain.anonymizeProxy(upstreamProxy); const browser = await puppeteer.launch({ args: [`--proxy-server=${localProxy}`] }); try { const page = await browser.newPage(); await page.goto(url); return await page.content(); } finally { await browser.close(); await proxyChain.closeAnonymizedProxy(localProxy, true); } }
Sticky Sessions vs Rotating IPs
For sticky sessions in Puppeteer and Selenium, use the dedicated or sticky-session configuration provided by your proxy provider rather than a rotating endpoint.
Browser Fingerprint Considerations
A proxy addresses the IP layer. It does not address the browser fingerprint layer on its own. Browser sessions can expose a range of signals, including TLS handshake characteristics, HTTP header patterns, JavaScript environment properties, and rendering output. Detection systems can evaluate these signals alongside the IP address.
For a full breakdown of how browser fingerprinting works, see our guide on Browser Fingerprinting Explained. When troubleshooting compatibility with a specific target, reviewing browser automation signals such as navigator.webdriver and User-Agent consistency with the proxy IP type can be a useful starting point. A mobile carrier IP paired with a mobile User-Agent and an appropriate viewport can create a more consistent browser and network configuration.
Common Problems and How to Fix Them
page.authenticate() is called before navigation and that the credentials are correct.proxy-chain with Puppeteer, verify that each browser instance creates a new proxyChain.anonymizeProxy() connection rather than reusing the same local proxy URL. IP assignment is controlled by the upstream PowerProxy endpoint configuration, not by the proxy-chain library.import requests proxies = { "http": "http://user:pass@gate.powerproxy.io:8000", "https": "http://user:pass@gate.powerproxy.io:8000" } response = requests.get( "https://httpbin.org/ip", proxies=proxies, timeout=30 ) print(response.json())
Best Practices for Browser Automation with Mobile Proxies
Selenium vs Puppeteer: Which Works Better with Mobile Proxies?
Both frameworks can work effectively with mobile proxies once authentication and session configuration are handled correctly.
| Factor | Selenium | Puppeteer | Playwright |
|---|---|---|---|
| Auth with username/password | SeleniumBase or extension | page.authenticate() | Built-in proxy parameter |
| Rotation per session | New driver instance | New browser instance | New browser instance |
| Multi-browser support | Chrome, Firefox, Edge | Chromium-based browsers | Chromium, Firefox, WebKit |
| Language | Python, Java, JS, C# | Node.js | Python, Node.js, Java, C# |
| Proxy setup complexity | Moderate | Low to moderate | Low |
If you are starting a new project and the framework choice is open, Playwright's built-in proxy configuration provides a straightforward way to configure authenticated proxies. For existing Selenium projects, SeleniumBase can reduce the complexity of authenticated proxy configuration.
Frequently Asked Questions
https://httpbin.org/ip or https://ipinfo.io/json at the start of each session. The response should show the proxy's exit IP rather than your server's public IP. If you use ipinfo.io, the organization information can also help identify whether the exit IP belongs to a mobile carrier or a hosting provider.Mobile Proxies Built for Browser Automation
Give your Selenium and Puppeteer workflows a stable mobile IP layer with flexible authentication, rotation, and session control. Power Proxy provides dedicated carrier-grade mobile proxies with HTTP, SOCKS5, and OpenVPN support and city-level geo-targeting.
Narmin Kamilsoy
Contributing author sharing insights and stories on our blog.