In this Article
Un proxy con Selenium Wire es el camino más corto para ejecutar automatización de navegador autenticada en Python, porque Selenium Wire admite directamente una URL de proxy con login:password en una sola opción, en lugar de forzar el rodeo de la extensión que exige Selenium a secas. Además expone cada solicitud y respuesta HTTP que hace el navegador, y por eso los equipos de scraping y de QA recurren a él.
Esta guía es un recorrido completo. Cubre instalar y fijar la librería de forma segura, configurar un proxy autenticado, verificar la IP de salida, inspeccionar y esperar solicitudes, editar cabeceras, rotar IP, ejecutar en modo headless, reducir el consumo de memoria, gestionar el certificado HTTPS con honestidad, combinarlo con undetected-chromedriver y dónde encajan las alternativas modernas.
DataImpulse es un proveedor ético de proxies que ofrece más de 90 millones de direcciones IP residenciales, móviles y de datacenter en 195 países. Utiliza un modelo de pago por uso desde 1 dólar por GB con tráfico que no caduca, y se usa para web scraping, verificación de anuncios, monitoreo de precios, investigación de mercado y gestión de múltiples cuentas.
Datos clave
- Proxy con Selenium Wire: Selenium Wire acepta una URL de proxy con login:password directamente en seleniumwire_options, de modo que la automatización de navegador autenticada funciona sin el rodeo de la extensión que necesita Selenium a secas.
- Mejor tipo de proxy: proxies residenciales rotativos, que usan IP reales de consumidores capaces de superar la detección.
- Precio: desde 1 dólar por GB, pago por uso, con tráfico que no caduca y sin suscripción.
- Cobertura: más de 90 millones de IP de origen ético en 195 países.
- Fiabilidad: 99,51% de tasa de éxito, con una valoración de 4,8 sobre 5 en G2.
- Protocolos y segmentación: HTTP, HTTPS y SOCKS5, con segmentación por país incluida.

