De meeste mensen komen Crawlee tegen terwijl ze eigenlijk een andere vraag proberen te beantwoorden: "welke headless browser moet ik gebruiken?" Dat is de verkeerde vraag, en Crawlee is precies de reden waarom. Het is geen browser. Het is een Node/TypeScript-framework dat er eentje inzet wanneer je die nodig hebt, en overslaat wanneer dat niet hoeft.
Ik heb een paar dagen Crawlee 3.17.0 getest op een gecontroleerde set fixtures en een paar publieke demowebsites, met Node v22.22.3 en macOS. De centrale belofte — één library, één API, daaronder óf een HTTP-crawler óf een echte browser — wilde ik vooral stevig toetsen. Want dat is de claim die bepaalt of Crawlee de moeite waard is voor je stack, of dat je beter gewoon direct naar Playwright grijpt. Kort gezegd: het verhaal met twee engines houdt stand, met een paar kanttekeningen die ik zo toelicht.
Wat Crawlee wel is, en wat niet
Crawlee beschrijft zichzelf als een library voor webscraping en browserautomatisering in Node.js, gebouwd om betrouwbare crawlers te maken. De officiële positionering is breed: data ophalen voor AI, LLM’s, RAG of GPT’s; HTML, PDF, JPG, PNG en andere bestanden downloaden; werken met Puppeteer, Playwright, Cheerio, JSDOM en ruwe HTTP; headful of headless; inclusief proxy-rotatie. Dat is nogal wat, dus het helpt om ook te zeggen wat Crawlee niet is.
Het is geen rendering engine. Het heeft geen eigen browser. Als je JavaScript wilt laten uitvoeren, stuurt Crawlee Playwright of Puppeteer aan, en die sturen vervolgens Chromium aan (of een andere browser). Het is ook geen gehoste dienst die je via het netwerk aanspreekt — het is een dependency die je zelf installeert en draait. Wat Crawlee wel is, is de laag boven de fetcher: de crawlerklassen, de request queue, de storage, en de logica om links te volgen. Zie het als het crawl-framework, met daaronder een verwisselbare engine.
Ter volledigheid: de versie die ik testte was 3.17.0 (uitgebracht op 2026-06-04), het is TypeScript, de licentie is Apache-2.0, en de repo stond op ongeveer 24,6k sterren per 2026-07-09 op apify/crawlee. Sterrentellingen veranderen — de repo kreeg er in de twee dagen dat ik keek 53 bij — dus zie dat getal als een momentopname, niet als een vast feit.
De twee engines: CheerioCrawler vs PlaywrightCrawler
Hier betaalt het ontwerp zich echt uit, en hier heb ik het meeste tijd aan besteed.
CheerioCrawler is de HTTP-route. Het haalt ruwe HTML op via het netwerk en parseert die met Cheerio — geen browser, geen JavaScript-executie, geen rendering. Daardoor is het snel en goedkoop. PlaywrightCrawler is de browserroute. Die start echte Chromium, rendert de pagina inclusief alle JavaScript die de DOM opbouwt, en kan zelfs screenshots maken.
Twee verschillende engines met echt verschillende mogelijkheden. Het punt dat Crawlee hier maakt, is dat ze dezelfde jas dragen. Beide nemen een requestHandler. Beide hebben run(). Beide crawlen links met enqueueLinks. Van de ene engine naar de andere overstappen is een klassewissel, geen herschrijving — dat heb ik geverifieerd door mijn extractielogica byte-for-byte gelijk te houden en alleen te veranderen welke crawlerklasse eromheen zat.

