Selenium com Proxies Autenticados: Guia Completo de Stealth e Rotação

Domine proxies autenticados no Selenium com selenium-wire, perfis Firefox, stealth, rotação de IPs e Selenium Grid para scraping em escala — com exemplos de código prontos para produção.

Selenium com Proxies Autenticados: Guia Completo de Stealth e Rotação

Por Que o Selenium Lida Tão Mal com Proxies Autenticados?

Se você já tentou passar http://user:pass@gate.proxyhat.com:8080 diretamente para webdriver.ChromeOptions(), sabe a frustração: o Chrome ignora as credenciais, exibe um pop-up de autenticação e o teste simplesmente trava. Esse é um problema arquitetural do Chromium — ele delega a autenticação proxy ao sistema operacional, não ao WebDriver.

Para engenheiros de QA e scraping que dependem do ecossistema Selenium, isso cria um gargalo real. Proxies residenciais — essenciais para contornar anti-bots e CAPTCHAs — quase sempre exigem autenticação user:pass. Sem uma estratégia sólida de Selenium proxy auth, você fica limitado a proxies datacenter sem autenticação ou a extensões de navegador frágeis.

Neste guia, vamos resolver isso de forma idiomática: middleware, profiles, stealth e rotação — tudo integrado ao fluxo do Selenium, sem gambiarras.

Chrome + selenium-wire: Autenticação Proxy Nativa

O selenium-wire estende o WebDriver do Selenium para interceptar e modificar requisições HTTP em tempo real. A principal vantagem para proxies autenticados: ele gerencia o túnel CONNECT e injeta o header Proxy-Authorization automaticamente.

Instalação e Configuração Base

pip install selenium-wire selenium
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options

PROXY_USER = "user-country-US"
PROXY_PASS = "pass"
PROXY_HOST = "gate.proxyhat.com"
PROXY_PORT = 8080

options = Options()
options.add_argument("--headless=new")
options.add_argument("--disable-blink-features=AutomationControlled")

seleniumwire_options = {
    "proxy": {
        "https": f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}",
        "http": f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}",
    },
    "disable_encoding": True,  # útil para inspecionar conteúdo bruto
}

driver = webdriver.Chrome(
    options=options,
    seleniumwire_options=seleniumwire_options,
)

driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()

Pontos críticos de produção:

  • Timeouts: configure seleniumwire_options["verify_ssl"] = False apenas em dev; em produção, mantenha SSL verification ativa.
  • Memória: selenium-wire armazena todas as requisições em memória. Em sessões longas, limpe periodicamente com del driver.requests.
  • Concorrência: cada instância abre uma porta local de proxy. Em paralelo, garanta portas distintas ou use port=0 para auto-atribuição.

Geo-targeting na Prática

Com Selenium residential proxies, o geo-targeting é codificado diretamente no username — sem necessidade de endpoints diferentes:

# Proxy com geo-targeting por país e cidade
PROXY_USER = "user-country-DE-city-berlin"
PROXY_PASS = "pass"

seleniumwire_options = {
    "proxy": {
        "https": f"http://{PROXY_USER}:{PROXY_PASS}@gate.proxyhat.com:8080",
    },
}

Firefox: Perfis de Proxy com Autenticação via Extensão

O Firefox não sofre do mesmo problema do Chrome — mas também não aceita credenciais proxy inline na URL. A abordagem idiomática é criar um profile com proxy pré-configurado e injetar autenticação via uma extensão WebExtension mínima.

import os
import tempfile
import zipfile
from selenium import webdriver
from selenium.webdriver.firefox.options import Options

PROXY_HOST = "gate.proxyhat.com"
PROXY_PORT = 8080
PROXY_USER = "user-country-GB"
PROXY_PASS = "pass"

