Zum Inhalt springen
Zurück zum Blog

Nodriver-Python-Tutorial: Unauffälliges Web-Scraping – vom ersten Skript bis zur Produktion

Suciu DanZuletzt aktualisiert am 12 min read
Nodriver-Python-Tutorial: Unauffälliges Web-Scraping – vom ersten Skript bis zur Produktion
Kurzfassung: Nodriver ist eine asynchrone Python-Bibliothek, die Chromium über das Chrome DevTools Protocol steuert, ohne Selenium oder chromedriver-Binary. Nutzen Sie sie, wenn ein selbst gehosteter Stealth-Browser, der einer echten Chrome-Sitzung näherkommt, besser passt als ein WebDriver-Stack – aber sie beseitigt IP-, TLS- oder Verhaltensrisiken nicht von allein. Dieses Tutorial führt vom ersten Skript bis zur containerisierten Produktion und einer gehosteten Browser API.

Nodriver ist eine asynchrone Python-Bibliothek, die Chromium über das Chrome DevTools-Protokoll steuert – ganz ohne Selenium und ohne chromedriver-Binärdatei. Man greift darauf zurück, wenn ein selbst gehosteter Stealth-Browser, der sich eher wie eine echte Chrome-Sitzung anfühlt, einem klassischen WebDriver-Stack überlegen ist. Dieser Leitfaden beginnt mit einem funktionierenden Scraper in einer öffentlichen Sandbox, führt über eine containerisierte Produktionsumgebung und endet damit, wann derselbe Ablauf stattdessen in eine gehostete Browser-API gehört.

Wichtige Erkenntnisse

  • Nodriver kommuniziert direkt über das CDP; es beseitigt IP-, TLS- oder Verhaltensrisiken nicht von selbst.
  • Fixieren Sie die Version. Ab Version 0.50.3 + Chrome 154 (06.10.2026) select gibt None bei einem Fehlschlag wait_for löst einen Fehler aus und xpath mit DOM.enable „missing“.
  • Bevorzugt uc.loop() anstelle von asyncio.run für ein ordnungsgemäßes Herunterfahren; browser.stop() ist synchronisiert.
  • Für Arbeiten, bei denen Unauffälligkeit wichtig ist, ist Chrome mit grafischer Benutzeroberfläche unter Xvfb vorzuziehen: Der headless-Modus kann dennoch HeadlessChrome im User-Agent-String an.
  • In der Produktion scheitern Scraper: Container, begrenzte Parallelität, Wiederholungsversuche, Überprüfung der Ausgangs-IP, Ausgabevalidierung.
  • Ordne Wartezeiten/Aktionen den Parametern der Browser-API zu (wait_for_css, wait_until, js_instructions, …) zuordnen, wenn ihr über das Selbsthosting hinauswachst.

Was „nodriver“ ist (und was es nicht ist)

CDP Direct vs. WebDriver

Klassischer Selenium-Weg:

Your script  →  WebDriver protocol  →  chromedriver  →  Chrome

Nodriver-Ansatz:

Your script  →  Chrome DevTools Protocol (websockets)  →  Chrome

Durch das Weglassen der Treiber-Binärdatei entfallen WebDriver-spezifische Automatisierungsmarker sowie eine ganze Reihe von Fehlern aufgrund von Versionsabweichungen. Es sorgt jedoch nicht dafür, dass Ihre IP-Adresse wie die eines Privatanwenders aussieht, Ihr TLS-Stack einzigartig ist oder Ihr Klick-Timing dem menschlichen Verhalten entspricht.

Ableitung von „undetected-chromedriver“

Nodriver ist der asynchrone, CDP-orientierte Nachfolger aus derselben Autorenlinie wie „undetected-chromedriver“. Das Modell wechselt von „den Treiber patchen“ zu „den Treiber niemals verwenden“. Nur für Browser der Chromium-Familie; ausschließlich asynchrone API.

Welche Erkennungsschichten es abdeckt

Ebene

Worauf Verteidiger achten

Was „nodriver“ verändert (Modell)

JS-Umgebung

navigator.webdriver, Eigenheiten des Chrome-Objekts

Verbessert den Standard-JS-Automatisierungs-Footprint im Vergleich zu „Raw WebDriver“ (muss dennoch pro Zielsystem überprüft werden)