Eén nuance is belangrijk, omdat daar de gelijkheid ophoudt: de content-handle verschilt. In een CheerioCrawler-handler krijg je $ — een statische, al geparste DOM die je opvraagt zoals in jQuery. In een browser-handler krijg je een live page-object. Dus de queue, routing en het "stuur dit door, volg die links"-gedeelte blijft identiek, maar de plek waar je de pagina daadwerkelijk uitleest ziet er anders uit. Crawlee’s eigen documentatie zegt ongeveer hetzelfde: de gedeelde interface geldt voor de crawl-operaties, terwijl de contenttoegang juist het deel is dat verschilt.
| Engine | Hoe het ophaalt | JavaScript uitvoeren? | Mijn test (1 dynamische pagina) | Beste voor |
|---|---|---|---|---|
CheerioCrawler | Ruwe HTTP + Cheerio-parse | Nee | ~0,035s | Statische HTML, JSON API’s, snelheid |
PlaywrightCrawler | Echte Chromium via Playwright | Ja | ~4,967s | JS-gerenderde pagina’s, screenshots |
Die timings komen van één machine en één run — geen benchmark, maar wel een goede indicatie van de trade-off. De browserroute kostte op dezelfde URL ongeveer twee ordes van grootte meer tijd. Dat is de prijs van rendering, en precies waarom je er niet standaard voor kiest.
De test: dezelfde URL, 0 versus 8/8
Claims zijn goedkoop. De reden dat ik het tweo-engine-verhaal vertrouw, is dat ik het kapot kon laten gaan en het daarna kon repareren door één klasse te wisselen.
Ik bouwde een lokale dynamische fixture — een cataloguspagina waarbij productkaarten door JavaScript worden ingevoegd na het laden, precies het soort pagina dat inmiddels de norm is op het moderne web. Ik liet CheerioCrawler erop los. Die gaf 0 productkaarten terug. Dat is geen bug; dat is natuurkunde. Cheerio voerde de JavaScript immers nooit uit, dus de kaarten bestonden niet in de HTML die het parseerde. Daarna zette ik PlaywrightCrawler op exact dezelfde URL, veranderde verder niets, en die rendert 8 van de 8 producten en maakte een screenshot als bewijs.

Om zeker te weten dat dit geen eigenaardigheid van mijn eigen fixture was, testte ik hetzelfde patroon op een publieke site — de JavaScript-demopagina Quotes to Scrape, die zijn quotes client-side opbouwt. Zelfde resultaat in dezelfde richting: CheerioCrawler zag 0 quotes, PlaywrightCrawler haalde er 10 op.

Ik wil wel precies zijn over wat dit bewijst. Het is een nette reproductie van iets dat Crawlee al documenteert — het framework deelt sinds versie 3.0 dezelfde basisclass en interface tussen zijn crawler-types. Dus dit is verificatie, geen ontdekking. Maar juist dat is de waarde: de marketingzin "één interface, HTTP of browser" klopt, en hier is het bewijs van 0 naar volledige data, zowel op een fixture die ik zelf beheer als op een site die ik niet beheer.
Waar de HTTP-route wint
Het zou makkelijk zijn om het bovenstaande te lezen als: "gebruik altijd de browser." Niet doen. Juist omdat de browser de dure fallback is, en niet de standaard, is het tweo-engine-ontwerp zo waardevol.
Op statische content was CheerioCrawler snel en nauwkeurig. Mijn statische catalogusfixture gaf 12 van de 12 producten terug, inclusief paginering via enqueueLinks({ selector: '.next-page' }), in ongeveer 0,155 seconden. Een artikelpagina leverde titel en alle 3 van de 3 alinea’s op, terwijl login-, subscribe- en copyright-tekst netjes los van de inhoud bleef.
Eén les is het waard om goed te onthouden: een pagina waarvan de data via JavaScript wordt geladen, heeft er vaak vlak achter gewoon een JSON API zitten. De data van mijn dynamische fixture zat achter een endpoint, en toen ik CheerioCrawler rechtstreeks op die API zette, haalde die 8 van de 8 producten binnen — zonder browser, in ongeveer 0,035 seconden. Exact dezelfde data waarvoor de browserroute bijna vijf seconden nodig had om te renderen. De les is oud, maar blijft waar: als je de onderliggende request kunt reproduceren, doe dat dan in plaats van Chromium op te starten. Crawlee laat je die keuze per crawler maken, zonder van framework te wisselen.
Het crawl-framework-gedeelte, en waarom je Crawlee zou kiezen boven alleen een browserlib
Als je alleen maar één pagina hoefde te renderen, had je Crawlee niet nodig — dan gebruik je gewoon Playwright of Puppeteer op zichzelf. Wat een losse browserlibrary je niet geeft, is een crawl: een queue, deduplicatie, dieptecontrole en retries. Dát is het deel van Crawlee dat niet om engines draait.
Ik draaide een crawl binnen hetzelfde hostdomein vanaf de root van een fixture, met enqueueLinks en depth-tracking. Crawlee liep 11 pagina’s door op dieptes {0:1, 1:3, 2:7} — één root, drie pagina’s één stap verder, zeven pagina’s twee stappen verder — en hield zich aan maxRequestsPerCrawl als stopvoorwaarde. De RequestQueue deed de administratie. Toen ik een request op een pagina met HTTP 500 afvuurde, probeerde Crawlee het opnieuw en kwam het falen daarna netjes via failedRequestHandler naar buiten, in plaats van het stilletjes te negeren of de run te laten crashen.

