# Autenticação de Proxy Nodriver: As Três Soluções Que Funcionam

O principal resultado para autenticação de proxy nodriver é uma discussão no GitHub, não um guia. nodriver não tem suporte nativo para user:pass — aqui estão as três soluções que funcionam, e o atalho de uma linha que a maioria das pessoas perde.

Pesquise **autenticação de proxy nodriver** e os dez principais resultados são uma discussão no GitHub, um repositório de demonstração, alguns tópicos no Stack Overflow sobre uma biblioteca diferente e uma postagem no Reddit — nenhum guia real. A razão é simples: nodriver, o sucessor assíncrono do CDP para undetected-chromedriver (esse projeto tem 12,8k estrelas no GitHub e 1,3k forks), não tem uma maneira nativa de passar `user:pass` para um proxy. O Chrome ignora credenciais incorporadas em um argumento de linha de comando, e nodriver não resolve isso. Este guia é a página que aquela discussão deveria ter se tornado: o que funciona, o que não funciona, e as três soluções que colocam um proxy autenticado em funcionamento.

## Proxy simples funciona; proxy autenticado não

Um proxy não autenticado é uma linha de código. Passe o endereço através de `browser_args` e cada solicitação sai do IP do proxy:

```python
import nodriver as uc

async def main():
    browser = await uc.start(
        browser_args=["--proxy-server=residentialboson.quantumproxies.io:PORT"],
    )
    page = await browser.get("https://httpbin.org/ip")
    print(await page.get_content())   # shows the proxy exit IP

uc.loop().run_until_complete(main())
```

