Die meisten stoßen auf Crawlee, weil sie eigentlich eine ganz andere Frage beantworten wollen: „Welchen Headless-Browser sollte ich verwenden?“ Das ist die falsche Fragestellung – und genau deshalb gibt es Crawlee. Crawlee ist kein Browser. Es ist das Node-/TypeScript-Framework, das bei Bedarf einen Browser einbindet und ihn weglässt, wenn keiner nötig ist.
Ich habe Crawlee 3.17.0 ein paar Tage lang gegen einen kontrollierten Satz von Test-Fixtures und einige öffentliche Demo-Seiten laufen lassen – auf Node v22.22.3 und macOS. Die zentrale Aussage des Produkts – eine Bibliothek, eine API, darunter entweder ein HTTP-Crawler oder ein echter Browser – wollte ich besonders gründlich prüfen. Denn genau davon hängt ab, ob Crawlee einen Platz im Stack verdient oder ob man direkt zu Playwright greifen sollte. Kurzfassung: Die Zwei-Engine-Story hält stand, mit ein paar Sternchen, auf die ich gleich eingehe.
Was Crawlee eigentlich ist – und was nicht
Crawlee beschreibt sich selbst als Web-Scraping- und Browser-Automation-Bibliothek für Node.js, entwickelt für robuste Crawler. Die offizielle Positionierung ist breit angelegt: Daten für KI, LLMs, RAG oder GPTs extrahieren; HTML, PDF, JPG, PNG und andere Dateien herunterladen; Unterstützung für Puppeteer, Playwright, Cheerio, JSDOM und direkte HTTP-Aufrufe; mit oder ohne sichtbaren Browser; Proxy-Rotation inklusive. Das ist ein ziemlich großes Spielfeld – umso wichtiger ist es zu sagen, was Crawlee nicht ist.
Crawlee ist keine Rendering-Engine. Es bringt keinen eigenen Browser mit. Wenn JavaScript ausgeführt werden muss, steuert Crawlee Playwright oder Puppeteer an, und diese wiederum Chromium (oder einen anderen Browser). Es ist auch kein gehosteter Dienst, den man per Netzwerk aufruft – sondern eine Abhängigkeit, die man installiert und selbst betreibt. Was Crawlee genau ist: die Schicht oberhalb des Fetchers – also die Crawler-Klassen, die Request-Queue, der Storage, die Logik zum Folgen von Links. Anders gesagt: das Crawl-Framework, darunter mit austauschbarem Engine-Slot.
Der Vollständigkeit halber: Die von mir getestete Version war 3.17.0 (veröffentlicht am 04.06.2026), es ist TypeScript, die Lizenz ist Apache-2.0, und das Repository lag am 09.07.2026 bei etwa 24,6k Stars auf apify/crawlee. Die Zahl der Stars schwankt – während ich das Repository beobachtet habe, kamen in zwei Tagen 53 hinzu – also sollte man diese Zahl als Momentaufnahme sehen, nicht als feste Größe.
Die zwei Engines: CheerioCrawler vs. PlaywrightCrawler
Hier zeigt sich, warum das Design überhaupt überzeugt – und genau darauf habe ich den Großteil meiner Zeit verwendet.
CheerioCrawler ist der HTTP-Weg. Er lädt das rohe HTML über den Netzwerk-Request und parst es mit Cheerio – ohne Browser, ohne JavaScript-Ausführung, ohne Rendering. Das ist schnell und günstig. PlaywrightCrawler ist der Browser-Weg. Er startet echtes Chromium, rendert die Seite inklusive allem JavaScript, das den DOM erst erzeugt, und kann sogar Screenshots anfertigen.
Zwei unterschiedliche Engines mit tatsächlich unterschiedlichen Fähigkeiten. Crawlees Aussage ist: Beide verhalten sich ansonsten gleich. Beide nehmen einen requestHandler. Beide bieten run(). Beide folgen Links mit enqueueLinks. Der Wechsel von einer Engine zur anderen ist ein Klassen-Tausch, kein Rewrite – das habe ich bestätigt, indem ich meine Extraktionslogik byte-identisch gelassen und nur die umschließende Crawler-Klasse ausgetauscht habe.

