Reseña de Crawlee: en Quotes to Scrape devolvió 0 por HTTP y 10 en Chromium

Última actualización: August 17, 2026
Reseña de Crawlee: en Quotes to Scrape devolvió 0 por HTTP y 10 en Chromium
Resumen con IA
Lo que hace útil a Crawlee es que su orquestación de rastreo admite tanto el análisis por HTTP como la ejecución en navegador. Por eso, una misma URL puede devolver resultados distintos según el crawler y la condición de disponibilidad elegidos. En la página pública de Quotes to Scrape con JavaScript, CheerioCrawler encontró 0 citas objetivo y PlaywrightCrawler encontró 10 después de esperar a .quote. El ciclo de vida del rastreo es parecido, pero esto no fue un simple cambio de clase en una sola línea: el handler de Cheerio usó $, mientras que el de Playwright usó page, una espera explícita y extracción desde el navegador. Crawlee es una opción sólida para equipos de Node o TypeScript que quieren una orquestación de rastreo compartida entre HTTP y ejecución en navegador.

Lo útil de Crawlee es que su orquestación de rastreo funciona tanto con parsing por HTTP como con ejecución en navegador. Eso hace que una misma URL pueda dar resultados distintos según el crawler elegido y la condición de “listo” aplicada.

En la página pública Quotes to Scrape JS, CheerioCrawler encontró 0 citas objetivo y PlaywrightCrawler encontró 10 después de esperar a .quote. El ciclo de vida del rastreo es parecido, pero esto no fue un simple cambio de clase de una sola línea: el handler de Cheerio usó $, mientras que el de Playwright usó page, una espera explícita y extracción del lado del navegador.

Qué es realmente Crawlee

Crawlee (el proyecto apify/crawlee, versión 3.17.0) es una biblioteca de web scraping y automatización de navegador para Node.js y TypeScript. Admite rastreo HTTP basado en Cheerio o JSDOM, y rastreo en navegador basado en Playwright o Puppeteer. El proyecto usa licencia Apache-2.0; conviene revisar sus avisos y obligaciones de atribución antes de distribuirlo.

La idea mental que importa es separar “obtener la página” de “leer la página”. Un camino descarga el HTML bruto y no ejecuta JavaScript. El otro abre Chromium y puede ejecutar los scripts de la página, pero aun así necesita una condición de preparación adecuada y puede quedarse corto ante contenido protegido por interacción, carga diferida, Shadow DOM, fallos de API o bloqueos anti-bot. Crawlee expone conceptos de ciclo de vida equivalentes en ambos caminos, no primitivas DOM intercambiables.

Ese es el punto que vale la pena entender antes de escribir un solo selector, porque la elección entre esos dos motores decide si tu scraper devuelve datos o devuelve nada en un sitio concreto.

Funciones clave: dos motores, una sola API

Crawlee two engines one API

CheerioCrawler obtiene el HTML y lo analiza con Cheerio; PlaywrightCrawler controla Chromium y puede tomar capturas de pantalla. Ambos usan requestHandler, exponen run() y comparten conceptos de rastreo como colas y descubrimiento de enlaces. Eso sí, el contexto del handler cambia: en la ruta Cheerio probada se extrajo con $, mientras que la ruta en navegador usó page, waitForSelector y $$eval. La infraestructura de cola y ciclo de vida puede seguir siendo familiar, pero el código de extracción quizá necesite un adaptador o una reescritura.

Debajo de eso, Crawlee aporta la infraestructura que necesita un rastreo real. Una RequestQueue gestiona el frente de URLs por visitar, elimina duplicados y registra lo ya procesado. enqueueLinks descubre y añade nuevas URLs (con filtrado por selector y por mismo host) para que el rastreo se expanda por sí solo. Un Dataset reúne los registros extraídos para exportarlos. Por defecto, Crawlee guarda todo esto en un directorio local storage/ en disco — cómodo para reanudar, y un poco molesto la primera vez que te encuentras una carpeta storage/ que no pediste en tu proyecto (mi harness redirigió eso a un directorio temporal y desactivó la persistencia para mantener la prueba limpia).