def create_proxy_auth_extension(host, port, user, password):
    """Cria uma WebExtension temporária que injeta credenciais proxy."""
    manifest_json = """{
        "version": "1.0.0",
        "manifest_version": 2,
        "name": "proxy-auth-helper",
        "permissions": ["webRequest", "webRequestBlocking", "<all_urls>"],
        "background": {"scripts": ["background.js"]}
    }"""

    background_js = """
    browser.webRequest.onAuthRequired.addListener(
        function(details) {
            return {authCredentials: {username: "%s", password: "%s"}};
        },
        {urls: ["<all_urls>"]},
        ["blocking"]
    );
    """ % (user, password)

    plugin_dir = tempfile.mkdtemp()
    with open(os.path.join(plugin_dir, "manifest.json"), "w") as f:
        f.write(manifest_json)
    with open(os.path.join(plugin_dir, "background.js"), "w") as f:
        f.write(background_js)

    ext_path = os.path.join(plugin_dir, "proxy_auth.zip")
    with zipfile.ZipFile(ext_path, "w") as zp:
        zp.write(os.path.join(plugin_dir, "manifest.json"), "manifest.json")
        zp.write(os.path.join(plugin_dir, "background.js"), "background.js")
    return ext_path


ext_path = create_proxy_auth_extension(
    PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS
)

options = Options()
options.add_argument("--headless")
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)
options.add_argument(f"--extension={ext_path}")

driver = webdriver.Firefox(options=options)
driver.get("https://httpbin.org/ip")
print(driver.find_element("tag name", "body").text)
driver.quit()

Essa abordagem é mais robusta que Chrome extensions porque o Firefox suporta webRequest.onAuthRequired de forma estável. Para sessões paralelas, gere um profile temporário único por instância com tempfile.mkdtemp().

Selenium Stealth: Reduzindo Impressões Digitais de Automação

Mesmo com o proxy correto, sites modernos detectam Selenium via fingerprints do navegador: navigator.webdriver, ausência de plugins, canvas fingerprinting e timing de eventos. Duas bibliotecas resolvem isso de forma complementar.

selenium-stealth

O selenium-stealth aplica patches no WebDriver após a inicialização — remove flags de automação, injeta propriedades realistas e normaliza o user-agent.

from selenium import webdriver
from selenium_stealth import stealth

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--disable-blink-features=AutomationControlled")

driver = webdriver.Chrome(options=options)

stealth(
    driver,
    languages=["pt-BR", "en-US", "en"],
    vendor="Google Inc.",
    platform="Win32",
    webgl_vendor="Intel Inc.",
    renderer="Intel Iris OpenGL Engine",
    fix_hairline=True,
)

driver.get("https://bot.sannysoft.com/")
print("Stealth check:", driver.title)
driver.quit()

selenium-driverless

Para Selenium stealth avançado, o selenium-driverless opera via Chrome DevTools Protocol (CDP) diretamente, sem criar o objeto webdriver no DOM. Isso torna a detecção significativamente mais difícil:

import asyncio
from selenium_driverless import webdriver

async def main():
    options = webdriver.ChromeOptions()
    options.add_argument("--headless=new")

    driver = await webdriver.Chrome(options=options)

    # Autenticação proxy via CDP — sem extensão
    await driver.execute_cdp_cmd(
        "Network.setExtraHTTPHeaders",
        {"headers": {"Proxy-Authorization": "Basic <base64 user:pass>"}}
    )

    await driver.get("https://nowsecure.nl/")
    print(await driver.title)
    await driver.quit()

asyncio.run(main())
Regra prática: use selenium-stealth para compatibilidade com scripts legados. Migre para selenium-driverless quando precisar de CDP direto ou quando os sites alvo atualizarem suas heurísticas de detecção.

Padrão Rotating Proxy Pool: IP Novo por Sessão

Para scraping de SERPs ou monitoramento de preços em escala, você precisa de um IP diferente por sessão — não por requisição. O padrão rotating proxy pool atribui um IP sticky a cada instância do WebDriver, rotacionando apenas entre sessões.

import itertools
import string
import random
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options

PROXY_HOST = "gate.proxyhat.com"
PROXY_PORT = 8080
PROXY_PASS = "pass"

def generate_session_id(length=8):
    """Gera um ID de sessão único para sticky IP."""
    return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))

def create_stealth_driver(country="US", city=None):
    """Cria um WebDriver com IP residencial único por sessão."""
    session_id = generate_session_id()
    username = f"user-country-{country}-session-{session_id}"
    if city:
        username = f"user-country-{country}-city-{city}-session-{session_id}"

    options = Options()
    options.add_argument("--headless=new")
    options.add_argument("--disable-blink-features=AutomationControlled")
    options.add_argument("--window-size=1920,1080")

    seleniumwire_options = {
        "proxy": {
            "https": f"http://{username}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}",
            "http": f"http://{username}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}",
        },
    }

    driver = webdriver.Chrome(
        options=options,
        seleniumwire_options=seleniumwire_options,
    )
    return driver


