Nodriver Proxy-authenticatie: De Drie Oplossingen Die Werken

Het beste resultaat voor nodriver proxy-authenticatie is een GitHub-discussie, geen handleiding. nodriver heeft geen native user:pass ondersteuning — hier zijn de drie oplossingen die werken, en de één-regel snelkoppeling die de meeste mensen missen.

Zoek nodriver proxy-authenticatie en de top tien resultaten zijn een GitHub-discussie, een demo-repo, een paar Stack Overflow threads over een andere bibliotheek, en één Reddit-post — geen echte handleiding. De reden is simpel: nodriver, de asynchrone CDP-opvolger van undetected-chromedriver (dat project heeft 12.8k GitHub-sterren en 1.3k forks), heeft geen native manier om user:pass naar een proxy door te geven. Chrome negeert inloggegevens die in een command-line vlag zijn ingebed, en nodriver verdoezelt dit niet. Deze handleiding is de pagina die die discussiedraad had moeten worden: wat werkt, wat niet, en de drie oplossingen die een geauthenticeerde proxy aan de praat krijgen.

Eenvoudige proxy werkt; geauthenticeerde proxy niet

Een niet-geauthenticeerde proxy is een één-regel. Geef het adres door via browser_args en elke aanvraag verlaat via het proxy-IP:

import nodriver as uc