Ein Punkt ist dabei wichtig, weil genau dort die Gleichheit aufhört: Der Zugriff auf den Inhalt ist unterschiedlich. In einem CheerioCrawler-Handler bekommt man $ – ein statisches, bereits geparstes DOM, das man wie mit jQuery abfragt. In einem Browser-Handler erhält man ein lebendes page-Objekt. Die Queue, das Routing und das ganze „Daten hinzufügen, Links folgen“-Gerüst bleiben identisch, aber die Stelle, an der man die Seite tatsächlich liest, hat eine andere Form. Crawlees eigene Doku sagt das sinngemäß ebenfalls – die gemeinsame Schnittstelle betrifft die Crawl-Operationen, während der Inhaltszugriff der Teil ist, der variiert.
| Engine | Wie sie lädt | Führt JavaScript aus? | Mein Lauf (1 dynamische Seite) | Am besten für |
|---|---|---|---|---|
CheerioCrawler | Rohes HTTP + Parsing mit Cheerio | Nein | ~0,035 s | Statisches HTML, JSON-APIs, Geschwindigkeit |
PlaywrightCrawler | Echtes Chromium über Playwright | Ja | ~4,967 s | JS-gerenderte Seiten, Screenshots |
Diese Zeiten stammen von einem einzelnen Rechner und einem einzelnen Lauf – kein Benchmark, sondern nur die Form des Kompromisses. Der Browser-Weg war auf derselben URL ungefähr zwei Größenordnungen langsamer. Das ist der Preis fürs Rendering, und genau deshalb sollte man ihn nicht standardmäßig wählen.
Der Test: gleiche URL, 0 vs. 8/8
Behauptungen sind billig. Warum ich der Zwei-Engine-Story glaube? Weil ich sie zum Scheitern bringen konnte – und sie sich dann durch den Wechsel einer einzigen Klasse reparieren ließ.
Ich habe ein lokales dynamisches Fixture gebaut – eine Katalogseite, deren Produktkarten per JavaScript erst nach dem Laden eingefügt werden, also genau die Art Seite, die im modernen Web längst der Standard ist. Auf dieses Ziel habe ich CheerioCrawler angesetzt. Ergebnis: 0 Produktkarten. Das ist kein Fehler, sondern Physik. Cheerio hat das JavaScript nie ausgeführt, also existierten die Karten im geparsten HTML nicht. Danach habe ich PlaywrightCrawler auf exakt dieselbe URL losgelassen, sonst nichts verändert – und er hat 8 von 8 Produkten gerendert und zur Absicherung einen Screenshot erzeugt.

Damit das nicht nur eine Eigenart meines lokalen Fixtures war, habe ich das gleiche Muster an einer öffentlichen Seite getestet – der JavaScript-Demo Quotes to Scrape, die ihre Zitate clientseitig erstellt. Dasselbe Ergebnis in dieselbe Richtung: CheerioCrawler sah 0 Zitate, PlaywrightCrawler holte 10 zurück.