def scrape_targets(targets, country="US"):
    """Processa uma lista de URLs, rotacionando IP a cada sessão."""
    results = []
    for url in targets:
        driver = create_stealth_driver(country=country)
        try:
            driver.get(url)
            # sua lógica de extração aqui
            results.append(driver.page_source[:200])
        except Exception as e:
            print(f"Erro em {url}: {e}")
        finally:
            driver.quit()  # libera o IP sticky
    return results


urls = [
    "https://httpbin.org/ip",
    "https://httpbin.org/headers",
    "https://httpbin.org/user-agent",
]
print(scrape_targets(urls, country="DE"))

O flag -session-{id} no username garante que o proxy atribui um IP residencial novo a cada sessão, mantendo-o estável durante toda a vida do WebDriver. Quando driver.quit() é chamado, o IP é reciclado.

Estratégias de Rotação

EstratégiaQuando UsarImplementação
Per-requestScraping de alta frequência, APIs públicasSem session flag — IP muda a cada request
Sticky sessionFluxos multi-página, login, carrinhoFlag -session-{id} — IP fixo por ~10 min
Per-WebDriverScraping paralelo, SERP trackingSession ID único por instância — IP novo por worker

Selenium Grid e Containerização para Escala

Quando você precisa de 50+ browsers em paralelo, instâncias locais não escalam. O Selenium Grid 4 com Docker é a solução padrão da indústria.

Docker Compose para Grid com Proxy

# docker-compose.yml
version: '3.8'
services:
  selenium-hub:
    image: selenium/hub:4.18
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"
    environment:
      - SE_SESSION_RETRY_INTERVAL=2
      - SE_NODE_SESSION_TIMEOUT=300

  chrome-node:
    image: selenium/node-chrome:4.18
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=4
      - SE_NODE_OVERRIDE_MAX_SESSIONS=true
    deploy:
      replicas: 5

  worker:
    build: ./scraper
    depends_on:
      - selenium-hub
    environment:
      - HUB_URL=http://selenium-hub:4444/wd/hub
      - PROXY_HOST=gate.proxyhat.com
      - PROXY_PORT=8080
    deploy:
      replicas: 10

Worker com Rotação de IP por Sessão

import os
import uuid
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from seleniumwire import webdriver as sw_webdriver

HUB_URL = os.environ["HUB_URL"]
PROXY_HOST = os.environ["PROXY_HOST"]
PROXY_PORT = os.environ["PROXY_PORT"]
PROXY_USER = f"user-country-US-session-{uuid.uuid4().hex[:8]}"
PROXY_PASS = "pass"

def create_remote_driver():
    options = Options()
    options.add_argument("--headless=new")
    options.add_argument("--disable-blink-features=AutomationControlled")

    seleniumwire_options = {
        "proxy": {
            "https": f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}",
        },
    }

    driver = sw_webdriver.Remote(
        command_executor=HUB_URL,
        options=options,
        seleniumwire_options=seleniumwire_options,
    )
    return driver

# Cada worker obtém um IP residencial único
with create_remote_driver() as driver:
    driver.get("https://httpbin.org/ip")
    print(driver.find_element("tag name", "body").text)

Dimensionamento prático: com 5 nodes Chrome (4 sessões cada) = 20 browsers simultâneos. Com Selenium residential proxies, isso significa 20 IPs residenciais distintos processando em paralelo. Para 100+ sessões, adicione mais nodes ou use Kubernetes com HPA (Horizontal Pod Autoscaler).

Kubernetes: Escalabilidade Elástica

Em produção, o padrão recomendado é:

  • Deployment para o hub (1 réplica com anti-affinity)
  • Deployment para nodes Chrome com replicas dinâmico via HPA baseado em CPU
  • Job ou Deployment para workers, cada um com session ID único
  • ConfigMap para credenciais proxy (nunca hardcode no image)
  • Resource limits: cada node Chrome precisa de ~1 vCPU e 2GB RAM por sessão

Selenium vs Playwright: Quando Migrar?

