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.

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:
- Registreer de handlers voordat je het domein inschakelt. nodriver's interne
enableoproep overschrijft je handlerregistratie, dus als je ze daarna toevoegt worden er nooit events afgevuurd — de nummer één reden waarom mensen rapporteren 'het doet niets'. - Vuur en vergeet de antwoorden. Het wachten op het antwoord binnen de handler blokkeert de eventloop en vergrendelt de hele browser. Omhul elke verzending in
asyncio.create_taskzodat het zonder blokkeren draait.
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.

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.