Protokoll / Treiber

Chromedriver-Fingerabdrücke

Vermeidet WebDriver durch Verwendung von CDP

TLS / HTTP2

JA3 / ALPN / HTTP2-Fingerabdrücke

Ersetzt den Netzwerkstack des Browsers nicht

IP / ASN / Geolokalisierung

Rechenzentrumsbereiche, Reputation

Behebt das Problem nicht; erfordert Proxys / Routing über Privathaushalte

Verhalten

Timing, Mausbewegungen, Scrollmuster

Erfindet kein menschliches Verhalten für Sie

Headless-Signale

HeadlessChrome UA, fehlende Plugins usw.

Modusabhängig; siehe unseren Abschnitt zu „Headless“

Sollte Ihr Team auf nodriver aufbauen? (Entscheidungsbox)

Überprüft am 06.10.2026 im Rahmen der Veröffentlichungsvorbereitung:

  • Lizenz: AGPL-3.0 für das von uns installierte PyPI-Paket. Dies ist relevant für netzwerkgebundene Dienste, die den Code ändern und ausführen. Dies ist keine Rechtsberatung – lassen Sie die AGPL von einem Anwalt prüfen, wenn Sie ein SaaS auf Basis eines Forks bereitstellen.
  • API-Form: ausschließlich asynchron; Browser der Chromium-Familie.
  • Wartung: Die letzte für diesen Leitfaden überprüfte PyPI-Version ist 0.50.3 (13.05.2026). Überprüfen Sie am Tag der Veröffentlichung noch einmal die Sterne/Issues/Commits, bevor Sie sich für eine mehrjährige Plattformentscheidung festlegen.
  • Testabdeckung / Alpha-Klassifizierung: PyPI listet weiterhin den Entwicklungsstatus :: 3 – Alpha auf. Rechnen Sie mit Fehlern, wenn Chrome Änderungen vornimmt.
  • Forks: Zendriver und andere CDP-Forks stehen zur Verfügung, falls Sie eine andere Wartungsstrategie benötigen – siehe die Tool-Matrix weiter unten.

Benötigen Sie Multi-Browser-Unterstützung (Firefox/WebKit), Synchronisierungs-APIs oder eine freizügige Lizenz für ein kommerzielles Produkt ohne AGPL-Analyse? Dann ist Nodriver möglicherweise die falsche Grundlage.

Installieren und überprüfen (pinned)

python3 -m venv venv
source venv/bin/activate
pip install 'nodriver==0.50.3'

Checkliste für die Installation:

  1. Python ≥ 3.9.
  2. Eine lokale Chrome/Chromium-Installation (überprüfen Sie dies mit google-chrome --version).
  3. Laufzeit-Abhängigkeiten werden automatisch heruntergeladen: websockets>=14 , mss, deprecated.
  4. Benennen Sie Ihr Skript nicht nodriver.py (das überschreibt das Paket).
  5. Smoke: Öffne eine öffentliche Seite und warte auf einen Selektor (Skript siehe unten).

Ihr erster Scraper

Sandbox für diesen Artikel: quotes.toscrape.com – ein anderes Demo-Ziel als die Storefront, die in mehreren konkurrierenden Tutorials verwendet wird.

# 01_first_scraper.py — verified 2026-10-06 on nodriver 0.50.3
import nodriver as uc

async def main():
    browser = None
    try:
        browser = await uc.start(headless=True)
        tab = await browser.get("https://quotes.toscrape.com/")
        await tab.select("div.quote", timeout=15)  # wait for state, not time
        quotes = await tab.select_all("div.quote")
        for q in quotes:
            text_el = await q.query_selector("span.text")
            author_el = await q.query_selector("small.author")
            print((text_el.text or "").strip(), "—", (author_el.text or "").strip())
    finally:
        if browser is not None:
            browser.stop()  # sync on 0.50.3 — do not await

if __name__ == "__main__":
    # Package README recommends uc.loop(); see event-loop notes below
    uc.loop().run_until_complete(main())

Zuverlässiges Auswählen und Extrahieren

Entscheidungstabelle für Selektor-Methoden (0.50.3)

Anforderung

Methode

Bei Fehlschlag (0.50.3, 06.10.2026)

Verwendung bei