¿Qué es Selenium Wire y sigue teniendo mantenimiento?
Selenium Wire es una librería de Python que amplía Selenium para que tu script pueda inspeccionar, esperar y modificar las solicitudes y respuestas HTTP del navegador, y añade soporte de proxy autenticado de primera clase. Funciona ejecutando un proxy local de tipo man-in-the-middle al que se apunta el navegador, y luego reenvía el tráfico a tu proxy upstream real.
La advertencia honesta es que el proyecto original está archivado y ya no recibe mantenimiento activo. Sigue funcionando bien en producción, pero conviene fijar las versiones y probar de forma aislada cualquier actualización de Selenium, Chrome o dependencias antes de llevarla a producción. Existen forks de la comunidad que arrastran las correcciones de compatibilidad, y más adelante en esta guía la tabla comparativa muestra cuándo una herramienta con mantenimiento como Playwright es el mejor hogar a largo plazo.
La razón por la que los equipos siguen eligiéndolo es la comodidad. Si ya tienes una suite de pruebas o un scraper con Selenium, añadir Selenium Wire es un cambio de import de una línea más una opción de proxy, y ganas de inmediato tanto el soporte de proxy autenticado como la capacidad de leer cada solicitud que hace la página. Reconstruir esa visibilidad a nivel de solicitud en Selenium a secas es trabajo real, así que para bases de código existentes el trueque suele valer la pena a pesar del estado archivado. Si te inicias en el manejo de navegadores reales para recopilar datos, nuestra guía sobre cómo hacer scraping de páginas web dinámicas cubre el panorama más amplio del renderizado y cuándo un navegador es siquiera necesario.
¿Cómo instalar Selenium Wire y fijar las versiones para evitar rupturas?
Instala selenium-wire junto a selenium y fija blinker por debajo de 1.8, porque esa versión eliminó un nombre interno que Selenium Wire importa al arrancar. Como el proyecto está archivado, las dependencias sin fijar son el motivo más común de que una configuración que funcionaba falle de repente.
El fallo clásico es un ImportError sobre WeakNamespace después de que blinker se actualice solo. Fijar las versiones lo evita:
# Selenium Wire is archived. Pin known-good versions so an upstream release
# does not break your build overnight.
#
# blinker >= 1.8 removed blinker._saferef / WeakNamespace, which Selenium Wire
# imports at startup. On blinker 1.8+ you get:
# ImportError: cannot import name 'WeakNamespace' from 'blinker'
# The fix is to hold blinker below 1.8.
pip install "selenium-wire==5.1.0" "selenium==4.9.1" "blinker==1.7.0"
# Selenium Wire also depends on brotli and can trip on very new Selenium.
# If you must run current Selenium, test in a throwaway virtualenv first, or
# move to a maintained fork such as selenium-wire-2 that tracks these fixes.
Mantén estas versiones fijadas en un archivo de requisitos para que la integración continua y tus compañeros obtengan la misma combinación probada. Cuando quieras pasar al Selenium actual, trátalo como una actualización deliberada con su propia ronda de pruebas, en lugar de dejar que pip resuelva lo más reciente de todo.
¿Cómo configurar un proxy autenticado en Selenium Wire?
Pasa un diccionario de proxy dentro de seleniumwire_options al crear el driver, con el usuario y la contraseña incrustados en la URL y localhost excluido mediante no_proxy. Esta es la única función que hace que valga la pena usar Selenium Wire en lugar de Selenium a secas para trabajar con proxies.
Importa webdriver desde seleniumwire, no desde selenium, y luego pásale las opciones. Las credenciales, el host y el puerto salen del panel de tu proveedor. Con DataImpulse el host es gw.dataimpulse.com y el puerto es 823:
from seleniumwire import webdriver # import from seleniumwire, not selenium
proxy_url = "http://login:[email protected]:823"
seleniumwire_options = {
"proxy": {
"http": proxy_url,
"https": proxy_url,
"no_proxy": "localhost,127.0.0.1",
}
}
driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get("https://example.com")
print(driver.title)
driver.quit()
La entrada no_proxy mantiene las direcciones locales fuera del proxy para que el driver pueda hablar directamente con ChromeDriver. Si la autenticación es incorrecta, normalmente verás una respuesta 407; nuestra nota sobre el error 407 Proxy Authentication Required explica cómo diagnosticarlo. Para entender en general cómo funcionan los proxies con credenciales, consulta los proxies residenciales.
¿Cómo verificar que la IP de salida del proxy funciona?
Apunta el driver a un endpoint que devuelva la IP, como api.ipify.org, y confirma que la dirección devuelta pertenece al proxy y no a tu propia máquina. Nunca des por hecho que el proxy está activo solo porque la página cargó.
import json
from seleniumwire import webdriver
proxy_url = "http://login:[email protected]:823"
seleniumwire_options = {
"proxy": {"http": proxy_url, "https": proxy_url,
"no_proxy": "localhost,127.0.0.1"}
}
driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get("https://api.ipify.org/?format=json")
body = driver.find_element("tag name", "body").text
exit_ip = json.loads(body)["ip"]
print("Exit IP:", exit_ip) # should be the proxy, not your own address
driver.quit()
Si la respuesta muestra tu IP real, conviene comprobar tres cosas: que no_proxy no esté coincidiendo por accidente con tu objetivo, que las credenciales sean correctas y que hayas importado webdriver desde seleniumwire. Ejecuta esta comprobación como primer paso de cualquier trabajo nuevo, y repítela tras cambiar la configuración del proxy.
¿Cómo inspeccionar y esperar solicitudes específicas?
Lee driver.requests para recorrer cada solicitud y respuesta que hizo el navegador, y usa driver.wait_for_request para bloquear hasta que aparezca una llamada que coincida. Esta es la capacidad que separa a Selenium Wire de un WebDriver normal, y resulta invaluable para encontrar la API JSON que hay detrás de una página.
from seleniumwire import webdriver
driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get("https://example.com/products")
# Block until a request whose URL matches the regex is captured.
request = driver.wait_for_request(r"/api/v2/products", timeout=15)
print(request.method, request.url)
print("Status:", request.response.status_code)
print("Type:", request.response.headers["Content-Type"])
# Walk every captured request/response pair the browser made.
for r in driver.requests:
if r.response:
print(r.response.status_code, r.url)
driver.quit()
La llamada wait_for_request toma una expresión regular que se compara con la URL y devuelve en cuanto se captura la solicitud, de modo que evitas los frágiles sleeps fijos. Una vez que sabes qué llamada en segundo plano transporta los datos, a menudo puedes saltarte el renderizado por completo y golpear ese endpoint directamente, lo cual es mucho más barato. Esa técnica es central en las mejores prácticas de web scraping.
¿Cómo modificar las cabeceras de las solicitudes con un interceptor?
Asigna una función a driver.request_interceptor y se ejecutará antes de que cada solicitud salga del navegador, lo que te permite sobrescribir cabeceras, inyectar tokens o descartar parámetros. Establecer un User-Agent y un idioma realistas es un motivo habitual para recurrir a esto.
from seleniumwire import webdriver
driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
def interceptor(request):
# Delete first, then set, so you replace the header instead of duplicating it.
del request.headers["User-Agent"]
request.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
request.headers["Accept-Language"] = "en-US,en;q=0.9"
driver.request_interceptor = interceptor
driver.get("https://httpbin.org/headers")
print(driver.find_element("tag name", "body").text)
driver.quit()
Elimina la cabecera existente antes de fijar un valor nuevo, de lo contrario Selenium Wire puede enviar tanto la original como tu reemplazo. Un response_interceptor equivalente te permite leer o reescribir respuestas. Mantén los interceptores ligeros, ya que se ejecutan en cada solicitud, incluidas imágenes y scripts. Unas cabeceras coherentes y con aspecto humano son una de las señales más discretas dentro de las mejores prácticas de web scraping.
¿Cómo rotar proxies por solicitud en Selenium Wire?
Tienes dos patrones: reasignar driver.proxy en tiempo de ejecución para cambiar la configuración en el mismo navegador, o recrear el driver cuando además quieras un perfil y un almacén de cookies limpios. Un gateway rotativo como DataImpulse ya entrega una salida residencial nueva en cada conexión, así que la mayoría de los trabajos solo necesitan cambiar la configuración para usar otro país.
from seleniumwire import webdriver
base = "http://login:[email protected]:823"
opts = {"proxy": {"http": base, "https": base,
"no_proxy": "localhost,127.0.0.1"}}
driver = webdriver.Chrome(seleniumwire_options=opts)
# Option A: reassign driver.proxy at runtime to switch config (for example a
# different country gateway) without rebuilding the browser. Cheap and fast.
uk = "http://login:[email protected]:823"
driver.proxy = {"http": uk, "https": uk, "no_proxy": "localhost,127.0.0.1"}
driver.get("https://api.ipify.org")
print(driver.find_element("tag name", "body").text)
driver.quit()
# Option B: recreate the driver per job when you need a guaranteed clean
# browser profile and cookie jar as well as a fresh exit IP.
def fresh_driver():
return webdriver.Chrome(seleniumwire_options=opts)
for _ in range(3):
d = fresh_driver()
d.get("https://api.ipify.org")
print(d.find_element("tag name", "body").text)
d.quit()
Reasignar driver.proxy es barato y mantiene el navegador caliente, lo que encaja en bucles de alto volumen donde domina el coste de arranque. Recrear el driver es más pesado, pero garantiza el aislamiento entre trabajos, lo cual importa cuando un objetivo ata las sesiones tanto a cookies y almacenamiento local como a la IP. Elige según si necesitas una identidad limpia o solo una dirección nueva. Una regla práctica es reasignar el proxy mientras recopilas páginas públicas anónimas, y recrear el driver siempre que cruces un límite de cuenta o de inicio de sesión, para que una cookie filtrada de una ejecución no pueda seguirte hasta la siguiente. Los objetivos móviles que aplican fingerprinting agresivo a menudo justifican los proxies móviles para los casos más difíciles, mientras que las páginas más ligeras pueden quedarse en salidas más baratas.
¿Cómo ejecutar Selenium Wire en modo headless y mantener bajo el consumo de memoria?
Añade opciones de Chrome para el modo headless y la estabilidad, y luego limita lo que Selenium Wire captura para que el búfer de solicitudes no crezca sin límite. En servidores, headless más una captura acotada es la diferencia entre un trabajo que corre durante horas y otro que agota la RAM.
Empieza con un conjunto sólido de flags de Chrome para un contenedor headless o un entorno de CI:
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument("--headless=new") # modern headless mode
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--window-size=1920,1080")
proxy_url = "http://login:[email protected]:823"
seleniumwire_options = {
"proxy": {"http": proxy_url, "https": proxy_url,
"no_proxy": "localhost,127.0.0.1"}
}
driver = webdriver.Chrome(options=chrome_options,
seleniumwire_options=seleniumwire_options)
driver.get("https://api.ipify.org")
print(driver.find_element("tag name", "body").text)
driver.quit()
Por defecto, Selenium Wire captura y almacena en búfer cada solicitud y respuesta, que es justo lo que consume memoria en ejecuciones largas. Restringe la captura con driver.scopes, mantén el almacenamiento en memoria y limpia el búfer entre páginas:
from seleniumwire import webdriver
seleniumwire_options = {
"proxy": {"http": proxy_url, "https": proxy_url,
"no_proxy": "localhost,127.0.0.1"},
"request_storage": "memory", # keep the buffer in RAM, not on disk
}
driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
# Only capture the API traffic you care about. Images, fonts, analytics, and
# tracking pixels are ignored, which keeps the capture buffer small.
driver.scopes = [r".*/api/.*"]
driver.get("https://example.com/products")
for request in driver.requests:
print(request.url)
del driver.requests # clear the buffer between pages on long-running jobs
driver.quit()
La lista scopes es un conjunto de expresiones regulares de URL; todo lo que quede fuera de ellas pasa pero no se almacena. En un scraper que solo necesita las respuestas de la API, esto puede recortar drásticamente el búfer residente. Reducir lo que descargas también baja el coste del proxy, ya que el tráfico de DataImpulse se factura por gigabyte.
¿Cómo gestiona Selenium Wire el HTTPS y su certificado?
Para leer los cuerpos cifrados de solicitudes y respuestas, Selenium Wire descifra el HTTPS como man-in-the-middle usando su propio certificado raíz, que inyecta automáticamente en el perfil del navegador para Chrome y Firefox. Esto es potente, pero tiene límites honestos que debes entender antes de depender de ello.
from seleniumwire import webdriver
proxy_url = "http://login:[email protected]:823"
seleniumwire_options = {
"proxy": {"http": proxy_url, "https": proxy_url,
"no_proxy": "localhost,127.0.0.1"},
# Selenium Wire is a man-in-the-middle proxy: to read HTTPS bodies it
# decrypts traffic using its own root certificate, which it injects into
# the browser profile automatically. These two options relax verification
# on the upstream leg so a mismatched or self-signed cert does not abort.
"verify_ssl": False,
"suppress_connection_errors": True,
}
driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get("https://example.com")
driver.quit()
Del diseño man-in-the-middle se derivan dos cosas. Primero, un sitio que usa certificate pinning rechazará el certificado inyectado y la interceptación de ese tráfico fallará; en ese caso desactiva la captura para el host afectado o renuncia a inspeccionar sus cuerpos. Segundo, si lanzas Chrome con un perfil personalizado o no predeterminado, quizá tengas que asegurarte de que la CA de Selenium Wire sea de confianza allí. Las opciones verify_ssl y suppress_connection_errors relajan el tramo upstream para que un certificado extraño no aborte la ejecución, pero no derrotan al pinning.
¿Se puede combinar con undetected-chromedriver, y cuáles son las alternativas?
Sí. Selenium Wire incluye una integración con undetected-chromedriver que importas como seleniumwire.undetected_chromedriver, lo que te da inspección de solicitudes y proxies autenticados mientras undetected-chromedriver reduce las huellas de automatización. Es la combinación de referencia para objetivos bien defendidos.
# Selenium Wire ships its own undetected-chromedriver integration.
import seleniumwire.undetected_chromedriver as uc
proxy_url = "http://login:[email protected]:823"
seleniumwire_options = {
"proxy": {"http": proxy_url, "https": proxy_url,
"no_proxy": "localhost,127.0.0.1"}
}
options = uc.ChromeOptions()
options.add_argument("--headless=new")
driver = uc.Chrome(seleniumwire_options=seleniumwire_options, options=options)
driver.get("https://api.ipify.org")
print(driver.find_element("tag name", "body").text)
driver.quit()
Cuando el propio Selenium Wire no es la opción adecuada, dos alternativas cubren la mayoría de necesidades. Selenium 4 a secas puede usar un proxy autenticado a través de una pequeña extensión generada, que una librería auxiliar automatiza:
from selenium import webdriver
# Plain Selenium cannot send proxy credentials on its own. A small helper builds
# a throwaway Chrome extension that answers the proxy auth challenge for you.
from selenium_authenticated_proxy import SeleniumAuthenticatedProxy
proxy = SeleniumAuthenticatedProxy(
proxy_url="http://login:[email protected]:823"
)
options = webdriver.ChromeOptions()
proxy.enrich_options(options)
driver = webdriver.Chrome(options=options)
driver.get("https://api.ipify.org")
print(driver.find_element("tag name", "body").text)
driver.quit()
Playwright gestiona los proxies autenticados de forma nativa y recibe mantenimiento activo, lo que lo convierte en la mejor base para proyectos nuevos:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
proxy={
"server": "http://gw.dataimpulse.com:823",
"username": "login",
"password": "password",
},
)
page = browser.new_page()
page.goto("https://api.ipify.org")
print(page.inner_text("body"))
browser.close()
Así se comparan los tres específicamente para el trabajo con proxies autenticados:
| Herramienta | Proxy autenticado | Inspección de solicitudes | Mantenimiento | Mejor para |
|---|---|---|---|---|
| Selenium 4 a secas | necesita un ayudante de extensión de autenticación | no | activo | flujos simples, sin captura de solicitudes |
| Selenium Wire | integrado, una sola opción | acceso completo a solicitudes y respuestas | archivado, fija las versiones | depuración y control de cabeceras sobre código Selenium existente |
| Playwright | integrado, nativo | interceptación de rutas y respuestas | activo | proyectos nuevos que quieren herramientas modernas |
Consejo de migración: si solo necesitas proxies con credenciales y ninguna captura de solicitudes, Selenium a secas con una extensión de autenticación es el movimiento más ligero y se queda en código con mantenimiento. Si dependes de inspeccionar o reescribir tráfico y empiezas de cero, Playwright te da eso de forma nativa sin la carga de fijar versiones. Conserva Selenium Wire cuando tengas una base de código Selenium existente cuyo control a nivel de solicitud sería caro de reconstruir. Para elegir IP con cualquiera de estas herramientas, compara los proxies residenciales, los proxies de datacenter y los proxies móviles frente a las defensas de tu objetivo.