Cada pieza por separado no tiene nada de extraordinario. La clave es que se comparten entre ambos motores, así que la cola, el descubrimiento de enlaces y el dataset se comportan igual tanto si rastreas por HTTP como si lo haces a través de un navegador. Aprendes una API y obtienes dos estrategias de obtención.

Configuración: el navegador se instala aparte

En la instalación probada, después de instalar los paquetes no aparecía un ejecutable de Chromium.

Crawlee setup install weight

npm install crawlee playwright se instaló sin problemas en mi caso — 85 paquetes, 0 vulnerabilidades, sin drama. Si te quedas ahí y ejecutas un CheerioCrawler, todo funciona, porque el rastreo HTTP no necesita navegador.

En este entorno, Chromium tuvo que instalarse por separado con npx playwright install chromium; sin eso, PlaywrightCrawler no pudo arrancar. La carga observada del navegador fue de aproximadamente 82 MiB, pero las notas originales no conservan si esa cifra correspondía al tamaño de descarga o al tamaño en disco. Es una observación de configuración específica de una máquina, no una propiedad fija del producto. Las rutas de documentación y el comportamiento de los paquetes pueden cambiar, así que este artículo no afirma que la omisión sea universal ni que esté permanentemente sin documentar.

Piensa en la configuración probada como dos pasos: instalar los paquetes de Node y, después, instalar el navegador que usará la ruta de Playwright. Revisa de nuevo las instrucciones actuales de configuración de Crawlee y Playwright según las versiones y la plataforma que vayas a desplegar.

Prueba práctica: la misma página, dos respuestas muy distintas

Crawlee Cheerio 0 vs Playwright 8/8

La prueba principal envió el mismo fixture renderizado en JavaScript a ambos crawlers. La URL y los campos objetivo eran compartidos; las primitivas de extracción, no.

En el fixture local, CheerioCrawler devolvió 0 tarjetas objetivo porque no estaban presentes en el HTML bruto. PlaywrightCrawler esperó a #dynamic-products article.product-card y luego devolvió las 8 tarjetas esperadas, además de capturar una captura de pantalla. Ese resultado confirma la completitud a nivel de fixture para los campos seleccionados después de esa espera; no significa que un navegador vea todos los estados posibles de una página. Los archivos originales y la captura están en el repositorio del benchmark.

Crawlee public Quotes JS ten

En la página pública Quotes to Scrape JS, CheerioCrawler encontró 0 citas objetivo y PlaywrightCrawler esperó a .quote antes de extraer 10. Esto confirma el mismo límite entre HTTP y navegador en un objetivo público, aunque la clase de crawler, el contexto del handler, la condición de espera y la primitiva de extracción sean distintos en cada lado.

La conclusión útil es más concreta: valida los campos necesarios con la ruta HTTP, y pasa a un crawler de navegador cuando la respuesta bruta no los incluya. El handler del navegador también debe esperar una condición vinculada a esos campos.

La ruta HTTP produjo todos los registros esperados en los fixtures controlados de catálogo estático y artículos, decodificó los ocho elementos esperados desde una respuesta JSON directa, recorrió un grafo acotado de 11 páginas y envió una respuesta 500 a failedRequestHandler. Son comprobaciones de capacidad separadas, no una única nota de precisión. Frente a la página pública Books to Scrape, el selector configurado devolvió 20 productos como prueba rápida.

PruebaMotorResultado
Extracción estática: catálogo + paginaciónCheerioCrawler12/12 productos esperados
Extracción de artículosCheerioCrawlertítulo + 3/3 párrafos
Transporte: respuesta JSON directaCheerioCrawler8/8 productos esperados
Recorrido: grafo de enlaces internosCheerioCrawler11 páginas, profundidades {0:1, 1:3, 2:7}
Ruta de fallo: HTTP 500CheerioCrawlerel estado llegó al handler de fallo
Renderizado: fixture localCheerioCrawler0 tarjetas objetivo en el HTML bruto
Renderizado: fixture localPlaywrightCrawler8/8 tras esperar el selector objetivo
Renderizado: Quotes JSCheerioCrawler0 citas objetivo en el HTML bruto
Renderizado: Quotes JSPlaywrightCrawler10 tras esperar el selector objetivo

