Conocimiento

Cómo usar proxies residenciales en Selenium (incluidos proxies autenticados)

Selenium fija el host del proxy con facilidad pero no tiene forma incorporada de pasar credenciales. Cómo manejar proxies autenticados con Selenium Wire, una extensión, o CDP.

Chris Collins

Chris Collins

7 de agosto de 2026 · 9 min de lectura

Selenium es la herramienta de automatización de navegador más desplegada que existe, y para scrapear un destino cargado de JavaScript hace el trabajo. Pero tiene una carencia de larga data que hace tropezar a casi todos la primera vez que añaden un proxy residencial: fijar el host del proxy es trivial, y proporcionar un usuario y una contraseña no lo es, porque Selenium no tiene forma incorporada de hacerlo. Apunta Chrome a un proxy autenticado y saca un diálogo de login 407 nativo que Selenium no puede rellenar, y tu script se cuelga. Aquí está cómo superar eso, de tres formas.

Esto va junto a las otras guías de navegador, proxies residenciales con Playwright y con Puppeteer, ambos manejan la auth del proxy de forma nativa. Si no necesitas un navegador completo, proxies en Python con un cliente HTTP simple es aún más sencillo.

Todo lo de abajo usa el gateway residencial de Shifter: un endpoint, p.shifter.io:443, con todo el targeting codificado en el nombre de usuario. Cambia el host y las credenciales por otro proveedor; la forma es la misma.

El modelo del gateway en un párrafo

El nombre de usuario del proxy lleva tu autenticación y tu targeting. No cambias de endpoint para cambiar de país o de sesión, cambias la cadena del nombre de usuario:

customer-USERNAME-country-us-sid-abc123-ttl-600

country-us apunta a Estados Unidos, sid fija una sesión sticky, ttl mantiene esa IP durante N segundos. Omite sid/ttl y cada conexión nueva rota. La contraseña se mantiene constante. Todo el problema en Selenium es hacer llegar ese usuario y esa contraseña al proxy.

El problema central

Fijar el host es la mitad fácil. Pasas --proxy-server en las opciones de Chrome exactamente como lo harías en otro sitio:

from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--proxy-server=http://p.shifter.io:443') # solo host
driver = webdriver.Chrome(options=options)

Eso funciona para un proxy con IP en whitelist y sin credenciales. Pero el gateway está autenticado con usuario y contraseña, y Chromium no leerá las credenciales de ese flag, así que la primera navegación se atasca en un prompt de auth 407 que Selenium no puede descartar. Necesitas una de tres formas de responder a ese desafío.

Enfoque 1: Selenium Wire (el fácil)

Selenium Wire extiende Selenium y acepta credenciales de proxy directamente, manejando la auth por ti. Es la opción de menor fricción y a la que la mayoría de los scrapers de Python recurren.

from seleniumwire import webdriver # pip install selenium-wire
import os
user = os.environ['SHIFTER_USER'] + '-country-us' # targeting en el nombre de usuario
pw = os.environ['SHIFTER_PASS']
seleniumwire_options = {
'proxy': {
'http': f'http://{user}:{pw}@p.shifter.io:443',
'https': f'http://{user}:{pw}@p.shifter.io:443',
'no_proxy': 'localhost,127.0.0.1',
}
}
driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get('https://api.ipify.org')
print(driver.page_source) # una IP residencial de EE. UU.
driver.quit()

Las credenciales, incluidos los flags de targeting en el nombre de usuario, van en la config proxy y Selenium Wire lidia con el 407 de forma transparente. También te deja cambiar el proxy en tiempo de ejecución reasignando driver.proxy, lo cual es útil para rotar sin relanzar Chrome.

Enfoque 2: una extensión de credenciales (Selenium puro, sin librería extra)

Si quieres quedarte en Selenium puro, la técnica clásica es cargar una pequeña extensión de Chrome que responda al desafío de auth con tus credenciales. La construyes al vuelo y la pasas con add_extension.

# manifest.json declara permisos de proxy + auth; background.js provee las creds.
background_js = """
chrome.webRequest.onAuthRequired.addListener(
() => ({ authCredentials: { username: USER, password: PASS } }),
{ urls: ['<all_urls>'] },
['blocking']
);
""".replace('USER', repr(user)).replace('PASS', repr(pw))
# comprime manifest.json + background.js, luego:
options.add_extension('proxy_auth.zip')

Esto te mantiene sin dependencias y funciona en cualquier binding de lenguaje de Selenium, ya que la extensión hace el trabajo. La salvedad: el patrón bloqueante de onAuthRequired de arriba es una técnica de Manifest V2, y Chrome está retirando MV2 en favor de MV3, así que en el Chrome actual este enfoque es más frágil que antes. Si empiezas de cero, prefiere Selenium Wire o la ruta CDP de abajo.

Enfoque 3: CDP en Selenium 4

Selenium 4 expone el Chrome DevTools Protocol, y puedes responder la auth del proxy a través del dominio Fetch manejando Fetch.authRequired y continuando la petición con credenciales. Es nativo del Selenium moderno y no necesita paquete extra, pero es engorroso de cablear a mano, esencialmente reimplementando lo que Selenium Wire ya envuelve. Recurre a él cuando quieras cero dependencias de terceros y estés cómodo con CDP; si no, Selenium Wire te ahorra la molestia.

Rotar geo y sesiones