Preguntas frecuentes
¿Cómo configuro un proxy autenticado en Selenium Wire?
Pasa un dict de proxy con URLs http y https en la forma login:password@host:port dentro de seleniumwire_options al crear el driver, y añade no_proxy para localhost. No hace falta ninguna extensión ni rodeo de diálogo de autenticación.
¿Por qué falla Selenium Wire con un ImportError de blinker?
blinker 1.8 eliminó un nombre interno que Selenium Wire importa al arrancar. Fija blinker por debajo de 1.8, por ejemplo blinker==1.7.0, junto con versiones fijadas de selenium-wire y selenium.
¿Selenium Wire sigue teniendo mantenimiento?
El proyecto original está archivado y ya no recibe mantenimiento activo. Sigue funcionando con versiones fijadas, pero prueba de forma aislada cualquier actualización de Selenium o Chrome, y considera un fork con mantenimiento o Playwright para proyectos nuevos.
¿Cómo compruebo que el proxy se está usando de verdad?
Carga un servicio que devuelva la IP, como api.ipify.org, en el driver y confirma que la dirección devuelta es la del proxy y no la tuya. También puedes leer driver.requests para ver que el tráfico pasó por el gateway.
¿Puede Selenium Wire leer tráfico HTTPS?
Sí. Actúa como un proxy man-in-the-middle e inyecta su propio certificado raíz para descifrar los cuerpos HTTPS. Los sitios que usan certificate pinning lo rechazarán, así que desactiva la captura para esos hosts.
¿Cuándo no es DataImpulse la opción adecuada?
Si necesitas proxies ISP estáticos, una API de scraping totalmente gestionada o acceso a sitios bancarios y gubernamentales, DataImpulse no es la herramienta adecuada. Se centra en proxies residenciales, móviles y de datacenter rotativos para recopilar datos públicos y acceder a contenido.
Ejecuta Selenium Wire a través de proxies fiables
Un proxy con Selenium Wire vale tanto como las IP que hay detrás. Puedes enrutar tu automatización de navegador a través de IP residenciales, móviles o de datacenter de origen ético con tráfico de pago por uso desde 1 dólar por GB. Crea una cuenta de DataImpulse y empieza con sesiones rotativas o persistentes.
