Aqui está a armadilha em que todo desenvolvedor de automação de navegador cai exatamente uma vez: você adiciona --proxy-server=http://user:pass@host:port às flags de inicialização do Chrome, o navegador inicia normalmente, e então toda página trava em um popup de autenticação que seu script não consegue ver nem clicar. O Chrome silenciosamente remove as credenciais da flag de proxy. Sem erro, sem linha de log, apenas um diálogo modal em um navegador que ninguém está observando.
Este guia é o mapa completo dos métodos de autenticação de proxy que realmente funcionam no Selenium e no Playwright em 2026 — qual usar, qual evitar e o código exato de cada um. (Para estratégia de seleção e rotação de proxy nessas ferramentas, veja Usando Proxies com Playwright e Puppeteer — este artigo é puramente sobre fazer as credenciais passarem.)
Clientes HTTP de linha de comando extraem as credenciais das URLs de proxy e respondem ao 407 Proxy Authentication Required do proxy com um cabeçalho Proxy-Authorization automaticamente. O Chromium não: --proxy-server aceita apenas scheme://host:port, e quando o 407 volta ele exibe um diálogo interativo. No modo headless não há nem diálogo — a requisição simplesmente falha.
Então a pergunta nunca é "como coloco a senha na URL" — é "qual camada responde o 407 por mim". Quatro respostas que funcionam, da melhor para a pior.
O Playwright resolveu o problema corretamente: ele responde aos desafios de autenticação de proxy por conta própria via CDP. As credenciais vão nas opções de launch ou de context:
# Python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
proxy={
"server": "http://us.jibaoproxy.com:913",
"username": "USERNAME-session-job1",
"password": "PASSWORD",
}
)
// Node.js - and per-context, which is where it gets powerful:
const browser = await chromium.launch({
proxy: { server: 'per-context' } // declare intent at launch
});
const ctx = await browser.newContext({
proxy: {
server: 'http://us.jibaoproxy.com:913',
username: 'USERNAME-session-job2',
password: 'PASSWORD',
}
});
Proxies por context significam que um único processo de navegador pode rodar N contexts em N sessões sticky diferentes — a base de toda configuração séria de scraping com Playwright. Se você está no Playwright, terminou; pule para a seção de verificação. Tudo abaixo existe porque o Selenium não tem equivalente.
O selenium-wire envolve o Selenium com um proxy MITM local que cuida da autenticação upstream:
from seleniumwire import webdriver # pip install selenium-wire
options = {
"proxy": {
"http": "http://USERNAME:[email protected]:913",
"https": "https://USERNAME:[email protected]:913",
}
}
driver = webdriver.Chrome(seleniumwire_options=options)
driver.get("https://example.com")
Ressalvas que você deve conhecer antes de ir para produção:
A abordagem clássica: uma pequena extensão gerada que define o proxy e responde à autenticação via chrome.webRequest.onAuthRequired. Sem MITM, sem processo extra, funciona no Selenium puro:
import zipfile, json
HOST, PORT = "us.jibaoproxy.com", 913
USER, PASS = "USERNAME-session-sel1", "PASSWORD"
manifest = {
"version": "1.0.0", "manifest_version": 2, "name": "Proxy Auth",
"permissions": ["proxy", "webRequest", "webRequestBlocking", ""],
"background": {"scripts": ["background.js"]},
}
background = f"""
chrome.proxy.settings.set({{value: {{mode: "fixed_servers", rules: {{
singleProxy: {{scheme: "http", host: "{HOST}", port: {PORT}}}
}}}}, scope: "regular"}}, () => {{}});
chrome.webRequest.onAuthRequired.addListener(
() => ({{authCredentials: {{username: "{USER}", password: "{PASS}"}}}}),
{{urls: [""]}}, ["blocking"]
);
"""
with zipfile.ZipFile("proxy_auth.zip", "w") as zp:
zp.writestr("manifest.json", json.dumps(manifest))
zp.writestr("background.js", background)
from selenium import webdriver
opts = webdriver.ChromeOptions()
opts.add_extension("proxy_auth.zip")
driver = webdriver.Chrome(options=opts)
Dois detalhes traiçoeiros: extensões não carregam no modo headless clássico — use --headless=new (Chrome 109+) ou rode com cabeça; e os scripts de background do Manifest V2 ainda funcionam para extensões de automação carregadas lateralmente, mas fique de olho no cronograma de descontinuação do MV2 no Chrome — o equivalente em MV3 precisa de um service worker e do mesmo listener onAuthRequired.
Rode um pequeno proxy local que guarda as credenciais; aponte o navegador para localhost sem nenhuma autenticação. Funciona com todo navegador, todo driver, toda linguagem, headless ou não:
# Using pproxy (pip install pproxy) - terminal 1:
pproxy -l http://127.0.0.1:8899 \
-r "http://USERNAME:[email protected]:913"
# Your script - terminal 2: plain Selenium, no auth needed
opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://127.0.0.1:8899")
driver = webdriver.Chrome(options=opts)
Esta também é a resposta mais limpa para Firefox/geckodriver (onde o truque da extensão não se aplica) e para ambientes exóticos como testes de aplicativos Electron. Custo: mais uma peça móvel para supervisionar, e o roteamento por context requer uma porta de encaminhador por sessão.
| Método | Funciona em | Headless | Sessões por context | Veredito de produção |
|---|---|---|---|---|
| Nativo do Playwright | Playwright | Sim | Sim | Escolha padrão |
| selenium-wire | Selenium (Py) | Sim | Por driver | Bom em escala moderada |
| Extensão de autenticação | Selenium (qualquer linguagem) | Só --headless=new | Por driver | Sólido, fique de olho no MV3 |
| Encaminhador local | Tudo | Sim | Uma porta por sessão | Fallback universal |
O fallback silencioso para o seu IP real é o modo de falha que faz contas serem banidas. Verifique o IP de saída no início de cada execução:
ip = driver.execute_script(
"return fetch('https://api.ipify.org').then(r => r.text())"
) if hasattr(driver, 'execute_script') else page.evaluate(
"fetch('https://api.ipify.org').then(r => r.text())"
)
assert ip != MY_REAL_IP, "Proxy not applied - aborting before we leak"
--proxy-server; o Chrome as descartou. Use um dos quatro métodos.ERR_PROXY_CONNECTION_FAILED — host/porta errados ou incompatibilidade de protocolo. Teste a mesma linha com curl -x primeiro; se o curl funcionar, o problema está na conexão do seu navegador.--headless=new.Navegadores não leem URLs de proxy user:pass@ — algo precisa responder o 407 por eles. No Playwright esse algo é embutido; no Selenium é o selenium-wire, uma extensão de autenticação gerada ou um encaminhador local. Escolha pela sua stack usando a tabela de comparação e então verifique o IP de saída em toda execução para que uma falha silenciosa de autenticação nunca possa vazar seu endereço real no meio do crawl.
500MB de tráfego grátis — um gateway, sticky ou rotativo, HTTP e SOCKS5.
Começar Teste GrátisNovos usuários recebem 500MB ao se cadastrar, mais um bônus na primeira recarga. Oferta por tempo limitado.