Nodriver Proxy-Authentifizierung: Die drei funktionierenden Lösungen

Das Top-Ergebnis für Nodriver Proxy-Authentifizierung ist eine GitHub-Diskussion, kein Leitfaden. Nodriver hat keine native Benutzer:Passwort-Unterstützung — hier sind die drei funktionierenden Lösungen und die Ein-Zeilen-Abkürzung, die die meisten übersehen.

Suchen Sie nach Nodriver Proxy-Authentifizierung und die Top-Ten-Ergebnisse sind eine GitHub-Diskussion, ein Demo-Repo, ein paar Stack Overflow-Threads über eine andere Bibliothek und ein Reddit-Post — kein tatsächlicher Leitfaden. Der Grund ist einfach: Nodriver, der asynchrone CDP-Nachfolger von undetected-chromedriver (dieses Projekt hat 12,8k GitHub-Sterne und 1,3k Forks), hat keine native Möglichkeit, user:pass an einen Proxy zu übergeben. Chrome ignoriert eingebettete Anmeldeinformationen in einem Befehlszeilen-Flag, und Nodriver überdeckt dies nicht. Dieser Leitfaden ist die Seite, die der Diskussionsthread hätte werden sollen: was funktioniert, was nicht, und die drei Lösungen, die einen authentifizierten Proxy zum Laufen bringen.

Ein einfacher Proxy funktioniert; ein authentifizierter Proxy nicht

Ein nicht authentifizierter Proxy ist eine Ein-Zeile. Geben Sie die Adresse über browser_args ein und jede Anfrage verlässt über die 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())

Fügen Sie nun Anmeldeinformationen hinzu — --proxy-server=http://USER:PASS@host:port — und es bricht. Chromium entfernt das USER:PASS@-Segment, da das Flag-Format keinen Anmeldeinformations-Slot hat, dann antwortet der Proxy mit 407 Proxy Authentication Required und Chrome öffnet einen nativen Anmeldedialog, der außerhalb des DOM lebt. Nodriver kann ihn nicht sehen oder ausfüllen. Diese 407 ist die gleiche Hürde, die in unserem Leitfaden zur Behebung von 407-Fehlern behandelt wird: Der Proxy lehnt Sie ab, nicht der Browser. Daher muss jede echte Lösung die Herausforderung auf andere Weise beantworten.

Lösung 1: IP-Whitelisting — keine Anmeldeinformationen, kein Dialog

Dies ist die Abkürzung, die in den GitHub-Threads nie erwähnt wird, und sie ist mit Abstand die einfachste. Wenn Ihr Scraper von einer Maschine mit einer stabilen öffentlichen IP läuft, registrieren Sie diese IP in Ihrem Anbieter-Dashboard und lassen Sie die Anmeldeinformationen vollständig weg — das Gateway authentifiziert Sie über die Quelladresse. Der Nodriver-Code bleibt das einfache --proxy-server-Snippet oben, kein Auth-Code überhaupt. Jeder QuantumProxies-Plan unterstützt IP-Whitelisting neben Benutzer:Passwort auf seinen residential proxies, daher ist dies der empfohlene Weg, wann immer Ihre Ausgangs-IP fest ist. Seine einzige Grenze ist topologisch: Es authentifiziert eine Maschine, nicht ein Skript, daher benötigen flüchtige Cloud-Runner, Container hinter NAT und CI-Boxen mit wechselnden IPs eine der nächsten beiden Lösungen.

Vergleich von vier Nodriver Proxy-Authentifizierungswegen: IP-Whitelisting, ein CDP Fetch Auth-Handler, eine generierte Chrome-Erweiterung und ein lokales Relay
Whitelisting kostet null Code, wenn Ihre IP fest ist; der CDP-Handler und die Erweiterung beantworten die Anmeldeherausforderung, wenn sie es nicht ist.

Lösung 2: Beantworten Sie die Herausforderung mit einem CDP Fetch-Handler

Nodriver spricht direkt das Chrome DevTools-Protokoll, sodass Sie die Auth-Herausforderung im Prozess abfangen können — keine Erweiterungsdatei erforderlich. Aktivieren Sie die Fetch-Domäne mit handle_auth_requests=True, dann antworten Sie auf jedes AuthRequired-Ereignis mit continue_with_auth. Zwei Details, beide aus der Antwort in Diskussion #1798, machen den Unterschied zwischen Funktionieren und Hängen:

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

Ein Vorbehalt tauchte im gleichen Thread auf: Ein Benutzer stellte fest, dass dies auf einfachen HTTP-Seiten funktionierte, aber auf HTTPS fehlschlug, und der Übeltäter war ein minderwertiger Proxy, nicht der Code — der Wechsel zu einem besseren Ausgang behebt es. Das ist die wiederkehrende Lektion des stealth scraping: Der Handler beantwortet die Herausforderung, aber die IP-Reputation entscheidet, ob die Seite Sie hereinlässt.

Lösung 3: Eine generierte Chrome-Erweiterung

Das andere Community-Muster erstellt beim Start eine kleine Chrome-Erweiterung, die sowohl den Proxy setzt als auch die Anmeldeherausforderung über chrome.webRequest.onAuthRequired beantwortet — der gleiche Trick, der in Selenium und Puppeteer funktioniert. Sie schreiben ein kleines Manifest plus einen Hintergrundarbeiter in ein temporäres Verzeichnis und laden es über --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())