Los tiempos completos y los números por prueba están en results/crawlee-test-summary.json.

Ahora, las advertencias honestas, porque una prueba de una sola máquina y una sola ejecución tiene límites y no voy a fingir lo contrario. Esto son tiempos, no benchmarks: una máquina, una ejecución por prueba, así que considera el mayor coste por página de la ruta de navegador como “claramente más lento que las ejecuciones Cheerio de menos de un segundo”, no como una cifra publicada. Y hay varias cosas que no probé en esta pasada: rotación de proxies, pools de sesiones, ejecuciones a gran escala de cientos o miles de páginas, persistencia y reanudación de RequestQueue tras un fallo, el motor Puppeteer y la ergonomía de exportación de Dataset/KeyValueStore (aquí hice las exportaciones manualmente). Puedo dar fe de la historia de dos motores y de la precisión a nivel de fixture. No puedo dar fe de la escalabilidad ni del comportamiento anti-bloqueo, así que no lo haré.

Qué se comparte y qué debe cambiar

Crawlee one-line engine switch

La superficie común es la orquestación del rastreo. Ambas clases de crawler aceptan un requestHandler y exponen run(). Las colas, los metadatos de la petición, el descubrimiento de enlaces, los hooks de fallo y los conceptos de almacenamiento pueden organizarse de forma consistente sobre cualquiera de los dos caminos de ejecución. Eso reduce la cantidad de infraestructura que un equipo tiene que reaprender cuando un objetivo necesita navegador.

La superficie de acceso a la página no es común. Un handler de CheerioCrawler recibe acceso orientado a Cheerio, como $, y puede trabajar con el cuerpo de la respuesta sin navegador. El handler de PlaywrightCrawler probado recibe page; espera a un selector y evalúa sobre el DOM del navegador. Incluso cuando ambos handlers emiten el mismo esquema de registro, llegan a él mediante APIs distintas. Un adaptador reutilizable podría ocultar parte de esa diferencia, pero este harness no implementó ni demostró uno.

Esa distinción importa para las estimaciones. Cambiar la clase de crawler puede conservar la cola, el dataset y la política de URLs, pero los selectores, las comprobaciones de disponibilidad, las capturas, los pasos de interacción y el manejo de errores todavía pueden cambiar. Por eso el artículo trata “infraestructura compartida de rastreo” como el beneficio verificado y rechaza la promesa de “migración en una línea” por no estar respaldada.

Un flujo práctico para elegir motor

Empieza por la ruta HTTP cuando el HTML devuelto o una respuesta JSON directa contengan los campos necesarios. Define un contrato de completitud —claves obligatorias, número mínimo de elementos o un selector objetivo— y falla de forma explícita cuando no se cumpla. Un array vacío no prueba que la página no tenga datos; en los dos casos JavaScript de aquí significó que la representación elegida no incluía los elementos objetivo.

Condición del objetivoEmpezar conEscalar cuando
Los campos obligatorios están en el HTML devueltoCheerioCrawlerFalten selectores o campos obligatorios
Una respuesta JSON reproducible contiene los datosCheerioCrawlerLa petición dependa de estado solo disponible en navegador
La página inserta elementos objetivo después de ejecutar scriptsPlaywrightCrawlerNo aplica; define una comprobación de disponibilidad específica
Se desconoce el tipo de objetivoHTTP primero con validación de completitudLa validación falle con un resultado tipado de “representación incompleta”

Pasa ese fallo tipado a un handler de navegador cuando la ejecución sea necesaria. En este harness, la página local esperaba #dynamic-products article.product-card, mientras que la página pública de citas esperaba .quote. Esas condiciones forman parte del contrato de extracción. Un evento genérico de carga no demostraría que los datos de la aplicación ya llegaron, y la prueba no respalda una regla universal de espera.

