La maggior parte delle persone incontra Crawlee mentre cerca di rispondere a un’altra domanda: “quale browser headless dovrei usare?”. È la domanda sbagliata, ed è proprio Crawlee a dimostrarlo. Non è un browser. È il framework Node/TypeScript che ne usa uno quando serve e lo evita quando non serve.
Ho passato un paio di giorni a testare Crawlee 3.17.0 su un set controllato di fixture e su alcuni siti demo pubblici, con Node v22.22.3 e macOS. La promessa principale — una sola libreria, una sola API, sotto il cofano un crawler HTTP oppure un browser reale — è ciò che volevo mettere davvero alla prova, perché è la questione che decide se Crawlee merita un posto nel tuo stack oppure se conviene andare direttamente con Playwright. In breve: la storia dei due motori regge, con qualche precisazione che vedremo tra poco.
Cos’è davvero Crawlee, e cosa non è
Crawlee si presenta come una libreria per web scraping e automazione del browser per Node.js, pensata per creare crawler affidabili. Il posizionamento ufficiale è ampio: estrazione dati per AI, LLM, RAG o GPT; download di HTML, PDF, JPG, PNG e altri file; supporto per Puppeteer, Playwright, Cheerio, JSDOM e HTTP grezzo; modalità con o senza interfaccia; rotazione dei proxy inclusa. È un perimetro molto vasto, quindi vale la pena chiarire cosa Crawlee non è.
Non è un motore di rendering. Non ha un browser proprio. Quando serve eseguire JavaScript, Crawlee controlla Playwright o Puppeteer, che a loro volta pilotano Chromium (o un altro browser). Non è nemmeno un servizio hosted da chiamare via rete: è una dipendenza che installi ed esegui in locale o nel tuo ambiente. Più precisamente, Crawlee è il livello sopra il fetcher: le classi crawler, la coda delle richieste, lo storage, la logica di inseguimento dei link. Pensalo come il framework di crawling, con un motore collegabile sotto.
Per la cronaca, la versione che ho testato era la 3.17.0 (rilasciata il 2026-06-04), è scritta in TypeScript, la licenza è Apache-2.0 e il repository era intorno ai 24,6k star al 2026-07-09 su apify/crawlee. Il numero delle star cambia nel tempo — il repo ne ha guadagnate 53 nei due giorni in cui l’ho monitorato — quindi consideralo solo come uno snapshot, non come un dato fisso.
I due motori: CheerioCrawler vs PlaywrightCrawler
Qui è dove il progetto mostra davvero il suo valore, ed è anche il punto su cui ho concentrato più tempo.
CheerioCrawler è il percorso HTTP. Scarica l’HTML grezzo via rete e lo analizza con Cheerio — niente browser, niente esecuzione di JavaScript, niente rendering. È veloce ed economico. PlaywrightCrawler è invece la strada del browser: avvia un vero Chromium, rende la pagina inclusi gli script che costruiscono il DOM e può persino fare screenshot.
Due motori diversi, con capacità davvero differenti. Il punto di Crawlee è che però si presentano allo stesso modo. Entrambi accettano un requestHandler. Entrambi espongono run(). Entrambi possono esplorare i link con enqueueLinks. Passare da un motore all’altro significa cambiare classe, non riscrivere il progetto — l’ho verificato mantenendo la logica di estrazione identica al byte e cambiando solo la classe crawler che la incapsulava.