Agora adicione credenciais — `--proxy-server=http://USER:PASS@host:port` — e ele quebra. O Chromium remove o segmento `USER:PASS@` porque o formato do argumento não tem espaço para credenciais, então o proxy responde com `407 Proxy Authentication Required` e o Chrome exibe um diálogo de login nativo que vive fora do DOM. nodriver não pode ver ou preenchê-lo. Esse 407 é a mesma barreira abordada em [nosso guia para corrigir erros 407](https://quantumproxies.io/blog/fix-407-proxy-authentication-required): o proxy está rejeitando você, não o navegador. Portanto, toda solução real precisa responder ao desafio de outra forma.

## Solução 1: Lista branca de IPs — sem credenciais, sem diálogo

Este é o atalho que os tópicos do GitHub nunca mencionam, e é o mais simples de longe. Se o seu scraper roda de uma máquina com um IP público estável, registre esse IP no painel do seu provedor e elimine completamente as credenciais — o gateway autentica você pelo endereço de origem. O código nodriver permanece como o snippet simples `--proxy-server` acima, sem código de autenticação. Todo plano da QuantumProxies suporta lista branca de IPs junto com user:pass em seus [proxies residenciais](https://quantumproxies.io/residential-proxies), então este é o caminho recomendado sempre que seu IP de saída for fixo. Seu único limite é topológico: ele autentica uma máquina, não um script, então runners em nuvem efêmeros, contêineres atrás de NAT e caixas de CI com IPs variáveis precisam de uma das duas próximas soluções.

![Quatro rotas para autenticar um proxy nodriver no gateway: lista branca de IPs, um manipulador de autenticação CDP Fetch, uma extensão do Chrome gerada e um relay local. O quadro diz quando cada uma se encaixa: a lista branca custa zero código em um IP fixo, o manipulador e a extensão respondem ao desafio quando o IP muda, o relay cobre o SOCKS5.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785776549/blog/generated/qp-b10-001-diag1.png)
*A lista branca não custa código quando seu IP é fixo; o manipulador CDP e a extensão respondem ao desafio de credenciais quando não é.*

## Solução 2: responder ao desafio com um manipulador CDP Fetch

nodriver fala diretamente o Chrome DevTools Protocol, então você pode interceptar o desafio de autenticação em processo — sem necessidade de arquivo de extensão. Habilite o domínio `Fetch` com `handle_auth_requests=True`, depois responda a cada evento `AuthRequired` com `continue_with_auth`. Dois detalhes, ambos da resposta na discussão #1798, são a diferença entre funcionar e travar:

- **Registre os manipuladores antes de habilitar o domínio.** A chamada interna `enable` do nodriver sobrescreve seu registro de manipulador, então se você os adicionar depois, nenhum evento será disparado — a razão número um pela qual as pessoas relatam 'não faz nada'.
- **Dispare e esqueça as respostas.** Aguardar a resposta dentro do manipulador bloqueia o loop de eventos e trava todo o navegador. Envolva cada envio em `asyncio.create_task` para que ele execute sem bloquear.

```python
import asyncio
import nodriver as uc

PROXY = "residentialpremium.quantumproxies.io:8080"   # host:port for --proxy-server
USER, PASS = "USER", "PASS"

class Scraper:
    def __init__(self):
        uc.loop().run_until_complete(self.run())

    async def run(self):
        browser = await uc.start(browser_args=[f"--proxy-server={PROXY}"])
        self.tab = await browser.get("data:,")        # blank tab first

        # 1) handlers BEFORE enabling the Fetch domain
        self.tab.add_handler(uc.cdp.fetch.RequestPaused, self.on_request)
        self.tab.add_handler(uc.cdp.fetch.AuthRequired, self.on_auth)
        # 2) only now turn on interception with auth handling
        await self.tab.send(uc.cdp.fetch.enable(handle_auth_requests=True))

        page = await browser.get("https://httpbin.org/ip")
        await asyncio.sleep(3)
        print(await page.get_content())

    async def on_auth(self, event):
        # fire-and-forget: awaiting here deadlocks the loop
        asyncio.create_task(self.tab.send(uc.cdp.fetch.continue_with_auth(
            request_id=event.request_id,
            auth_challenge_response=uc.cdp.fetch.AuthChallengeResponse(
                response="ProvideCredentials", username=USER, password=PASS,
            ),
        )))

    async def on_request(self, event):
        asyncio.create_task(self.tab.send(
            uc.cdp.fetch.continue_request(request_id=event.request_id)))

if __name__ == "__main__":
    Scraper()
```

Uma advertência surgiu no mesmo tópico: um usuário descobriu que isso funcionava em páginas HTTP simples, mas falhava em HTTPS, e o culpado era um proxy de baixa qualidade, não o código — trocar por uma melhor saída resolveu. Essa é a lição recorrente do scraping stealth: o manipulador responde ao desafio, mas a reputação do IP decide se o site permite sua entrada.

## Solução 3: uma extensão Chrome gerada

O outro padrão da comunidade constrói uma pequena extensão Chrome na inicialização que define o proxy e responde ao desafio de credenciais através de `chrome.webRequest.onAuthRequired` — o mesmo truque que funciona no Selenium e Puppeteer. Você escreve um pequeno manifesto mais um trabalhador de fundo em um diretório temporário e o carrega via `--load-extension`:

```python
import nodriver as uc

async def main():
    # ext_dir holds a Manifest V3 extension: manifest.json + worker.js that
    # calls chrome.proxy.settings.set(...) and returns authCredentials from
    # chrome.webRequest.onAuthRequired. Generate it once, then load it:
    browser = await uc.start(browser_args=[
        "--load-extension=" + ext_dir,
        "--headless=new",   # extensions only load in the NEW headless mode
    ])
    page = await browser.get("https://httpbin.org/ip")
    print(await page.get_content())

uc.loop().run_until_complete(main())
```

O manifesto completo e o trabalhador são idênticos aos arquivos Manifest V3 em nosso [guia de autenticação de proxy do Selenium](https://quantumproxies.io/blog/selenium-proxy-setup-authenticated) — copie-os literalmente, apenas a chamada de lançamento muda. Dois problemas se repetem em todos os lugares: extensões carregam apenas sob `--headless=new` (plain `--headless` falha), e um diretório descompactado é mais confiável em versões do Chrome do que um zip compactado. A extensão lida com qualquer tipo de proxy, o que a torna o recurso quando a rota CDP está lutando contra você.

## A quarta opção: um relay local

Se você preferir não mexer no nodriver, execute um pequeno relay local que mantém as credenciais e apresenta um endpoint sem autenticação em `127.0.0.1`. nodriver então aponta para o endereço de loopback com o argumento simples e nunca vê um desafio. Esta é a rota mais limpa para SOCKS5, onde o Chromium recusa proxies autenticados completamente (rastreado como bug do Chromium 40829748). Cobrimos o relay mínimo, as ferramentas prontas e quando é exagero em [o guia de relay de proxy](https://quantumproxies.io/blog/proxy-relay-socks5-auth-tools).

## Uma nota sobre SOCKS5

SOCKS5 não autenticado funciona através do argumento — `--proxy-server=socks5://host:port` — mas SOCKS5 autenticado não, e nenhum manipulador CDP salva você porque o Chromium nunca lançou suporte para nome de usuário/senha SOCKS5. As respostas práticas são as mesmas três: liste o IP, execute um relay, ou use o endpoint HTTP do provedor. Todo plano da QuantumProxies expõe tanto proxies HTTP quanto [SOCKS5](https://quantumproxies.io/socks5-proxies) no mesmo gateway, então mudar para o endpoint HTTP é muitas vezes a solução SOCKS5 mais rápida de todas. Para navegadores anti-detect como uma família, o [mapa de proxies autenticados](https://quantumproxies.io/blog/anti-detect-frameworks-authenticated-proxies-map) compara nodriver, zendriver e o resto lado a lado.

![Lista branca de IPs para o nodriver: registre o IP de saída da máquina no provedor, inicie com uma flag --proxy-server simples e o gateway autentica o endereço de origem, de modo que não aparecem nem 407 nem diálogo de credenciais. O quadro mostra zero código de autenticação, ideal para uma VPS fixa, mas não para runners de CI atrás de NAT.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785776549/blog/generated/qp-b10-001-diag2.png)
*Quando o IP de saída é estável, a lista branca autentica a máquina e o código de autenticação desaparece completamente.*

## Perguntas frequentes

### O nodriver suporta proxies autenticados?

Não nativamente. Você pode passar um proxy não autenticado através de `browser_args=["--proxy-server=host:port"]`, mas `user:pass` nesse argumento é removido pelo Chromium. Para autenticar, você deve listar seu IP com o provedor, responder ao desafio com um manipulador CDP `Fetch.AuthRequired`, gerar uma extensão de proxy-auth Chrome, ou executar um relay local que mantém as credenciais.

### Por que meu manipulador de autenticação nodriver não recebe eventos?

Quase sempre porque você habilitou o domínio `Fetch` antes de registrar os manipuladores. A chamada interna `enable` do nodriver sobrescreve o registro, então os eventos nunca chegam ao seu callback. Adicione os manipuladores `RequestPaused` e `AuthRequired` primeiro, depois chame `fetch.enable(handle_auth_requests=True)`. Também envolva suas respostas em `asyncio.create_task` para que aguardá-las não bloqueie o loop.

### O nodriver pode usar um proxy SOCKS5 com nome de usuário e senha?

Não. O Chromium não suporta SOCKS5 autenticado (bug do Chromium 40829748), e o nodriver herda essa limitação. SOCKS5 não autenticado funciona via `--proxy-server=socks5://host:port`. Para SOCKS5 autenticado, liste seu IP, execute um relay local que adicione as credenciais, ou mude para o endpoint HTTP do provedor, que lida com autenticação Basic de forma limpa.

### nodriver ou zendriver para proxies autenticados?

Ambos compartilham a mesma lacuna e as mesmas soluções, porque zendriver é um fork comunitário do nodriver. zendriver tem um rastreador de problemas mais ativo onde a questão da autenticação é abertamente discutida, mas os métodos que funcionam são idênticos. Se você está no fork, a configuração específica do fork espelha tudo aqui — o manipulador CDP e a lista branca se comportam da mesma forma.

O resumo honesto: nodriver não fará autenticação de proxy por você, e isso é aceitável uma vez que você conhece o mapa. Liste quando seu IP for estável, recorra ao manipulador CDP ou extensão quando não for, e mantenha um relay na manga para SOCKS5. O código acima responde ao desafio — mas uma saída residencial limpa é o que realmente faz você passar pela porta.

[Execute nodriver em IPs residenciais listados](https://quantumproxies.io/residential-proxies)