Después de escalar, mantén estable el esquema de salida aunque cambien las primitivas DOM. Registra qué motor produjo el resultado, qué condición de disponibilidad se cumplió y si la validación de campos obligatorios pasó. Así el fallback de HTTP a navegador queda visible, en vez de convertir silenciosamente los campos ausentes en registros aceptados.

Por último, trata la instalación y el coste operativo del navegador como entradas de despliegue. La observación de unos 82 MiB solo sirve como orden de magnitud local; mide la build exacta del navegador, la plataforma, el comportamiento de caché y el impacto en la imagen en tu entorno. La rotación de proxies, las sesiones, la persistencia, la recuperación tras fallos y la concurrencia sostenida siguen necesitando sus propias pruebas antes de que este fixture sirva para decidir en producción.

Ventajas y desventajas

Ventajas:

  • Los crawlers HTTP y de navegador comparten conceptos de ciclo de vida, pero exponen contextos de extracción específicos para cada motor.
  • Extracción HTTP con recall 1.0 en catálogos estáticos, artículos y APIs JSON.
  • Infraestructura compartida en ambos motores: RequestQueue, enqueueLinks con control de profundidad, Dataset.
  • La ruta de navegador ejecutó los scripts del fixture y recuperó todos los elementos objetivo esperados en las dos pruebas renderizadas con JavaScript.
  • Manejo de errores limpio: el HTTP 500 se expuso sin que el proceso se cayera.
  • Licencia Apache-2.0; los usuarios finales deberían revisar sus obligaciones de aviso y atribución.

Desventajas:

  • En el entorno probado, el motor de navegador necesitó una instalación separada de Chromium; sin ella PlaywrightCrawler no arrancó.
  • La ruta HTTP no puede mostrar elementos objetivo ausentes del HTML bruto; sin validación de completitud, eso puede parecer un resultado vacío válido.
  • La ruta de navegador añade un binario extra y un mayor coste local por página en esta ejecución; el tamaño y los tiempos varían según la build y la plataforma.
  • Las ejecuciones por defecto dejan un directorio storage/ en disco.
  • Solo Node/TypeScript: no ayuda si tu stack es Python.

Para quién es — y quién debería saltárselo

Crawlee encaja con equipos de Node o TypeScript que necesitan tanto rastreo HTTP como en navegador bajo conceptos compartidos de cola y ciclo de vida. Una ruta práctica es intentar primero el crawler HTTP, validar los campos obligatorios y escalar un fallo tipado de completitud a un handler de navegador con una condición de disponibilidad específica del objetivo. El código de acceso al DOM del handler es específico del motor incluso cuando la infraestructura de cola y descubrimiento de enlaces se comparte.

Baja las expectativas, o busca otra opción, si trabajas en Python (Crawlee es de Node/TS — existe un puerto aparte para Python, pero este análisis probó la librería de Node), si todos tus objetivos son estáticos y prefieres un scraper HTTP más simple y ligero, o si necesitas comportamiento probado a gran escala — rotación de proxies, pools de sesiones, reanudación tras fallos — algo que esta prueba práctica no cubrió. Y si vas a usar PlaywrightCrawler, instala Chromium antes o simplemente no arrancará.

Alternativas, y dónde encaja Thunderbit

Crawlee es software de código abierto que tú mismo ejecutas y mantienes. No tiene coste por llamada de proveedor, pero el cómputo del navegador, el ancho de banda, los proxies, el almacenamiento, la observabilidad y el trabajo de ingeniería siguen siendo costes operativos. Tú te encargas de la elección del crawler, el binario del navegador, el estado del almacenamiento y la lógica de disponibilidad.

Revisión relacionada: revisión de scrapy-playwright.

Un servicio gestionado de extracción traslada al proveedor la responsabilidad de adquisición y definición de esquema. Nosotros construimos Thunderbit, pero no lo ejecutamos contra estos fixtures, así que este artículo no permite comparar calidad, latencia, paridad de funciones ni costes. La decisión relevante es si tu equipo quiere el control in-process de Crawlee o una frontera de servicio por llamada.