Warten + CSS

await tab.select(css, timeout=…)

Gibt None (löst keinen Fehler aus; Docstring ist falsch)

Standard-Wartezeit

Einmalige CSS-Wartezeit

await tab.query_selector(css)

Gibt None

Sie wissen bereits, dass das DOM bereit ist

Wartezeit, die laut fehlschlagen muss

await tab.wait_for(selector=…)

Löst TimeoutError

Hartes Gate, bevor es weitergeht

Textsuche

await tab.find(text, best_match=True)

Leichter Fehler nach Wiederholungsversuchen

Schaltflächen/Beschriftungen ohne stabiles CSS

Viele Knoten

await tab.select_all(css)

Verhalten, das bei Wiederholungsversuchen an eine leere Liste erinnert

Listen/Karten

XPath

await tab.xpath(…)

Funktioniert nicht mehr ab Version 0.50.3 + Chrome 154 — ProtocolException: 'DOM.enable' wasn't found

CSS-Selektoren bevorzugen

Text- und Attribut-Helfer

def attr_get(el, name: str):
    if el is None:
        return None
    attrs = el.attrs  # ContraDict in nodriver 0.50.3
    if attrs is None:
        return None
    try:
        return attrs.get(name)
    except Exception:
        try:
            return attrs[name]
        except Exception:
            return None

# Observed: element.text and element.text_all both return usable strings

XPath-Status unter 0.50.3 + Chrome 154

Fehler in Chrome 154 + nodriver 0.50.3 (06.10.2026) beim Aufruf von DOM.enable. XPath-abhängige Scraper sollten in dieser Kombination nicht ohne erneute Überprüfung ausgeliefert werden.

Dynamische Seiten

Warten auf Zustand, nicht auf Zeit

Warten auf einen Selektor, Text oder eine Netzwerk-Ruhebedingung. Ist sleep dient der seltenen visuellen Fehlersuche – nicht für endgültige Scraper. Bevorzugen Sie select / wait_for statt tab.sleep in Produktionsumgebungen.

Paginierung, die Navigationen übersteht

Nachdem Sie auf „Weiter“ geklickt haben, können alte Element-Handles getrennt werden. Führen Sie bei jedem Versuch eine erneute Abfrage des Steuerelements durch; warten Sie auf eine URL-Änderung oder einen neuen Inhaltsselektor.

# Pagination retry pattern for quotes.toscrape.com-style next links
async def click_next_with_retry(tab, max_attempts=3) -> bool:
    for _ in range(max_attempts):
        next_link = await tab.select("li.next > a", timeout=5)
        if next_link is None:
            return False
        before = tab.url
        try:
            await next_link.click()
        except Exception:
            continue
        for _ in range(20):
            await tab.sleep(0.25)
            await tab.select("div.quote", timeout=2)
            if tab.url != before:
                return True
        if tab.url != before:
            return True
    return False

Seiten 1→2→3 weitergeschaltet; Autoren wurden wie erwartet geändert.

Unendliches Scrollen mit Stoppbedingungen

Bei Seiten ohne „Weiter“-Link scrollen Sie bis zum Eintreten einer Stoppbedingung: einer Endmarkierung, einer Zählplateau oder der maximalen Anzahl an Runden.

async def scroll_until_plateau(tab, max_rounds=20):
    history = []
    plateau = 0
    for round_i in range(1, max_rounds + 1):
        items = await tab.select_all("div.item")
        count = len(items)
        end = await tab.query_selector("#end-marker")
        history.append(count)
        if end is not None:
            return {"reason": "end_marker", "count": count}
        if len(history) >= 2 and history[-1] == history[-2]:
            plateau += 1
        else:
            plateau = 0
        if plateau >= 2:
            return {"reason": "count_plateau", "count": count}
        await tab.evaluate("window.scrollTo(0, document.body.scrollHeight)")
        await tab.sleep(0.4)
    return {"reason": "max_rounds", "count": history[-1] if history else 0}

Halt bei end_marker bei 40 Elementen nach 4 Runden.