async def main():
    browser = await uc.start(
        browser_args=["--proxy-server=gate.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())

Voeg nu inloggegevens toe — --proxy-server=http://USER:PASS@host:port — en het breekt. Chromium stript het USER:PASS@ segment omdat het vlagformaat geen inlogslot heeft, waarna de proxy antwoordt met 407 Proxy Authentication Required en Chrome een native inlogdialoog opent die buiten de DOM leeft. nodriver kan het niet zien of invullen. Die 407 is dezelfde muur die wordt behandeld in onze handleiding voor het oplossen van 407-fouten: de proxy wijst je af, niet de browser. Dus elke echte oplossing moet de uitdaging op een andere manier aangaan.

Oplossing 1: IP-whitelisting — geen inloggegevens, geen dialoog

Dit is de snelkoppeling die de GitHub-threads nooit noemen, en het is verreweg de eenvoudigste. Als je scraper draait vanaf een machine met een stabiel openbaar IP, registreer dat IP dan in je provider-dashboard en laat de inloggegevens volledig weg — de gateway authenticeert je op basis van het bronadres. De nodriver-code blijft de eenvoudige --proxy-server snippet hierboven, helemaal geen auth-code. Elk QuantumProxies-plan ondersteunt IP-whitelisting naast user:pass op zijn residential proxies, dus dit is de aanbevolen route wanneer je egress-IP vast is. De enige beperking is topologisch: het authenticeert een machine, geen script, dus vluchtige cloud runners, containers achter NAT, en CI-boxen met veranderende IP's hebben een van de volgende twee oplossingen nodig.

Vergelijking van vier nodriver proxy-authenticatieroutes: IP-whitelisting, een CDP Fetch auth handler, een gegenereerde Chrome-extensie, en een lokale relay
Whitelisting kost nul code wanneer je IP vast is; de CDP-handler en extensie beantwoorden de inloguitdaging wanneer dat niet zo is.

Oplossing 2: beantwoord de uitdaging met een CDP Fetch handler

nodriver spreekt het Chrome DevTools Protocol direct, dus je kunt de auth-uitdaging in-process onderscheppen — geen extensiebestand nodig. Schakel het Fetch domein in met handle_auth_requests=True, en reageer dan op elk AuthRequired event met continue_with_auth. Twee details, beide uit het antwoord op discussie #1798, maken het verschil tussen werken en vastlopen:

import asyncio
import nodriver as uc

PROXY = "gate.quantumproxies.io:PORT"   # 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("draft:,")        # 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()

Een kanttekening die in dezelfde thread naar voren kwam: een gebruiker ontdekte dat dit werkte op eenvoudige HTTP-pagina's maar faalde op HTTPS, en de boosdoener was een proxy van lage kwaliteit, niet de code — overschakelen naar een betere exit loste het op. Dat is de terugkerende les van stealth scraping: de handler beantwoordt de uitdaging, maar de IP-reputatie bepaalt of de site je binnenlaat.

Oplossing 3: een gegenereerde Chrome-extensie

Het andere gemeenschapsmodel bouwt een kleine Chrome-extensie bij het opstarten die zowel de proxy instelt als de inloguitdaging beantwoordt via chrome.webRequest.onAuthRequired — dezelfde truc die werkt in Selenium en Puppeteer. Je schrijft een klein manifest plus een achtergrondwerker in een tijdelijke directory en laadt het via --load-extension:

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())

Het volledige manifest en de werker zijn identiek aan de Manifest V3-bestanden in onze Selenium proxy-authenticatie handleiding — kopieer ze letterlijk, alleen de startoproep verandert. Twee valkuilen herhalen zich overal: extensies laden alleen onder --headless=new (eenvoudig --headless faalt), en een uitgepakte directory is betrouwbaarder over Chrome-versies heen dan een verpakte zip. De extensie behandelt elk proxytype, wat het de terugvaloptie maakt wanneer de CDP-route je tegenwerkt.

De vierde optie: een lokale relay

Als je liever helemaal niet aan nodriver komt, draai dan een kleine lokale relay die de inloggegevens vasthoudt en een no-auth eindpunt presenteert op 127.0.0.1. nodriver wijst dan naar het loopback-adres met de eenvoudige vlag en ziet nooit een uitdaging. Dit is de schoonste route voor SOCKS5, waar Chromium geauthenticeerde proxies ronduit weigert (bijgehouden als Chromium-bug 40829748). We behandelen de minimale relay, de kant-en-klare tools, en wanneer het overkill is in de proxy relay handleiding.

Een opmerking over SOCKS5

Niet-geauthenticeerde SOCKS5 werkt via de vlag — --proxy-server=socks5://host:port — maar geauthenticeerde SOCKS5 niet, en geen CDP-handler redt je omdat Chromium nooit SOCKS5 gebruikersnaam/wachtwoord ondersteuning heeft geleverd. De praktische antwoorden zijn dezelfde drie: whitelist het IP, draai een relay, of gebruik het HTTP-eindpunt van de provider in plaats daarvan. Elk QuantumProxies-plan biedt zowel HTTP als SOCKS5 proxies op dezelfde gateway, dus overschakelen naar het HTTP-eindpunt is vaak de snelste SOCKS5 oplossing van allemaal. Voor anti-detect browsers als familie vergelijkt de geauthenticeerde-proxy kaart nodriver, zendriver en de rest naast elkaar.

Stroomdiagram dat laat zien hoe IP-whitelisting bij de proxy-gateway een nodriver-script laat draaien met een eenvoudige proxy-vlag en zonder inlogdialoog
Wanneer het egress-IP stabiel is, authenticeert whitelisting de machine en verdwijnt de auth-code volledig.

Veelgestelde vragen

Ondersteunt nodriver geauthenticeerde proxies?

Niet native. Je kunt een niet-geauthenticeerde proxy doorgeven via browser_args=["--proxy-server=host:port"], maar user:pass in die vlag wordt gestript door Chromium. Om te authenticeren moet je ofwel je IP whitelisten bij de provider, de uitdaging beantwoorden met een CDP Fetch.AuthRequired handler, een proxy-auth Chrome-extensie genereren, of een lokale relay draaien die de inloggegevens vasthoudt.

Waarom ontvangt mijn nodriver auth handler geen events?

Bijna altijd omdat je het Fetch domein hebt ingeschakeld voordat je de handlers registreerde. nodriver's interne enable overschrijft de registratie, dus events bereiken je callback nooit. Voeg eerst de RequestPaused en AuthRequired handlers toe, en roep dan fetch.enable(handle_auth_requests=True) aan. Omhul je antwoorden ook in asyncio.create_task zodat het wachten erop de loop niet kan blokkeren.

Kan nodriver een SOCKS5 proxy gebruiken met een gebruikersnaam en wachtwoord?

Nee. Chromium ondersteunt geen geauthenticeerde SOCKS5 (Chromium-bug 40829748), en nodriver erft die beperking. Niet-geauthenticeerde SOCKS5 werkt via --proxy-server=socks5://host:port. Voor geauthenticeerde SOCKS5, whitelist je IP, draai een lokale relay die de inloggegevens toevoegt, of schakel over naar het HTTP-eindpunt van de provider, dat Basic auth netjes afhandelt.

nodriver of zendriver voor geauthenticeerde proxies?

Beide delen dezelfde kloof en dezelfde oplossingen, omdat zendriver een community-fork van nodriver is. zendriver heeft een actiever issuetracker waar de auth-vraag openlijk wordt besproken, maar de werkende methoden zijn identiek. Als je op de fork zit, spiegelt de fork-specifieke setup alles hier — de CDP-handler en whitelisting gedragen zich hetzelfde.

De eerlijke samenvatting: nodriver zal geen proxy-auth voor je doen, en dat is prima zodra je de kaart kent. Whitelist wanneer je IP stabiel is, grijp naar de CDP-handler of extensie wanneer dat niet zo is, en houd een relay achter de hand voor SOCKS5. De code hierboven beantwoordt de uitdaging — maar een schone residentiële exit is wat je daadwerkelijk door de deur krijgt.

Draai nodriver op gewhiteliste residentiële IP's