Wichtig ist mir, sauber zu bleiben, was das beweist: Es ist eine klare Reproduktion dessen, was Crawlee bereits dokumentiert – seit Version 3.0 teilen sich die verschiedenen Crawler-Typen dieselbe Basisklasse und Schnittstelle. Das hier ist also eine Verifikation, keine Entdeckung. Aber genau das macht den Wert aus: Die Marketingaussage „eine Schnittstelle, HTTP oder Browser“ stimmt – und hier ist der 0-zu-vollen-Daten-Beleg, einmal auf einem kontrollierten Fixture und einmal auf einer fremden Seite.
Wo der HTTP-Weg gewinnt
Man könnte den Abschnitt oben leicht so lesen, als müsse man „immer den Browser nehmen“. Tut man aber nicht. Gerade weil das Zwei-Engine-Design wichtig ist, ist der Browser die teure Ausweichlösung – nicht die Standardwahl.
Bei statischem Inhalt war CheerioCrawler präzise und schnell. Mein statisches Katalog-Fixture lieferte 12 von 12 Produkten mit voller Trefferquote, folgte der Pagination via enqueueLinks({ selector: '.next-page' }) und brauchte dafür etwa 0,155 Sekunden. Eine Artikelseite gab Titel und alle 3 von 3 Textabsätze sauber heraus, während Login-/Subscribe-/Copyright-Standardtexte elegant vom eigentlichen Inhalt getrennt blieben.
Der wichtigste Punkt: Eine Seite, deren Daten per JavaScript geladen werden, hat oft eine JSON-API direkt dahinter. Die Daten meines dynamischen Fixtures lagen an einem Endpoint, und als ich CheerioCrawler direkt auf diese API angesetzt habe, bekam ich 8 von 8 Produkte zurück – ganz ohne Browser, in rund 0,035 Sekunden. Dieselben Daten brauchte der Browser-Weg fast fünf Sekunden zum Rendern. Die alte, aber immer noch wahre Lehre lautet: Wenn man den zugrunde liegenden Request nachbilden kann, sollte man genau das tun, statt Chromium zu starten. Crawlee ermöglicht diese Entscheidung pro Crawler, ohne das Framework zu wechseln.
Der Teil als Crawl-Framework – warum man Crawlee gegenüber einer nackten Browser-Lib wählen sollte
Wenn man nur eine Seite rendern müsste, bräuchte man Crawlee nicht – dann würde man Playwright oder Puppeteer direkt verwenden. Was eine reine Browser-Library nicht mitbringt, ist ein echter Crawl: Queue, Deduplizierung, Tiefensteuerung, Retries. Genau das ist der Teil von Crawlee, der nichts mit Engines zu tun hat.
Ich habe einen Crawl über denselben Host von einem Fixture-Root aus mit enqueueLinks und Tiefen-Tracking ausgeführt. Crawlee lief über 11 Seiten mit den Tiefen {0:1, 1:3, 2:7} – eine Root-Seite, drei Seiten einen Hop entfernt und sieben Seiten zwei Hops entfernt – und hielt sich an maxRequestsPerCrawl als Stopp-Bedingung. Die RequestQueue übernahm die gesamte Verwaltung. Als ich eine Anfrage an eine Seite mit HTTP 500 schickte, versuchte Crawlee es erneut und meldete den Fehler anschließend über den failedRequestHandler, statt ihn still zu verschlucken oder den Lauf abstürzen zu lassen.

Das ist das stärkste Argument für Crawlee gegenüber einem Standalone-Browser-Tool: Die Crawl-Orchestrierung ist eingebaut – und zwar dieselbe Orchestrierung, egal ob darunter HTTP oder ein Browser arbeitet. Man schreibt Queue- und Follow-Logik einmal. Und entscheidet separat, ob der jeweilige Crawler JavaScript rendert.
Installation und der versteckte Browser-Download
Die Installation war größtenteils unkompliziert – mit einer Falle, die Erstnutzer ziemlich sicher erwischt.
npm install crawlee playwright lief sauber durch – 0 gemeldete Sicherheitslücken. Aber PlaywrightCrawler startet erst, wenn zusätzlich npx playwright install chromium ausgeführt wird. Dabei wird ein Chromium-Binary von etwa 81,7 MiB heruntergeladen. Allein das crawlee-Paket installiert keinen Browser. Wer diesen Schritt überspringt und direkt mit einem Browser-Crawler loslegt, bekommt einen Startfehler, der nicht sofort offensichtlich ist, wenn man das Packaging-Modell von Playwright nicht schon kennt. Das ist inherited Playwright-Verhalten, kein Crawlee-Bug – aber ein echter Stolperstein beim ersten Start, den man erwähnen sollte.