Klicks, Registerkarten, Iframes und „evaluate“ (kurz)

  • Neuer Tab/neues Fenster: browser.get(url, new_tab=True) / new_window=True (Paket-API).
  • tab.evaluate(expr) Für Scroll-/DOM-Abfragen – Selektoren bevorzugen, wann immer möglich.
  • Cookies: Behandeln Sie JAR-Dateien wie geheime Daten; schwärzen Sie sie in Protokollen (Sicherheitshinweis, kein ausführliches Cookie-Tutorial).
  • Screenshots: await tab.save_screenshot(...) haben in unserem Diagnosetest funktioniert.

Identität: User-Agent, Headless und Xvfb

Eine konsistente Identität vs. Rotation

Passen Sie den User-Agent an die Chrome-Version an, die Sie tatsächlich starten. Eine zufällige Rotation, die nicht mit Chrome/154 (oder was auch immer Sie ausführen), ist ein leicht zu erkennendes Anzeichen. Bevorzugen Sie eine stabile Desktop-Identität pro Worker-Profil.

Headless-Signale in Chrome 154 (06.10.2026)

Nur bei öffentlichen Diagnoseseiten (bot.sannysoft.com; areyouheadless 502-Fehler für beide Modi):

Modus

navigator.userAgent

navigator.webdriver

headless=True

enthält HeadlessChrome/154.0.0.0

False

headless=False unter Xvfb

enthält Chrome/154.0.0.0 (kein Headless-Modus)

False

Das 154.0.0.0 in diesen Zeichenfolgen enthaltene „build“ ist die verkürzte User-Agent-Form von Chrome und kein Tippfehler im Vergleich zur vollständigen 154.0.8037.57 Binärversion. Nodriver kann navigator.webdriver in beiden Modi löschen, während sich der Headless-Modus weiterhin über die User-Agent-Zeichenkette identifiziert. Das allein reicht für viele einfache Überprüfungen aus.

Unter Xvfb als Standard für Arbeiten, bei denen Unauffälligkeit wichtig ist

Auf Linux-Servern ohne physischen Bildschirm:

# pattern
xvfb-run -a python your_scraper.py
# or export DISPLAY to a running Xvfb and start(headless=False)

Verwende den „headless“-Modus für interne Sandboxes und CI. Verwende den „headed“-Modus mit Xvfb, wenn das Ziel die „headless“-User-Agent-Zeichenfolgen identifiziert.

Proxys ohne Preisgabe Ihrer IP-Adresse

Nicht authentifizierte vs. authentifizierte Proxys

Gehen Sie nicht von Chrome-Flag-Einstellungen aus anderen Blogs aus. Bevor Sie Anmeldeabfragen hinter einem Proxy automatisieren, überprüfen Sie in Ihrer Chrome-Version, ob die Ausgangs-IP des Browsers die Proxy-IP ist – und nicht Ihre Host-IP.

Überprüfen Sie immer die Ausgangs-IP

# Guard pattern — wire to your proxy stack; always assert exit IP before scraping
async def assert_exit_ip(tab, expected_subnet_prefix: str | None = None):
    tab2 = await tab.browser.get("https://httpbin.org/ip")  # or your IP echo
    await tab2.select("body", timeout=15)
    body = (await tab2.get_content()) if hasattr(tab2, "get_content") else None
    # parse JSON IP; compare to expected proxy IP; fail closed
    return body

Brechen Sie den Auftrag ab, wenn die beobachtete Ausgangs-IP die Ihres Rechenzentrums-Hosts ist. Führen Sie diese Überprüfung auch in der Produktion durch, selbst wenn der Proxy „konfiguriert zu sein scheint“.

Privathaushalts- und Geo-Routing

Wenn das Problem in der IP-Reputation oder der Länderzuordnung liegt – und nicht in der DOM-Automatisierung –, leiten Sie den Datenverkehr über private Proxys weiter oder verlagern Sie die Browser-Aufgaben auf eine Browser-API-Anfrage mit country set.

Einsatz von nodriver in der Produktion

Die meisten Tutorials hören an dieser Stelle auf. Hier scheitern die Scraper.

Container-Rezept (Übersicht)

# Outline only — adapt paths and package names for your base image
FROM python:3.13-slim-bookworm
RUN apt-get update && apt-get install -y --no-install-recommends \
    wget gnupg ca-certificates fonts-liberation xvfb \
    && install Google Chrome / Chromium per your distro docs \
    && useradd -m scraper
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
USER scraper
ENV DISPLAY=:99
CMD ["sh", "-c", "Xvfb :99 -screen 0 1920x1080x24 & python worker.py"]