Dit is het sterkste argument voor Crawlee boven een standalone browsertool: de crawl-orchestratie zit erin ingebakken, en belangrijker nog, diezelfde orchestratie blijft gelijk of de onderliggende engine nu HTTP of browser is. Je schrijft je queue- en follow-logica één keer. Per crawler beslis je apart of JavaScript-rendering nodig is.
Installatie en de verborgen browserdownload
Installeren ging grotendeels soepel, met één valkuil die first-time users zal raken.
npm install crawlee playwright liep netjes, met 0 kwetsbaarheden. Maar PlaywrightCrawler start niet voordat je ook npx playwright install chromium draait, waarmee ongeveer 81,7 MiB aan Chromium-binary wordt opgehaald. Alleen het crawlee-pakket installeren haalt dus geen browser op. Sla je die stap over en spring je direct naar een browsercrawler, dan krijg je een launch-fout die niet meteen duidelijk is als je het packagingmodel van Playwright niet al kent. Dat is overgenomen Playwright-gedrag, geen fout van Crawlee, maar wel een echte frictie bij de eerste run die het waard is om te noemen.

Nog één operationele noot: standaard schrijft Crawlee naar een lokale storage/-map. Mijn testopzet zette dat om naar een tijdelijke scratchmap en schakelde persistentie uit om alles schoon te houden, maar een standaardrun laat gewoon een storage/-map achter in je project. Geen probleem, maar wel goed om te weten voordat hij ineens in je git status opduikt.
Kort over een derde engine
Crawlee’s parity-verhaal beperkt zich niet tot Cheerio en Playwright. Er is ook PuppeteerCrawler, en ik heb gekeken hoe ver de claim "zelfde interface" daar reikt — op class- en API-niveau, niet met een live crawl.
Alle drie de crawlerklassen gaan terug op dezelfde BasicCrawler-basis. CheerioCrawler loopt via een HttpCrawler; PlaywrightCrawler en PuppeteerCrawler lopen allebei via een gedeelde BrowserCrawler. Als je het geïnstalleerde pakket inspecteert, blijken 24 publieke methoden gedeeld te worden door alle drie de engines, inclusief de queue- en storage-operaties waarop het hele ontwerp rust — run, addRequests, pushData, getData, getDataset, exportData, getRequestQueue, useState, stop. PuppeteerCrawler en PlaywrightCrawler hebben zelfs exact dezelfde publieke methodenset. De enige verschillen tussen de engines zitten op de grens tussen HTTP en browser, precies waar je ze zou verwachten.
De grens die ik wel expliciet wil noemen: ik heb geen live PuppeteerCrawler-crawl gedraaid. De puppeteer peer dependency is optioneel en zat niet in mijn testpakket, en het testen ervan had nog een extra browserdownload betekend. Dus de Puppeteer-pariteit hier is structureel geverifieerd — dezelfde basisklasse, dezelfde gedeelde methoden, dezelfde handler-context — maar niet via een uitgevoerde run. En zelfs waar de interface overeenkomt, is het gedrag eronder niet volledig identiek: Crawlee’s eigen richtlijn vermeldt dat Playwright automatisch op elementen wacht, terwijl Puppeteer je expliciet laat wachten. Dat is een eigenschap van de engine, geen fout van Crawlee, maar het betekent wel dat "dezelfde API" niet hetzelfde is als "exact dezelfde code in elke handler".
Wat ik niet heb getest
Dit deel heeft ik bewust laten liggen, zodat je mijn resultaten niet breder leest dan ze zijn.
- Schaal. Alles draaide op kleine fixtures en korte publieke crawls. Geen langdurige run van 100–1.000 pagina’s, dus ik kan niets zinnigs zeggen over Crawlee’s autoscaling of stabiliteit onder echte belasting.
- Queue-persistentie en hervatten. Ik heb nooit halverwege een crawl de stekker eruit getrokken om te zien of
RequestQueuena een crash netjes verdergaat. Dat is een belangrijke functie voor grote jobs, maar hier niet getest. - Dataset- en KeyValueStore-export. Ik schreef mijn JSON/CSV-exports handmatig in de harness. De ingebouwde
Dataset/KeyValueStore-exportergonomie van Crawlee — eigenlijk een belangrijk deel van de waarde van het framework — heb ik niet gebruikt. - Proxy- en session-pools. Crawlee levert proxy-rotatie en fingerprinting. Ik behandel dat strikt als een compliance- en operationsonderwerp, niet als een "anti-bot bypass"-selling point, en ik heb het ook niet op de proef gesteld.
En de timings hierboven zijn steeds single-machine, single-run. Ze laten de vorm zien van de kosten van HTTP versus browser. Het zijn geen benchmarks, en ik zou ze ook niet zo citeren.
Plus- en minpunten
Pluspunten
- Eén API-oppervlak voor HTTP- en browsercrawling — de enginewissel is echt een klassewissel, geverifieerd met 0 → volledige data op zowel een lokale fixture als een publieke site.
- Een echt crawl-framework:
RequestQueue,enqueueLinksmet depth-control, retries en eenfailedRequestHandler, niet alleen een pagerenderer. - Nauwkeurige HTTP-extractie (12/12 statisch, 3/3 artikelalinea’s, 8/8 via JSON API) zolang JavaScript niet in de weg zit.
- De browserroute haalt content op die de HTTP-route fysiek niet kan zien, en kan screenshots maken.
- Apache-2.0, TypeScript, actief onderhouden.
Minpunten
- De browsercrawlers hebben een aparte
npx playwright install chromiumnodig (~81,7 MiB), iets datnpm install crawleeniet regelt — makkelijk te missen. - Browser-rendering heeft echte kosten per pagina (~5s tegenover sub-seconde in mijn test met één pagina).
- De standaard
storage/-map verschijnt als bijeffect bij een gewone run. - Schaal, queue-persistentie/hervatten en Dataset-exportergonomie zijn in mijn test niet bewezen.
- Proxy- en fingerprinting-functies moet je gebruiken binnen de voorwaarden van een site en de wet — een verantwoordelijkheid, geen feature om blind op te leunen.
Wanneer je Crawlee kiest versus een managed API
Crawlee is een doe-het-zelftool, en voor veel teams is dat precies goed. Kies het wanneer je de crawler in je eigen Node-codebase wilt beheren, HTTP- en browsercrawling in één project wilt combineren zonder van framework te wisselen, en zelf controle wilt houden over queue en storage. Als je het geen probleem vindt om een browservloot te draaien en later op te schalen, geeft Crawlee je een nette, goed ontworpen ruggengraat om daarop te bouwen.
De andere route is: helemaal geen infrastructuur beheren. Als het babysitten van Chromium-instances, proxy-rotatie en anti-bot-afhandeling niet is waar je je engineeringtijd aan wilt besteden, dan is een managed API het alternatief — en precies daar past onze eigen developer-stack bij Thunderbit in. Voor technische gebruikers is Thunderbit niet de Chrome-extensie; het is een AI scraping API, MCP-server en CLI. Je roept POST /distill aan om een pagina om te zetten naar schone, LLM-klare Markdown, of POST /extract met een JSON Schema om gestructureerde data terug te krijgen, met een renderMode van none, basic of full zodat je zelf bepaalt wanneer volledige browser-rendering de moeite waard is. De MCP-server laat een AI-agent (Claude, Cursor en andere MCP-clients) midden in een taak scrapen, en de CLI draait vanuit de terminal of CI:
Probeer Thunderbit voor webdata-extractie
npx -y @thunderbit/thunderbit-cli distill "<url>" -f markdown > out.md
Het onderscheid dat voor ontwikkelaars telt: Crawlee geeft je de ruwe bouwstenen — gerenderde HTML, geparste nodes — en jij beheert de pipeline; een managed API geeft je schema-compatibele, gestructureerde JSON terug, terwijl rendering, CAPTCHAs en anti-bot server-side worden afgehandeld. Andere taken, andere aanpak. Wil je maximale controle en vind je operations prima, kies Crawlee. Wil je data zonder browservloot, kies de managed route. Veel teams gebruiken uiteindelijk beide: één voor maatwerkcrawls en één voor de gevallen waarin je vooral zegt: "geef me gewoon die gestructureerde data." De kostenafweging zie je bij Thunderbit's pricing.
Conclusie
Moet je Crawlee gebruiken? Ja — als je een Node- of TypeScript-ontwikkelaar bent die één framework wil voor zowel HTTP- als browsercrawling, met een echte crawl queue eronder. De belofte met twee engines is precies waarom je het kiest, en die hield in mijn tests netjes stand: dezelfde URL ging van 0 naar volledige data met één klassewissel, statische extractie was snel en accuraat, en queue- en depth-crawling werkten zoals gedocumenteerd.
Ga er wel in met twee dingen in je achterhoofd. Reserveer ruimte voor de verborgen browserdownload de eerste keer dat je PlaywrightCrawler gebruikt, en ga er niet vanuit dat de onderdelen die ik niet heb getest — schaal, crash-resume, ingebouwde exports — net zo goed werken als de onderdelen die ik wél heb getest, totdat je ze op je eigen workload hebt gedraaid. Als basis om je eigen crawler op te bouwen is Crawlee sterk en goed ontworpen. Als kant-en-klare, hands-off datapijplijn is het een beginpunt, geen eindbestemming.
Probeer Thunderbit voor webdata-extractie Get Started Free
Veelgestelde vragen
Is Crawlee gratis, en onder welke licentie valt het?
Ja. Crawlee is open source onder de Apache-2.0-licentie en installeerbaar via npm (npm install crawlee). De versie die ik testte was 3.17.0. Voor de browsercrawlers is wel een aparte Chromium-download via Playwright nodig; die is ook gratis, maar voegt ongeveer 81,7 MiB toe aan je setup.
CheerioCrawler vs PlaywrightCrawler — welke moet ik gebruiken?
Gebruik CheerioCrawler wanneer de data in de ruwe HTML zit of achter een onderliggende JSON API staat — het is veel sneller en start nooit een browser. Gebruik PlaywrightCrawler wanneer de content door JavaScript wordt gerenderd, wat je merkt als de HTTP-route lege resultaten oplevert. In mijn tests gaf de HTTP-engine 0 items terug op een JS-gerenderde pagina en gaf de browser-engine alles terug. Omdat ze dezelfde API delen, is overstappen een klassewissel, geen herschrijving.
Heeft Crawlee een browser nodig om te draaien?
Alleen voor de browsercrawlers. CheerioCrawler heeft helemaal geen browser nodig. PlaywrightCrawler (en PuppeteerCrawler) hebben een browserbinary nodig — installeer die met npx playwright install chromium. Let op: npm install crawlee haalt zelf geen browser binnen; dat is de meest voorkomende valkuil bij de eerste run.
Kan Crawlee paginering en crawls over meerdere pagina’s afhandelen?
Ja, en dat is een hoofdreden om het boven een losse browserlibrary te kiezen. enqueueLinks volgt links, inclusief pagineringsselectors zoals .next-page, de RequestQueue dedupliceert en beheert de crawl, en je krijgt depth-control plus limieten via maxRequestsPerCrawl. In mijn test liep een crawl binnen hetzelfde hostdomein 11 pagina’s door over dieptes 0–2, en mislukte requests kwamen via een failedRequestHandler naar buiten.
Hoe verhoudt Crawlee zich tot een hosted scraping API?
Crawlee is self-hosted: jij schrijft en runt de crawler, en jij beheert schaal, proxies en anti-bot-afhandeling. Een managed API zoals Thunderbit’s distill/extract-endpoints levert schone Markdown of schema-compatibele gestructureerde JSON terug, terwijl rendering en anti-bot server-side worden afgehandeld, via een API, een MCP-server en een CLI. Kies Crawlee als je maximale controle over je eigen pipeline wilt; kies een managed API als je de browserinfrastructuur liever niet zelf wilt draaien en schalen.