Su un punto bisogna essere precisi, perché è lì che finisce la parità: cambia l’oggetto con cui leggi il contenuto. Dentro un handler di CheerioCrawler ricevi $ — un DOM statico, già parsato, da interrogare come faresti con jQuery. Dentro un handler browser ricevi un oggetto page vivo. Quindi coda, routing e il meccanismo “salva questi dati, segui quei link” restano identici, ma il punto in cui leggi davvero la pagina cambia forma. Anche la documentazione di Crawlee lo dice chiaramente: l’interfaccia condivisa riguarda le operazioni di crawling, mentre l’accesso al contenuto è la parte che varia.
| Motore | Come recupera i dati | Esegue JavaScript? | Mio test (1 pagina dinamica) | Ideale per |
|---|---|---|---|---|
CheerioCrawler | HTTP grezzo + parsing con Cheerio | No | ~0,035 s | HTML statico, API JSON, velocità |
PlaywrightCrawler | Chromium reale tramite Playwright | Sì | ~4,967 s | Pagine renderizzate in JS, screenshot |
Questi tempi arrivano da una singola macchina e da una sola esecuzione: non sono un benchmark, solo la fotografia del compromesso. Sullo stesso URL, il percorso browser è costato circa due ordini di grandezza in più in termini di tempo. È il prezzo del rendering, ed è il motivo per cui non lo scegli come opzione predefinita.
Il test: stesso URL, da 0 a 8/8
Le promesse costano poco. Il motivo per cui mi fido della storia dei due motori è che sono riuscito a farla fallire e poi a correggerla semplicemente cambiando classe.
Ho creato una fixture dinamica locale — una pagina catalogo in cui le schede prodotto vengono inserite via JavaScript dopo il caricamento, il tipo di pagina che oggi è diventato lo standard sul web moderno. Ho puntato CheerioCrawler su quella pagina. Ha restituito 0 schede prodotto. Non è un bug; è semplicemente il risultato del fatto che Cheerio non ha eseguito il JavaScript, quindi quelle schede non sono mai entrate nell’HTML analizzato. Poi ho puntato PlaywrightCrawler esattamente sullo stesso URL, senza cambiare altro, e ha renderizzato 8 su 8 prodotti, catturando anche uno screenshot come prova.

Per assicurarmi che non fosse una stranezza della mia fixture, ho ripetuto lo stesso schema su un sito pubblico — la demo JavaScript Quotes to Scrape, che costruisce le citazioni lato client. Stesso risultato, stessa direzione: CheerioCrawler ha visto 0 citazioni, PlaywrightCrawler ne ha recuperate 10.

Voglio essere preciso su ciò che questo dimostra. È una riproduzione pulita di qualcosa che Crawlee già documenta: dalla versione 3.0, il framework usa la stessa classe base e la stessa interfaccia di fondo per i vari tipi di crawler. Quindi qui non c’è una scoperta, ma una verifica. Ed è esattamente questo il valore: la promessa di marketing “una sola interfaccia, HTTP o browser” è reale, e qui hai la ricevuta del passaggio da 0 a dati completi sia su una fixture che controllo io, sia su un sito che non controllo.
Dove vince il percorso HTTP
Sarebbe facile leggere la sezione sopra come “usa sempre il browser”. Non farlo. Proprio il design a due motori conta perché il browser è il piano B costoso, non la scelta di default.
Sui contenuti statici, CheerioCrawler è stato preciso e rapido. La mia fixture catalogo statica ha restituito 12 su 12 prodotti con pieno recupero, seguendo la paginazione tramite enqueueLinks({ selector: '.next-page' }), in circa 0,155 secondi. Una pagina articolo ha restituito titolo e tutti i suoi 3 su 3 paragrafi del corpo, separando bene il boilerplate di login/iscrizione/copyright dal contenuto.
Il caso più importante da ricordare: una pagina il cui contenuto viene caricato via JavaScript spesso ha dietro di sé una JSON API. I dati della mia fixture dinamica vivevano su un endpoint e, puntando CheerioCrawler direttamente su quell’API, ho recuperato 8 su 8 prodotti — senza browser, in circa 0,035 secondi. Gli stessi dati che il percorso browser ha impiegato quasi cinque secondi a renderizzare. La lezione è vecchia, ma continua a essere vera: se puoi replicare la richiesta sottostante, fallo invece di avviare Chromium. Crawlee ti consente di prendere questa decisione per ogni crawler, senza cambiare framework.
La parte framework di crawling: il vero motivo per scegliere Crawlee rispetto a una semplice libreria browser
Se ti servisse solo renderizzare una pagina, non avresti bisogno di Crawlee — useresti Playwright o Puppeteer da soli. Ciò che una libreria browser pura non ti dà è il crawling: una coda, deduplicazione, controllo della profondità, retry. Ed è questa la parte di Crawlee che non riguarda affatto i motori.
Ho eseguito un crawl sullo stesso hostname partendo dalla root di una fixture, usando enqueueLinks con tracciamento della profondità. Crawlee ha visitato 11 pagine distribuite su profondità {0:1, 1:3, 2:7} — una root, tre pagine a un hop di distanza, sette pagine a due hop — e ha rispettato maxRequestsPerCrawl come condizione di arresto. La RequestQueue ha gestito il bookkeeping. Quando ho inviato una richiesta a una pagina che restituiva HTTP 500, Crawlee ha ritentato e poi ha esposto il fallimento attraverso failedRequestHandler, invece di nasconderlo in silenzio o mandare in crash l’esecuzione.