Hinweise: Als Nicht-Root ausführen; die Chrome-Sandbox-Flags in eingeschränkten Containern verstehen; Profile auf einem beschreibbaren Volume speichern, wenn Sie mühsam gewonnene Cookies wiederverwenden; und diese Cookies in den Protokollen unkenntlich machen.

Parallelitätsmodell

Einheit

Isolation

Typische Verwendung

Tabs in einem Browser

Gemeinsamer Prozess/Cookies/Fingerabdruck

Verwandte Schritte in einer Sitzung

Mehrere Browser

Bessere Isolierung, mehr RAM

Parallele Aufträge

Mehrere Prozesse/Container

Stärkste Isolation

Worker-Flotten

Begrenzte Parallelität mit einer asyncio.Semaphore (oder Queue-Workern). Messen Sie den Speicherverbrauch pro Browser auf produktionsähnlichen Seiten auf Ihrer Hardware.

Wiederholversuche, Timeouts und Wiederherstellung nach Abstürzen

  • Zeitlimit pro Navigation mit wait_for / select Budgets.
  • Fehler klassifizieren: Timeout, leere Shell, Challenge-Seite, Chrome-Absturz.
  • Starten Sie nach wiederholten Protokollfehlern den Browserprozess neu – nicht nur den Tab.
  • Begrenzung der Wiederholungsversuche durch Backoff mit Jitter.

Beobachtbarkeit

  • Metriken: Erfolg / Blockierung / Timeout / leer pro Host.
  • Screenshot bei Fehlern in den Objektspeicher.
  • Protokoll-Redaktion: Proxy-Benutzername/Passwort, Cookie Header, Speicherauszüge.

Validierung der Ausgabe

Ein „HTTP-ähnlicher“ Erfolg im Browser ist kein brauchbares HTML. Erkennen Sie Challenge-Titel, leere App-Shells und fehlende erforderliche Selektoren, bevor Sie Daten in das Warehouse schreiben. Kombinieren Sie dies mit der Validierungsmentalität aus Ihrem übergeordneten Scraping-Stack (um Blockierungen zu vermeiden).

Realitätscheck zur Bot-Abwehr

Geltungsbereich (06.10.2026): ausschließlich öffentliche Fingerabdruck-/Diagnoseseiten. Keine kommerziellen Cloudflare- oder DataDome-Ziele (gemäß den redaktionellen Richtlinien für diesen Artikel).

Ziel

Ergebnis

bot.sannysoft.com

Geladen; nützlich für den Vergleich von User-Agent- und WebDriver-Sniff-Daten

arh.antoinevastel.com/bots/areyouheadless

502 Bad Gateway – nicht eindeutig

Kommerzielle Seiten von Cloudflare / DataDome / Turnstile

In diesem Leitfaden nicht behandelt

Tab.verify_cf Hilfsprogramm

In Version 0.50.3 vorhanden; als optional behandeln und an Ihren Zielen überprüfen

Betrachten Sie jede Behauptung „nodriver umgeht X“ ohne datierten, abgegrenzten Test als Marketingaussage. Für gehärtete Ziele siehe auch die Produktanleitung zur Umgehung von Cloudflare.

Wählen Sie Ihr Tool aus (Matrix nach Einschränkungen)

Versionen wurden am 06.10.2026 über den PyPI-Index überprüft. Der „Stealth“-Status ist qualitativ und keine Punktzahl.

Tool

Sprache

Browser

Synchron/asynchron

Lizenz (PyPI-Signal)

Stealth-Modus

Betriebsaufwand

nodriver 0.50.3

Python

Chromium-Familie

async

AGPL-3.0

CDP, kein WebDriver

Sie führen Chrome + Display aus

Zendriver 0.17.1

Python

Chromium-Familie

async

AGPL

Abzweigung der nodriver-Linie

Ähnlich

Playwright 1.63.0

viele

Chromium, Firefox, WebKit

beides

Apache-2.0 (Projekt)

Starke Automatisierung, im aktuellen Zustand leichter zu erkennen

Leichtere Treiberverwaltung

Patchright 1.63.0

Python

Chromium/Chrome-Kanal