Como el targeting vive en el nombre de usuario, una identidad distinta es un nombre de usuario distinto, y en Selenium el proxy se fija a nivel de navegador. Eso significa que la rotación ocurre por driver, no por pestaña. Dos patrones prácticos: con Selenium Wire, reasigna driver.proxy en tiempo de ejecución para intercambiar el nombre de usuario entre unidades de trabajo; con el enfoque de extensión o CDP, corre un driver por identidad y hazlos pool. En cualquier caso, dale a cada unidad lógica de trabajo su propio sid y rota entre unidades, no a mitad de sesión (sticky vs rotativo cubre la distinción), y mapea el trabajo a identidades como describe el post sobre reparto de carga.

Reutiliza el driver, y acota la concurrencia

Lanzar Chrome es caro, un driver fresco por petición paga tiempo de arranque y memoria reales cada vez, la sobrecarga que la guía de latencia existe para eliminar. Lanza un driver (o un pequeño pool de ellos) y reutilízalo entre peticiones. Y como cada driver es un navegador completo que retiene memoria real, no puedes correr miles, mantén un pool acotado y limita el trabajo en vuelo por host de destino para que un sitio frágil no reciba una paliza mientras uno permisivo pasa hambre. Más paralelismo más allá de la tolerancia de un destino compra bloqueos y caídas por falta de memoria, no throughput (cómo evitar que te bloqueen).

El navegador es solo la mitad de no ser bloqueado

Una IP residencial maneja la mitad de red de parecer humano, pero Selenium sigue manejando un navegador automatizado, y los sitios hacen fingerprint de eso también, navigator.webdriver, flags de automatización, y rarezas de headless. Una IP limpia con buena reputación te mantiene fuera de muchos desafíos, pero no disfraza un navegador obviamente automatizado. Mantén el user-agent y el viewport realistas, maneja la página a ritmo humano, y recuerda que los errores que disparan la detección aplican a la capa del navegador tanto como a la capa de IP. Las dos tienen que cuadrar.

Verifica que de verdad estás en el proxy

Antes de hacer benchmark o depurar cualquier otra cosa, confirma la IP de salida desde dentro del navegador:

driver.get('http://ip-api.com/json')
print(driver.find_element('tag name', 'body').text) # espera el país objetivo

Tu propia IP significa que el proxy no se aplica. Un cuelgue en un diálogo de login significa que el paso de auth (Selenium Wire, extensión, o CDP) falta o está mal configurado. Un cuelgue general significa que la salida local está bloqueada. Los tres se cubren en la guía de diagnóstico de timeouts.

Preguntas frecuentes

¿Por qué se cuelga Selenium en un popup de login de proxy? Chromium levanta un diálogo de autenticación 407 nativo para un proxy autenticado, y Selenium no puede interactuar con diálogos nativos del navegador. Tienes que responder al desafío de otra forma: Selenium Wire, una extensión de credenciales, o el Fetch.authRequired de CDP. Fijar --proxy-server solo provee el host, no las credenciales.

¿Puedo poner user:pass@host en --proxy-server? No. Chromium no lee las credenciales del flag --proxy-server. Provee el host ahí y suministra el usuario y la contraseña por uno de los tres enfoques de arriba. Como el gateway codifica el targeting en el nombre de usuario, el nombre de usuario completo (con -country-...) es lo que pasas como usuario del proxy.

¿Tengo que usar Selenium Wire? No, pero es el camino más simple en Python. Las alternativas sin dependencias son una extensión de credenciales (funciona en cualquier binding de lenguaje, aunque el patrón clásico MV2 se está retirando) o CDP en Selenium 4 (nativo pero con más trabajo de cableado).

¿Cómo roto IPs en Selenium? Varía el nombre de usuario del proxy, lo que cambia la identidad a través del mismo gateway. En Selenium Wire puedes reasignar driver.proxy en tiempo de ejecución; si no, corre un driver por identidad y hazlos pool. Omite el sid en el nombre de usuario para rotar en cada conexión nueva.

¿Selenium, Playwright, o Puppeteer? Playwright y Puppeteer ambos toman las credenciales del proxy de forma nativa, así que evitan todo este baile; Selenium necesita uno de los rodeos de aquí. Selenium sigue siendo una buena elección si es lo que tu stack ya usa; si empiezas de cero y quieres auth de proxy sin dolor, los otros dos son más suaves.

En resumen

Selenium más proxies residenciales funciona bien en cuanto resuelves la única carencia que tiene: tomará el host del proxy en --proxy-server, pero necesita ayuda para proveer credenciales para un proxy autenticado. Usa Selenium Wire para la menor fricción, una extensión de credenciales si quieres quedarte sin dependencias, o CDP en Selenium 4 para una ruta nativa. Luego rota geo y sesiones variando el nombre de usuario, reutiliza un driver de larga vida, acota tu concurrencia porque cada uno es un navegador real, y mantén el fingerprint del navegador tan humano como la IP.

Hazlo bien y Selenium maneja los destinos interactivos y cargados de JavaScript que los clientes HTTP simples no pueden. Apúntalo al gateway residencial, y recuerda que la calidad del pool decide con qué frecuencia te desafían siquiera (reputación de IP). La página de precios tiene los planes por GB para probarlo contra tus propios destinos.

¿Listo para empezar?

Prueba los proxies residenciales de Shifter, más de 205M IPs, más de 195 países, desde 0,75 $/GB.

Comenzar