Questo è l’argomento più forte a favore di Crawlee rispetto a uno strumento browser standalone: l’orchestrazione del crawl è integrata e, cosa fondamentale, resta la stessa sia che sotto ci sia HTTP sia che ci sia un browser. Scrivi una volta sola la logica di coda e follow-up. Decidi separatamente se ogni crawler debba rendere o meno JavaScript.
Installazione e il browser nascosto da scaricare
L’installazione è andata per lo più senza problemi, con una trappola che colpisce chi lo prova per la prima volta.
npm install crawlee playwright è andato liscio — nessuna vulnerabilità segnalata. Ma PlaywrightCrawler non si avvia finché non esegui anche npx playwright install chromium, che scarica un binario Chromium di circa 81,7 MiB. Installare solo il pacchetto crawlee non scarica alcun browser. Se salti questo passaggio e lanci subito un crawler browser, incontrerai un errore di avvio che non è affatto ovvio se non conosci già il modello di packaging di Playwright. È un comportamento ereditato da Playwright, non un difetto di Crawlee, ma resta un punto di frizione reale per il primo avvio.

Un’altra nota operativa: per impostazione predefinita Crawlee scrive nella directory locale storage/. Nel mio harness di test ho reindirizzato tutto a una cartella temporanea e disabilitato la persistenza per mantenere l’ambiente pulito, ma un’esecuzione standard creerà una cartella storage/ nel progetto. Non è un problema, semplicemente è bene saperlo prima che compaia in git status.
Un terzo motore, in breve
La storia della parità di Crawlee non si ferma a Cheerio e Playwright. Esiste anche PuppeteerCrawler, e ho verificato fino a dove arriva la promessa di “stessa interfaccia” anche per lui — a livello di classe e superficie API, non con un crawl reale.
Tutte e tre le classi crawler risalgono alla stessa base BasicCrawler. CheerioCrawler passa attraverso HttpCrawler; PlaywrightCrawler e PuppeteerCrawler passano entrambi attraverso un BrowserCrawler condiviso. Ispezionando il pacchetto installato, ho trovato 24 metodi pubblici condivisi da tutti e tre i motori, comprese le operazioni di coda e storage su cui si regge l’intero design — run, addRequests, pushData, getData, getDataset, exportData, getRequestQueue, useState, stop. PuppeteerCrawler e PlaywrightCrawler espongono addirittura lo stesso insieme di metodi pubblici. Le differenze tra motori emergono solo lungo la linea di separazione HTTP/browser, esattamente dove ci si aspetta che siano.
Il confine da dichiarare chiaramente è questo: non ho eseguito un crawl reale con PuppeteerCrawler. La dipendenza peer puppeteer è opzionale e non era installata nel mio pacchetto di test, e provare quel motore avrebbe significato scaricare un altro browser. Quindi qui la parità con Puppeteer è verificata in modo strutturale — stessa classe base, stessi metodi condivisi, stessa forma del contesto handler — non tramite un’esecuzione reale. E anche quando l’interfaccia coincide, il comportamento sottostante non è perfettamente identico: la documentazione ufficiale di Crawlee osserva che Playwright attende automaticamente gli elementi, mentre Puppeteer richiede attese esplicite. È una caratteristica del motore, non un difetto di Crawlee, ma significa che “stessa API” non vuol dire “stesso codice dentro ogni handler”.
Cosa non ho testato
Ecco cosa ho lasciato volutamente fuori da questo giro, così non interpreti i risultati in modo più ampio di quanto siano.
- Scala. Tutto è stato eseguito su fixture piccole e crawl pubblici brevi. Nessuna esecuzione da 100–1.000 pagine, quindi non posso dire molto su autoscaling o stabilità sotto carico reale.
- Persistenza e ripresa della coda. Non ho mai interrotto un crawl a metà per vedere se
RequestQueueriprende correttamente dopo un crash. È una funzione importante per job lunghi, ma qui non è stata testata. - Export di Dataset e KeyValueStore. Ho scritto a mano gli export JSON/CSV nel mio harness. L’ergonomia degli export integrati di
Dataset/KeyValueStore— probabilmente uno dei veri vantaggi pratici del framework — non l’ho provata. - Proxy e pool di sessioni. Crawlee include rotazione dei proxy e fingerprinting. Io li considero rigorosamente un tema di conformità e operations, non un argomento di vendita per “bypassare bot protection”, e non li ho stressati in nessuna direzione.
E i tempi riportati lungo tutto l’articolo sono sempre quelli di una singola macchina e di una singola esecuzione. Mostrano la forma del costo HTTP-vs-browser. Non sono benchmark, e non li citerei come tali.
Pro e contro
Pro
- Un’unica superficie API per crawling HTTP e browser: il passaggio di motore è davvero un cambio classe, verificato dal passaggio da 0 a dati completi sia su una fixture locale sia su un sito pubblico.
- Un vero framework di crawling:
RequestQueue,enqueueLinkscon controllo della profondità, retry efailedRequestHandler, non solo un renderer di pagine. - Estrazione HTTP accurata (12/12 statico, 3/3 paragrafi di un articolo, 8/8 tramite API JSON) quando JavaScript non intralcia.
- Il percorso browser recupera contenuti che l’HTTP puro non può vedere e consente di fare screenshot.
- Apache-2.0, TypeScript, manutenzione attiva.
Contro
- I crawler browser richiedono un
npx playwright install chromiumseparato (~81,7 MiB) chenpm install crawleenon gestisce — facile da dimenticare. - Il rendering browser comporta un costo reale per pagina (~5 s contro meno di un secondo nel mio test su una singola pagina).
- Effetto collaterale della directory
storage/nelle esecuzioni standard. - Scala, ripresa della coda dopo crash ed ergonomia dell’export Dataset non sono state dimostrate nei miei test.
- Le funzioni di proxy e fingerprinting vanno usate nel rispetto dei termini del sito e della legge — una responsabilità, non una scorciatoia da sfruttare.
Quando scegliere Crawlee e quando invece una API gestita
Crawlee è uno strumento da costruire in casa, e per molti team è la scelta giusta. Usalo quando vuoi gestire il crawler nel tuo codebase Node, combinare crawling HTTP e browser nello stesso progetto senza cambiare framework e controllare tu stesso coda e storage. Se ti va bene gestire — e col tempo anche scalare — una flotta di browser, Crawlee ti offre una base pulita e ben progettata su cui costruire.
L’altra strada è non gestire affatto questa infrastruttura. Se non vuoi occuparti di istanze Chromium, rotazione dei proxy e gestione anti-bot, allora un’API gestita è l’alternativa — ed è qui che si inserisce il nostro stack developer su Thunderbit. Per utenti tecnici, Thunderbit non è l’estensione Chrome: è una API di scraping AI, un server MCP e una CLI. Chiami POST /distill per trasformare una pagina in Markdown pulito, pronto per LLM, oppure POST /extract con uno schema JSON per ottenere dati strutturati, scegliendo renderMode tra none, basic o full così decidi tu quando vale la pena usare il rendering completo del browser. Il server MCP permette a un agente AI (Claude, Cursor e altri client MCP) di fare scraping mentre svolge un’attività, mentre la CLI gira da terminale o in CI:
Prova Thunderbit per l’estrazione di dati web
npx -y @thunderbit/thunderbit-cli distill "<url>" -f markdown > out.md
La distinzione che conta per gli sviluppatori: Crawlee ti consegna la materia prima — HTML renderizzato, nodi parsati — e tu possiedi la pipeline; un’API gestita ti restituisce JSON strutturato che aderisce allo schema, con rendering JavaScript, CAPTCHA e anti-bot gestiti lato server. Sono lavori diversi. Se vuoi il massimo controllo e non ti spaventa l’operatività, scegli Crawlee. Se vuoi i dati senza dover mantenere una flotta di browser, scegli la strada gestita. Molti team finiscono per usare entrambe: una per i crawl su misura e una per i casi “dammi solo i dati strutturati”. Puoi valutare il trade-off dei costi nella pagina prezzi di Thunderbit.
Verdetto
Vale la pena usare Crawlee? Sì — se sei uno sviluppatore Node o TypeScript che vuole un unico framework capace di coprire crawling HTTP e browser con una vera coda di crawling sotto il cofano. La promessa dei due motori è la ragione per sceglierlo, e nei miei test ha retto bene: lo stesso URL è passato da 0 a dati completi con il cambio di una sola classe, l’estrazione statica è stata accurata e veloce, e il crawling con coda e profondità ha funzionato come documentato.
Tieni però presenti due cose. Metti in conto il download nascosto del browser la prima volta che usi PlaywrightCrawler, e non dare per scontato che le parti che non ho testato — scala, ripresa dopo crash, export integrati — si comportino bene quanto quelle che ho verificato finché non le provi sul tuo carico reale. Come base per costruire il tuo crawler, Crawlee è un pezzo di ingegneria forte e ben progettato. Come pipeline dati finita e completamente hands-off, è un punto di partenza, non la destinazione.
Prova Thunderbit per l’estrazione di dati web Get Started Free
FAQ
Crawlee è gratis e con quale licenza viene distribuito?
Sì. Crawlee è open source sotto licenza Apache-2.0 e si installa da npm (npm install crawlee). La versione che ho testato era la 3.17.0. Per eseguire i crawler browser serve un download separato di Chromium tramite Playwright, che è anch’esso gratuito ma aggiunge circa 81,7 MiB alla configurazione.
CheerioCrawler vs PlaywrightCrawler: quale dovrei usare?
Usa CheerioCrawler quando i dati sono già nell’HTML grezzo o in una JSON API sottostante — è molto più veloce e non avvia mai un browser. Usa PlaywrightCrawler quando il contenuto viene renderizzato via JavaScript, cosa che riconosci quando il percorso HTTP restituisce risultati vuoti. Nei miei test il motore HTTP ha restituito 0 elementi su una pagina renderizzata in JS, mentre il motore browser ha recuperato tutto. Poiché condividono la stessa API, il passaggio è un cambio classe, non una riscrittura.
Crawlee ha bisogno di un browser per funzionare?
Solo per i crawler browser. CheerioCrawler non ha bisogno di alcun browser. PlaywrightCrawler (e PuppeteerCrawler) richiedono un binario browser — si installa con npx playwright install chromium. Nota che npm install crawlee da solo non scarica alcun browser: è il classico problema che si incontra al primo avvio.
Crawlee può gestire paginazione e crawl su più pagine?
Sì, ed è uno dei motivi principali per preferirlo a una libreria browser standalone. enqueueLinks segue i link, inclusi selettori di paginazione come .next-page, RequestQueue deduplica e organizza il crawl, e hai controllo della profondità oltre ai limiti di maxRequestsPerCrawl. Nei test, un crawl sullo stesso hostname ha attraversato 11 pagine su profondità 0–2, e le richieste fallite sono emerse tramite failedRequestHandler.
Come si confronta Crawlee con una scraping API gestita?
Crawlee è self-hosted: scrivi ed esegui tu il crawler, e ti occupi tu di scala, proxy e anti-bot. Un’API gestita come gli endpoint distill/extract di Thunderbit restituisce Markdown pulito o JSON strutturato conforme allo schema, con rendering e anti-bot gestiti lato server, il tutto esposto tramite API, server MCP e CLI. Scegli Crawlee se vuoi il massimo controllo sulla tua pipeline; scegli un’API gestita se preferisci non dover mantenere e scalare personalmente l’infrastruttura browser.