beides

siehe LIZENZ

Playwright-gepatcht

Ähnlich wie Playwright

Camoufox 0.5.7

Python

Firefox (benutzerdefiniert)

beides

MIT (PyPI)

Firefox-Fingerabdruck-Winkel

Browser-Binär-Ops

SeleniumBase 4.55.1 (CDP-Modus)

Python

Chromium

beides

MIT

Option „CDP-Modus“

Framework-Größe

Hosted-Browser-API

beliebig (HTTP)

verwaltet

k. A.

kommerziell

Vom Anbieter betrieben

Geringster lokaler Betriebsaufwand

Auswahl nach Vorgaben: Lizenz, Browser-Engine, Synchronisierungsanforderungen und wer für die Verfügbarkeit verantwortlich ist.

Selbst entwickeln oder kaufen: selbst gehosteter Nodriver oder ein gehosteter Browser

Was die Kosten bestimmt

  • Anzeige-/Xvfb-/GPU-Eigenheiten auf Cloud-VMs
  • RAM und CPU pro gleichzeitigem Chrome-Prozess
  • Privat- oder Mobil-Proxys
  • Entwicklungsaufwand für Chrome-Upgrades und fehlerhafte Selektoren
  • Block-Bearbeitung und Bereitschaftsdienst
  • Speicherung von Screenshots und Schwärzung personenbezogener Daten
  • Überprüfung der AGPL-Konformität

Selbst hosten, wenn Sie lange interaktive Sitzungen, benutzerdefinierte Erweiterungen oder eine enge Anbindung an interne Netzwerke benötigen. Kaufen, wenn Sie sich um SLAs für Anfragen/Antworten, geografische Einschränkungen und die Browserwartung keine Gedanken mehr machen möchten.

Nodriver → Übersetzungstabelle für die Browser-API

Die Browser-API ist ein REST-Aufruf an https://api.webscrapingapi.com/v1—keinen Live-CDP-Socket (Produktbestätigung). Parameternamen am 06.10.2026 in den API-Parametern überprüft:

Nodriver-Muster

Browser-API-Parameter

Warten auf CSS (select / wait_for)

wait_for_css

Lebenszyklus-Bereitschaft

wait_until (domcontentloaded, load, networkidle0, networkidle2)

Zusätzliche Verzögerung

wait_for (ms)

Klick-/Scroll-/Eingabe-Sequenzen

js_instructions

Screenshot

screenshot=1 (+ screenshot_options)

Feld-Extraktion

extract_rules

Geokontext

country

Gerät / Ansichtsbereich

device, window_width, window_height

Dokumentation: GET-Anfrage, Rendering mit JavaScript.

Wenn die Scraper-API ( render_js=1 ) ausreicht

render_js=1) ausreicht

Wenn Sie lediglich einen gerenderten HTML-Snapshot ohne mehrstufiges Interaktionsskript benötigen, beginnen Sie mit der Scraper-API und der JS-Rendering-Funktion. Wechseln Sie zur Browser-API, wenn Sie in einer einzigen Anfrage geordnete Aktionen, Selektor-Wartezeiten, Screenshots oder Extraktionsregeln benötigen. Vergleichen Sie die Optionen unter „Web Access APIs“.

Fehlerbehebung (Symptom → Ursache → Lösung)

Aus Fehlern, die wir am 06.10.2026 reproduziert haben:

Symptom

Mögliche Ursache

Behebung

select gibt None nach Zeitüberschreitung

Selektor falsch oder Inhalt wurde nie gerendert

Selektor korrigieren; mit wait_for , falls ein harter Fehler erforderlich ist

TimeoutError von wait_for

Erwartet – Fehlschlag nach Budget

Wartezeit verlängern oder Screenshot erstellen

ProtocolException: 'DOM.enable' wasn't found

xpath Pfad in unserem Chrome 154 + 0.50.3

CSS verwenden; XPath nach Upgrades erneut testen

UA enthält HeadlessChrome

headless=True

Ausführung unter Xvfb für sensible Ziele

Ausstehende Aufgaben / Event loop is closed nach dem Skript

asyncio.run Shutdown vs. Nodriver-Listener

Bevorzugen uc.loop(); stellen Sie sicher, browser.stop() in finally

Zitierliste nach „Erfolg“ leeren