Noch ein praktischer Hinweis: Standardmäßig schreibt Crawlee in ein lokales storage/-Verzeichnis. Mein Test-Harness leitete das in ein temporäres Scratch-Verzeichnis um und deaktivierte Persistenz, um alles sauber zu halten. Bei einem normalen Lauf landet jedoch ein storage/-Ordner im Projekt. Kein Drama – aber gut zu wissen, bevor er plötzlich im git status auftaucht.
Kurz zu einer dritten Engine
Crawlees Paritätsversprechen endet nicht bei Cheerio und Playwright. Es gibt auch PuppeteerCrawler, und ich habe geprüft, wie weit die Aussage „gleiche Schnittstelle“ auch dort trägt – auf Klassen- und API-Ebene, nicht mit einem Live-Crawl.
Alle drei Crawler-Klassen gehen auf dieselbe BasicCrawler-Basisklasse zurück. CheerioCrawler läuft über einen HttpCrawler; PlaywrightCrawler und PuppeteerCrawler laufen beide über einen gemeinsamen BrowserCrawler. Beim Blick in das installierte Paket teilen sich alle drei Engines 24 öffentliche Methoden, darunter die zentralen Queue- und Storage-Operationen, auf denen das gesamte Design basiert – run, addRequests, pushData, getData, getDataset, exportData, getRequestQueue, useState, stop. PuppeteerCrawler und PlaywrightCrawler haben sogar exakt denselben öffentlichen Methodenbestand. Die Unterschiede zwischen den Engines liegen nur dort, wo man sie erwarten würde: an der Grenze zwischen HTTP und Browser.
Wichtig ist die Grenze in aller Deutlichkeit: Ich habe keinen Live-PuppeteerCrawler-Crawl ausgeführt. Die optionale Peer-Dependency puppeteer war in meinem Test-Setup nicht installiert, und dafür hätte es auch noch einen weiteren Browser-Download gebraucht. Die Parität zu Puppeteer ist hier also strukturell verifiziert – gleiche Basisklasse, gleiche Shared Methods, gleiche Handler-Kontext-Form – aber nicht durch einen ausgeführten Lauf. Und selbst wenn die Schnittstelle gleich ist, ist das Verhalten darunter nicht identisch: Crawlees eigene Hinweise sagen, dass Playwright auf Elemente automatisch wartet, während Puppeteer explizit zum Warten aufgefordert werden muss. Das ist eine Eigenschaft der Engine, kein Fehler von Crawlee – es bedeutet aber, dass „gleiche API“ nicht „derselbe Code in jedem Handler“ heißt.
Was ich nicht getestet habe
Hier ist bewusst offen geblieben, was in diesem Durchlauf nicht behandelt wurde – damit meine Ergebnisse nicht größer gelesen werden, als sie sind.
- Skalierung. Alles lief auf kleinen Fixtures und kurzen öffentlichen Crawls. Kein 100- bis 1.000-Seiten-Dauerlauf, also kann ich über Auto-Scaling oder Stabilität unter echter Last nichts Belastbares sagen.
- Queue-Persistenz und Wiederaufnahme. Ich habe keinen Crawl mitten im Lauf abgebrochen, um zu prüfen, ob
RequestQueuenach einem Crash sauber weitermacht. Das ist eine wichtige Fähigkeit für lange Jobs und hier ungetestet. - Export von Dataset und KeyValueStore. Meine JSON-/CSV-Exports habe ich im Test-Harness selbst geschrieben. Die eingebauten
Dataset-/KeyValueStore-Export-Workflows von Crawlee – also eigentlich ein zentrales Komfortargument für das Framework – habe ich nicht ausprobiert. - Proxy- und Session-Pools. Crawlee bringt Proxy-Rotation und Fingerprinting mit. Ich betrachte das strikt als Thema für Compliance und Betrieb, nicht als „Anti-Bot-Bypass“-Werbeversprechen, und habe diese Funktionen ebenfalls nicht unter Belastung getestet.
Und noch einmal: Alle Laufzeiten hier stammen von einem einzigen Rechner und nur einem Durchlauf. Sie zeigen die Form des Kostenunterschieds zwischen HTTP und Browser. Sie sind keine Benchmarks, und ich würde sie auch nicht so zitieren.
Vor- und Nachteile
Vorteile
- Eine einheitliche API für HTTP- und Browser-Crawling – der Wechsel der Engine ist tatsächlich ein Klassenwechsel, bestätigt durch 0 → volle Daten sowohl auf einem lokalen Fixture als auch auf einer öffentlichen Seite.
- Ein echtes Crawl-Framework:
RequestQueue,enqueueLinksmit Tiefensteuerung, Retries undfailedRequestHandler– nicht nur ein Seitenrenderer. - Präzise HTTP-Extraktion (12/12 statisch, 3/3 Artikelabsätze, 8/8 über JSON-API), wenn JavaScript keine Rolle spielt.
- Der Browser-Weg holt Inhalte zurück, die der HTTP-Weg physisch nicht sehen kann, und erstellt Screenshots.
- Apache-2.0, TypeScript, aktiv gepflegt.
Nachteile
- Die Browser-Crawler brauchen einen separaten Schritt
npx playwright install chromium(~81,7 MiB), dennpm install crawleenicht übernimmt – leicht zu übersehen. - Browser-Rendering verursacht echten Zeitaufwand pro Seite (~5 s gegenüber unter 1 s in meinem Einzelseiten-Test).
- Standardmäßiges
storage/-Verzeichnis bei normalen Läufen. - Skalierung, Crash-Resume und der Komfort der eingebauten Exporte sind in meinem Test nicht belegt.
- Proxy- und Fingerprinting-Funktionen müssen innerhalb der Nutzungsbedingungen einer Website und der geltenden Gesetze eingesetzt werden – Verantwortung, kein Freifahrtschein.
Wann Crawlee sinnvoll ist – und wann eine Managed API besser passt
Crawlee ist ein Werkzeug zum Selberbauen, und für viele Teams ist genau das die richtige Wahl. Greife dazu, wenn du den Crawler in deiner eigenen Node-Codebasis kontrollieren willst, HTTP- und Browser-Crawling in einem Projekt mischen möchtest, ohne das Framework zu wechseln, und Queue sowie Storage selbst im Griff haben willst. Wer bereit ist, einen Browser-Fleet zu betreiben und irgendwann zu skalieren, bekommt mit Crawlee ein sauberes, gut konstruiertes Fundament dafür.
Der andere Weg: die gesamte Infrastruktur gar nicht erst selbst betreiben. Wenn du keine Lust hast, Chromium-Instanzen, Proxy-Rotation und Anti-Bot-Themen zu betreuen, ist eine Managed API die Alternative – und genau dort liegt auch unser eigener Developer-Stack bei Thunderbit. Für technische Nutzer ist Thunderbit nicht die Chrome-Erweiterung, sondern eine KI-Scraping-API, ein MCP-Server und eine CLI. Mit POST /distill verwandelst du eine Seite in sauberes, LLM-taugliches Markdown. Mit POST /extract und einem JSON Schema bekommst du strukturierte Daten zurück. Über renderMode mit den Werten none, basic oder full entscheidest du selbst, wann sich ein vollständiges Browser-Rendering lohnt. Der MCP-Server ermöglicht es einem KI-Agenten (Claude, Cursor und anderen MCP-Clients), mitten in einer Aufgabe zu scrapen, und die CLI läuft im Terminal oder in CI:
Thunderbit für Web-Datenextraktion testen
npx -y @thunderbit/thunderbit-cli distill "<url>" -f markdown > out.md
Der entscheidende Unterschied für Entwickler: Crawlee liefert dir das Rohmaterial – gerendertes HTML, geparste Nodes – und du besitzt die Pipeline; eine Managed API liefert strukturiertes JSON, das zum Schema passt, und übernimmt Rendering, CAPTCHAs und Anti-Bot-Themen serverseitig. Unterschiedliche Aufgaben. Wenn du maximale Kontrolle willst und der Betriebsaufwand für dich okay ist: Crawlee. Wenn du die Daten willst, ohne einen Browser-Fleet zu betreiben: der Managed-API-Weg. Viele Teams nutzen am Ende beides – das eine für maßgeschneiderte Crawls, das andere für Fälle nach dem Motto „Gib mir einfach die strukturierten Daten“. Die Kosten dabei kannst du dir auf Thunderbits Preisen ansehen.
Fazit
Sollte man Crawlee verwenden? Ja – wenn du als Node- oder TypeScript-Entwickler ein einziges Framework suchst, das HTTP- und Browser-Crawling unter einer echten Crawl-Queue vereint. Genau dieses Zwei-Engine-Versprechen ist der Grund, Crawlee zu wählen, und in meinen Tests hat es sauber funktioniert: Dieselbe URL wechselte per Klassen-Tausch von 0 zu vollständigen Daten, die statische Extraktion war schnell und präzise, und das Queue- und Tiefen-Crawling lief wie dokumentiert.
Zwei Dinge sollte man dabei im Blick behalten: Plane den versteckten Browser-Download beim ersten Einsatz von PlaywrightCrawler ein, und nimm nicht automatisch an, dass die Teile, die ich nicht getestet habe – Skalierung, Wiederaufnahme nach Absturz, eingebauter Export – genauso gut funktionieren wie die von mir geprüften. Als Grundlage für den eigenen Crawler ist Crawlee ein starkes, gut durchdachtes Stück Technik. Als fertige, komplett wartungsarme Datenpipeline ist es eher ein Startpunkt als das Ziel.
Thunderbit für Web-Datenextraktion testen Get Started Free
FAQs
Ist Crawlee kostenlos und unter welcher Lizenz steht es?
Ja. Crawlee ist Open Source unter der Apache-2.0-Lizenz und wird über npm installiert (npm install crawlee). Die von mir getestete Version war 3.17.0. Für die Browser-Crawler ist zusätzlich ein separater Chromium-Download über Playwright nötig – ebenfalls kostenlos, aber mit rund 81,7 MiB zusätzlichem Setup-Volumen.
CheerioCrawler vs. PlaywrightCrawler – welchen sollte ich verwenden?
Nutze CheerioCrawler, wenn die Daten im Roh-HTML oder in einer zugrunde liegenden JSON-API stecken – er ist deutlich schneller und startet nie einen Browser. Nutze PlaywrightCrawler, wenn der Inhalt per JavaScript gerendert wird, was sich oft daran erkennen lässt, dass der HTTP-Weg leere Ergebnisse liefert. In meinen Tests lieferte die HTTP-Engine auf einer JS-gerenderten Seite 0 Elemente, während die Browser-Engine alles zurückgab. Weil beide dieselbe API teilen, ist der Wechsel nur ein Klassen-Tausch, kein Rewrite.
Braucht Crawlee einen Browser zum Laufen?
Nur für die Browser-Crawler. CheerioCrawler braucht überhaupt keinen Browser. PlaywrightCrawler (und PuppeteerCrawler) benötigen ein Browser-Binary – installiere es mit npx playwright install chromium. Wichtig: npm install crawlee allein lädt keinen Browser herunter, und genau das ist der häufigste Stolperstein beim ersten Start.
Kann Crawlee Pagination und mehrseitige Crawls verarbeiten?
Ja, und genau das ist einer der Hauptgründe, warum man es einer einzelnen Browser-Library vorzieht. enqueueLinks folgt Links – auch Pagination-Selektoren wie .next-page – die RequestQueue dedupliziert und verwaltet den Crawl, und du bekommst Tiefensteuerung plus Limits über maxRequestsPerCrawl. In meinem Test lief ein Crawl über denselben Host über 11 Seiten auf den Tiefen 0–2, und fehlgeschlagene Requests wurden über einen failedRequestHandler sichtbar.
Wie unterscheidet sich Crawlee von einer gehosteten Scraping-API?
Crawlee wird selbst betrieben: Du schreibst und startest den Crawler und bist selbst für Skalierung, Proxies und Anti-Bot-Verhalten verantwortlich. Eine Managed API wie Thunderbits distill-/extract-Endpunkte liefert sauberes Markdown oder schema-konformes JSON zurück und übernimmt Rendering sowie Anti-Bot-Handling serverseitig – erreichbar über API, MCP-Server und CLI. Wähle Crawlee, wenn du maximale Kontrolle über deine eigene Pipeline willst; wähle eine Managed API, wenn du die Browser-Infrastruktur nicht selbst betreiben und skalieren möchtest.