Das vollständige Manifest und der Arbeiter sind identisch mit den Manifest V3-Dateien in unserem Selenium Proxy-Authentifizierungsleitfaden — kopieren Sie sie wörtlich, nur der Startaufruf ändert sich. Zwei Stolpersteine wiederholen sich überall: Erweiterungen laden nur unter --headless=new (einfaches --headless schlägt fehl), und ein nicht gepacktes Verzeichnis ist über Chrome-Versionen hinweg zuverlässiger als ein gepacktes Zip. Die Erweiterung behandelt jeden Proxy-Typ, was sie zum Rückgriff macht, wenn der CDP-Weg Ihnen Probleme bereitet.

Die vierte Option: Ein lokales Relay

Wenn Sie Nodriver überhaupt nicht anfassen möchten, führen Sie ein kleines lokales Relay aus, das die Anmeldeinformationen hält und einen No-Auth-Endpunkt auf 127.0.0.1 präsentiert. Nodriver zeigt dann auf die Loopback-Adresse mit dem einfachen Flag und sieht nie eine Herausforderung. Dies ist der sauberste Weg für SOCKS5, bei dem Chromium authentifizierte Proxies vollständig ablehnt (verfolgt als Chromium-Bug 40829748). Wir behandeln das minimale Relay, die fertigen Tools und wann es übertrieben ist in dem Proxy-Relay-Leitfaden.

Eine Anmerkung zu SOCKS5

Nicht authentifiziertes SOCKS5 funktioniert über das Flag — --proxy-server=socks5://host:port — aber authentifiziertes SOCKS5 nicht, und kein CDP-Handler kann Sie retten, da Chromium nie SOCKS5-Benutzername/Passwort-Unterstützung geliefert hat. Die praktischen Antworten sind die gleichen drei: Whitelisten Sie die IP, führen Sie ein Relay aus oder verwenden Sie den HTTP-Endpunkt des Anbieters stattdessen. Jeder QuantumProxies-Plan bietet sowohl HTTP- als auch SOCKS5-Proxies auf dem gleichen Gateway, daher ist der Wechsel zum HTTP-Endpunkt oft die schnellste SOCKS5-Lösung überhaupt. Für Anti-Detect-Browser als Familie vergleicht die authentifizierte Proxy-Karte Nodriver, Zendriver und den Rest nebeneinander.

Ablauf, der zeigt, wie IP-Whitelisting am Proxy-Gateway ein Nodriver-Skript mit einem einfachen Proxy-Flag und ohne Anmelde-Dialog ausführen lässt
Wenn die Ausgangs-IP stabil ist, authentifiziert Whitelisting die Maschine und der Auth-Code verschwindet vollständig.

Häufig gestellte Fragen

Unterstützt Nodriver authentifizierte Proxies?

Nicht nativ. Sie können einen nicht authentifizierten Proxy über browser_args=["--proxy-server=host:port"] übergeben, aber user:pass in diesem Flag wird von Chromium entfernt. Um zu authentifizieren, müssen Sie entweder Ihre IP beim Anbieter whitelisten, die Herausforderung mit einem CDP Fetch.AuthRequired-Handler beantworten, eine Proxy-Auth Chrome-Erweiterung generieren oder ein lokales Relay ausführen, das die Anmeldeinformationen hält.

Warum erhält mein Nodriver-Auth-Handler keine Ereignisse?

Fast immer, weil Sie die Fetch-Domäne aktiviert haben, bevor Sie die Handler registriert haben. Nodrivers interne enable überschreibt die Registrierung, sodass Ereignisse nie Ihren Callback erreichen. Fügen Sie zuerst die RequestPaused- und AuthRequired-Handler hinzu, dann rufen Sie fetch.enable(handle_auth_requests=True) auf. Wickeln Sie auch Ihre Antworten in asyncio.create_task, damit das Warten darauf die Schleife nicht blockieren kann.

Kann Nodriver einen SOCKS5-Proxy mit einem Benutzernamen und Passwort verwenden?

Nein. Chromium unterstützt keine authentifizierten SOCKS5 (Chromium-Bug 40829748), und Nodriver erbt diese Einschränkung. Nicht authentifiziertes SOCKS5 funktioniert über --proxy-server=socks5://host:port. Für authentifiziertes SOCKS5 whitelisten Sie Ihre IP, führen Sie ein lokales Relay aus, das die Anmeldeinformationen hinzufügt, oder wechseln Sie zum HTTP-Endpunkt des Anbieters, der Basic Auth sauber handhabt.

Nodriver oder Zendriver für authentifizierte Proxies?

Beide teilen die gleiche Lücke und die gleichen Lösungen, da Zendriver ein Community-Fork von Nodriver ist. Zendriver hat einen aktiveren Issue-Tracker, in dem die Auth-Frage offen diskutiert wird, aber die funktionierenden Methoden sind identisch. Wenn Sie auf dem Fork sind, spiegelt das fork-spezifische Setup alles hier wider — der CDP-Handler und das Whitelisting verhalten sich gleich.

Die ehrliche Zusammenfassung: Nodriver wird keine Proxy-Authentifizierung für Sie durchführen, und das ist in Ordnung, sobald Sie die Karte kennen. Whitelisten Sie, wenn Ihre IP stabil ist, greifen Sie zum CDP-Handler oder zur Erweiterung, wenn sie es nicht ist, und behalten Sie ein Relay für SOCKS5 in der Hinterhand. Der obige Code beantwortet die Herausforderung — aber ein sauberer Residential-Exit ist das, was Sie tatsächlich durch die Tür bringt.

Führen Sie Nodriver auf whitelisted Residential-IPs aus