Zu früh navigiert / falsche Seite

Erneut auf Inhaltsauswahl warten; Anzahl überprüfen

Paginierung hängte sich auf

Veralteter „Weiter“-Link

Erneutesselect Steuerelement bei jedem Versuch

Proxy „funktioniert“, aber die Website erkennt die lokale IP-Adresse

Fehlerhafte Konfiguration von Authentifizierung/Proxy

Exit-IP-Schutz vor dem Scraping

Verantwortungsbewusste Nutzung

Nur zulässige öffentliche Seiten scrapen, Robots-Dateien, Nutzungsbedingungen und geltendes Recht beachten, personenbezogene Daten minimieren und Zugangsdaten sichern. Lesen Sie „Verantwortungsbewusster Umgang mit Webdaten“. Für einen umfassenderen Überblick über den Headless-Kontext siehe „Python-Headless-Browser“.

FAQ

Was ist nodriver?

Eine asynchrone Python-Bibliothek, die Chromium über CDP ohne Selenium oder Chromedriver steuert. In dieser Anleitung wird Version 0.50.3 verwendet (Stand: 06.10.2026).

Wie unterscheidet sich nodriver von undetected-chromedriver und Selenium?

Selenium verwendet WebDriver + eine Treiber-Binärdatei. „Undetected-chromedriver“ patcht diesen Pfad. Nodriver umgeht WebDriver und kommuniziert asynchron über CDP.

Ist nodriver nachweisbar?

Es unterdrückt zwar einige Automatisierungssignale, beseitigt jedoch keine IP-, TLS-, Verhaltens- oder Headless-UA-Lecks. In unserem Test navigator.webdriver war False, doch der Headless-Modus war weiterhin HeadlessChrome im UA sichtbar.

Funktioniert „nodriver“ im Headless-Modus?

Ja, für funktionsfähiges Scraping in unserer Sandbox. Bei Zielen, bei denen Tarnung wichtig ist, empfehlen wir aufgrund der von uns gemessenen Unterschiede bei der User-Agent-Zeile den „Headed“-Modus in Kombination mit Xvfb.

Wie verwende ich einen authentifizierten Proxy mit „nodriver“, ohne meine IP-Adresse preiszugeben?

Konfigurieren Sie den Proxy für Ihre Chrome-Version und überprüfen Sie vor jedem Auftrag stets die Ausgangs-IP.

Kann nodriver Cloudflare oder DataDome umgehen?

Man sollte keine allgemeinen Rückschlüsse von Diagnoseseiten auf kommerzielle Bot-Produkte ziehen. Wenn Sie verify_cf Version 0.50.3 verwenden, überprüfen Sie dies an Ihren eigenen Zielen, bevor Sie sich darauf verlassen.

Nodriver vs. Playwright vs. Zendriver: Was sollte ich verwenden?

Entscheiden Sie sich anhand von Lizenz, Browser-Engine, synchronen/asynchronen Anforderungen und der Zuständigkeit für den Betrieb – siehe die obige Matrix. Playwright ist bei mehreren Engines die beste Wahl; nodriver/zendriver sind unter AGPL für eine unauffällige CDP-Präsenz optimiert; die gehostete Browser-API ist die beste Wahl, wenn Sie keine Chrome-Flotten einsetzen möchten.

Wie führe ich Nodriver in Docker oder auf einem Linux-Server aus?

Installieren Sie Chrome, führen Sie „headed“ unter Xvfb aus (oder akzeptieren Sie die Kompromisse des „headless“-Modus), als Nicht-Root-Benutzer und mit begrenzten Workern. Verwenden Sie die Dockerfile-Vorlage als Ausgangspunkt und validieren Sie das Image in Ihrer Umgebung.

Wie viele nodriver-Browser kann ich parallel ausführen?

Testen Sie dies auf Ihrer Hardware und mit Ihren Zielseiten. Vertrauen Sie keinen Angaben zur Parallelität, ohne eigene Zahlen zu haben.

Ist die kommerzielle Nutzung von nodriver sicher (Lizenz)?

Das von uns installierte Paket unterliegt der AGPL-3.0. Lassen Sie es von einem Rechtsbeistand prüfen, bevor Sie es in einen Netzwerkdienst einbinden. Dies stellt keine Rechtsberatung dar.