Revisiones de benchmark relacionadas: la comparación completa de scrapers open source, Playwright vs Puppeteer en las mismas páginas y la revisión de Scrapy sin replay de peticiones en navegador.

Prueba Thunderbit para extracción de datos web

Veredicto

Crawlee es una opción sólida para equipos de Node o TypeScript que quieren orquestación de rastreo compartida entre HTTP y ejecución en navegador. Los handlers probados no eran intercambiables: pasar a Playwright requirió page, una espera por selector objetivo y extracción del lado del navegador. Quedan abiertas las preguntas sobre proxies, sesiones, persistencia, reanudación y comportamiento a gran escala.

Prueba Thunderbit para extracción de datos web Get Started Free

Preguntas frecuentes

¿Cuál es la diferencia real entre los dos crawlers de Crawlee? CheerioCrawler obtiene HTML por HTTP y no ejecuta JavaScript. PlaywrightCrawler controla Chromium y puede ejecutar scripts de la página y tomar capturas, pero con un mayor coste local por página. Comparten conceptos de ciclo de vida, aunque no el mismo contexto de handler: en esta prueba se usó $ en la ruta HTTP y page, una espera por selector objetivo y evaluación del lado del navegador en la ruta de Playwright.

¿Por qué PlaywrightCrawler no arranca después de instalar Crawlee? En el entorno probado, la instalación del paquete no incluía un ejecutable de navegador. Instalar Chromium con npx playwright install chromium resolvió el fallo de arranque. La carga observada fue de unos 82 MiB, pero la medición original no conservó si era tamaño de transferencia o de disco, así que conviene volver a medirlo en tu plataforma y build.

¿Puede CheerioCrawler extraer páginas renderizadas con JavaScript? No puede ejecutar el JavaScript de la página. Aun así, sí puede pedir un endpoint JSON accesible que use el cliente, como muestra el fixture de respuesta directa. Cuando los datos necesarios solo existen después de la ejecución en navegador, usa un crawler de navegador y una condición de disponibilidad vinculada a esos campos.

¿Crawlee es preciso para extracción estática normal? En los fixtures controlados, los handlers produjeron 12/12 productos esperados del catálogo, 3/3 párrafos esperados del artículo y 8/8 elementos JSON directos esperados. Son comprobaciones de completitud del fixture, no una nota general de precisión para sitios no probados.

¿Crawlee es gratis para uso comercial? Se publica bajo Apache-2.0. Confirma la licencia actual en el repositorio y revisa las obligaciones de aviso y atribución para tu distribución.

Antes de adoptarlo en producción, prueba las partes que este fixture deja abiertas: concurrencia repetida sobre páginas representativas, comportamiento de proxies y sesiones, recuperación de colas persistentes tras interrupciones, limpieza de procesos de navegador y exportación de datasets bajo fallo. Conserva junto a esos resultados la versión del navegador y la ruta de instalación resueltas. Las dos clases de crawler reducen las diferencias de orquestación, pero no eliminan la necesidad de comprobaciones de disponibilidad específicas del motor, presupuestos de recursos y manejo operativo de fallos.

Ke
Ke
CTO en Thunderbit | Científico de datos sénior y experto en ML Con casi una década de experiencia en aprendizaje automático y ciencia de datos, Ke Shen es exalumno de la Universidad de Columbia y antiguo científico de datos sénior en Walmart Labs. Con una sólida experiencia, reconocida por sus pares, en Python, R, Java y estadística, comparte conocimientos probados en el campo sobre cómo llevar algoritmos complejos de IA desde la teoría hasta una arquitectura lista para producción.
Tabla de contenidos
Thunderbit · Agente de datos web con IA

Extrae datos de cualquier página en 1 clic

Con la confianza de más de 250,000 usuarios
plan gratuito disponible
De la página web a la hoja de cálculo
Describe lo que necesitas: el agente de IA de Thunderbit lo extrae y lo exporta a Excel, Google Sheets, Airtable o Notion. Empieza gratis.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week