O Playwright se tornou a alternativa mais popular ao Selenium para scraping moderno. Mas a decisão não é binária — depende do contexto.

DimensãoSeleniumPlaywright
Proxy autenticadoRequer selenium-wire ou extensãoNativo: proxy={username, password}
StealthRequer selenium-stealth / driverlessMelhor baseline, mas não é invisível
Ecossistema12+ anos, bindings em 8+ linguagens5 anos, JS/TS/Python/Java/.NET
Grid paraleloMaduro (Selenium Grid 4)Nativo com browser.newContext()
CDP AccessLimitado sem hacksPrimeiro-class via CDPSession
Legado / QACompatível com Selenium IDE, Grid, CloudSem compatibilidade com testes existentes
Auto-waitRequer explicit waitsAuto-wait embutido em todas as ações
Mobile emulationRequer Chrome mobile emulation flagsDevice descriptors nativos

Quando Ficar com Selenium

  • Sua suíte de testes QA já usa Selenium IDE / Grid / Selenese — migração é cara.
  • Você precisa de bindings em linguagens que o Playwright não suporta (Ruby, Perl, PHP).
  • Cloud providers (BrowserStack, Sauce Labs, LambdaTest) oferecem infraestrutura Selenium-first.
  • Equipe já domina o ecossistema e o custo de re-treinamento não se justifica.

Quando Migrar para Playwright

  • Novos projetos de scraping onde Selenium proxy auth é um bloqueador recorrente.
  • Você precisa de CDP direto para interceptação avançada ou stealth profundo.
  • Paralelismo nativo sem Grid é prioridade — browser.newContext() é mais leve que um novo WebDriver.
  • Auto-wait e debug tools (Trace Viewer, Codegen) aceleram desenvolvimento.
Decisão pragmática: se você está escrevendo um scraper novo hoje, comece com Playwright. Se está mantendo uma suíte Selenium existente, invista em selenium-wire + stealth — o custo de migração raramente compensa para projetos em produção.

Melhores Práticas para Produção

Gerenciamento de Sessões

  • Always quit: chame driver.quit() no finally — não confie em garbage collection.
  • Session timeout: configure timeouts no Grid (SE_NODE_SESSION_TIMEOUT) para evitar zombies.
  • Retry com IP novo: em caso de CAPTCHA ou block, gere novo session ID e recrie o driver.

Ética e Compliance

  • Respeite robots.txt e os Termos de Serviço do site alvo.
  • Implemente rate limiting — mesmo com rotação de IPs, requests excessivos podem sobrecarregar o servidor.
  • Para dados pessoais, esteja em conformidade com GDPR e CCPA.
  • Considere APIs oficiais antes de scraping — muitas vezes são mais estáveis e legais.

Observabilidade

  • Log o IP do proxy atribuído (via httpbin.org/ip antes do scraping real) para rastrear qual IP foi bloqueado.
  • Monitore success rate por país e por site — proxies residenciais têm taxas diferentes por região.
  • Alerte quando success rate cair abaixo de 85% — pode indicar bloqueio de range ou fingerprint detection.

Pontos-chave

  • Selenium proxy auth não funciona nativamente no Chrome — use selenium-wire para injetar credenciais no túnel CONNECT.
  • No Firefox, crie uma WebExtension mínima com webRequest.onAuthRequired para autenticação proxy.
  • Selenium stealth com selenium-stealth ou selenium-driverless é essencial para contornar anti-bots modernos.
  • O padrão rotating proxy pool usa session IDs no username para garantir IP único por WebDriver — não por request.
  • Selenium Grid 4 + Docker é o caminho para 20-100+ browsers em paralelo com IPs residenciais distintos.
  • Para novos projetos, Playwright oferece proxy auth nativo e melhor stealth — mas Selenium mantém vantagem em ecossistema e legado.

Pronto para escalar seu scraping com proxies residenciais de alta confiabilidade? Confira os planos do ProxyHat e as localizações disponíveis para geo-targeting preciso. Para aprofundar em padrões de scraping, veja nosso guia de web scraping em produção.

Pronto para começar?

Acesse mais de 50M de IPs residenciais em mais de 148 países com filtragem por IA.

Ver preçosProxies residenciais
← Voltar ao Blog