Wann sollte ich eine gehostete Browser-API anstelle von nodriver verwenden?

Wenn Sie REST-Wartezeiten/Aktionen/Geodaten nutzen möchten, ohne Chrome auszuführen, oder wenn die Kosten für Proxy und Wartung überwiegen. Wandeln Sie Ihre „nodriver waits“ in wait_for_css / js_instructions und vergleichen Sie eine einzelne Anfrage.

Nächster Schritt

Nehmen Sie eine Seite, die Ihr nodriver-Skript bereits verarbeitet, und senden Sie sie über eine einzige Browser-API-Anfrage mit wait_for_css (und js_instructions falls Sie scrollen oder klicken). Vergleichen Sie den Entwicklungsaufwand, die Fehlerquellen und die Form der Ausgabe. Bei hohem Datenaufkommen, geografischen Anforderungen oder verwalteter Bereitstellung wenden Sie sich bitte an das WebScrapingAPI-Team.


Über den Autor

Suciu Dan, Mitbegründer @ WebScrapingAPI

Suciu Dan

Mitbegründer

Suciu Dan ist Mitbegründer von WebScrapingAPI und verfasst praxisorientierte, auf Entwickler zugeschnittene Anleitungen zu den Themen Web-Scraping mit Python, Web-Scraping mit Ruby und Proxy-Infrastruktur.

Umgang mit Google-/goto-Weiterleitungs-URLs und CAES-Token in einem SERP-Scraper
Die Wissenschaft des Web-Scrapings

Umgang mit Google-/goto-Weiterleitungs-URLs und CAES-Token in einem SERP-Scraper

TL;DR: Kurzfassung: Google-/goto-URLs mit CAES-Token und ältere /url-Wrapper sind Weiterleitungsschichten, keine Ziele; ein SERP-Scraper, der jede href als endgültig behandelt, verfälscht Rank-Tracking und Link-Datenbanken. Bevorzugen Sie eine strukturierte SERP-API, wenn sie Ziel-Links liefert. Wenn Sie HTML parsen müssen, klassifizieren Sie jede href, deduplizieren Sie Weiterleitungen und lösen Sie sie mit einem einfachen GET auf. Entschlüsseln Sie CAES nicht.

Suciu Dan11 min read
Artikel lesen
HTTP-Antwort-Header in cURL: Jedes Flag, jede Technik und jedes Skripting-Rezept
Die Wissenschaft des Web-Scrapings

HTTP-Antwort-Header in cURL: Jedes Flag, jede Technik und jedes Skripting-Rezept

TL;DR: cURL verbirgt standardmäßig Antwort-Header. Verwenden Sie -i, um Header neben dem Body zu sehen, -I für eine HEAD-Anfrage, die nur Header zurückgibt, -v für vollständiges Debugging von Anfrage und Antwort und -D, um Header in einer Datei zu speichern. Für modernes Scripting können Sie mit cURL 7.83+ einzelne Header extrahieren oder mit der Option -w write-out alle Header als JSON ausgeben.

Suciu Dan11 min read
Artikel lesen
Was ist ein Headless Browser? Architektur, Anwendungsfälle und Top-Tools
Die Wissenschaft des Web-Scrapings

Was ist ein Headless Browser? Architektur, Anwendungsfälle und Top-Tools

TL;DR: Ein Headless Browser ist ein Webbrowser, der ohne sichtbare grafische Oberfläche läuft und ausschließlich über Code oder Befehlszeilenanweisungen gesteuert wird. Entwickler verwenden Headless-Browser für automatisierte Tests, Web-Scraping, Leistungsüberwachung und zunehmend auch für den Einsatz von KI-Agenten. In diesem Leitfaden erfahren Sie, wie sie intern funktionieren, wann Sie einen solchen Browser einem normalen Browser vorziehen sollten und welche Frameworks Ihre Zeit wert sind.

Suciu Dan12 min read
Artikel lesen

Los geht’s

Sind Sie bereit, Ihre Datenerfassung zu erweitern?

Schließen Sie sich den über 2.000 Unternehmen an, die WebScrapingAPI nutzen, um Webdaten im Unternehmensmaßstab ohne zusätzlichen Infrastrukturaufwand zu extrahieren.