Alternativas autoalojadas a Firecrawl para un VPS
Compara Draco, Hound y Firecrawl autoalojado por RAM, navegador headless y compatibilidad API. Incluye instalación fijada y conexión MCP para agentes.
Qué debe hacer una alternativa autoalojada a Firecrawl
Una alternativa autoalojada a Firecrawl tiene una función: recibir una URL y devolver la página como Markdown limpio que un agente pueda leer. Las API alojadas cobran por página, por lo que la factura aumenta según la cantidad de páginas que consulte el agente. Un VPS que ya paga puede realizar el mismo trabajo. Los proyectos se diferencian en una cuestión: ¿es necesario iniciar en su servidor un navegador headless (un motor de navegador real que se ejecuta sin ventana)?
La respuesta determina el consumo de memoria, el coste de cada página y qué páginas devuelven contenido vacío. Esta guía compara Draco, Hound y la versión autoalojada de Firecrawl, instala la opción más ligera en una versión fijada y la conecta a un agente mediante MCP (model context protocol).
Los cuatro proyectos y qué es realmente cada uno
Draco es un único binario escrito en Rust, con licencia MIT o Apache-2.0. La versión v0.20.5 se publicó el 16 de julio de 2026. draco scrape <url> imprime Markdown en stdout. draco serve ejecuta un daemon que responde en 127.0.0.1:3002, el puerto que usa Firecrawl. No proporciona ninguna imagen de contenedor ni inicia ningún navegador.
Firecrawl self-hosted es el motor del producto alojado, con licencia AGPL-3.0. Su docker-compose.yaml define siete servicios: playwright-service, api, redis, rabbitmq, nuq-postgres, foundationdb y foundationdb-init. Incluye la cola de rastreo real, a cambio de ejecutar un sistema distribuido pequeño.
Hound se encuentra en el repositorio master-fetch y se publica en PyPI como hound-mcp, con licencia MIT y versión 13.0.1 a fecha del 3 de agosto de 2026. Requiere Python 3.11 o posterior. Es, ante todo, un servidor MCP y, en segundo lugar, un fetcher: intenta usar HTTP sin más y sólo inicia un navegador Patchright cuando la petición HTTP simple devuelve una respuesta bloqueada.
Trawl aparece aquí porque los usuarios se encuentran con él al buscar los otros proyectos, pero realiza una tarea distinta. Resuelve desafíos de JavaScript y CAPTCHAs mediante un Firefox con el fingerprint modificado, como sustituto de FlareSolverr en un stack multimedia *arr. No es un extractor de Markdown. La sección sobre buenas prácticas que aparece más abajo explica por qué esta diferencia determina si debe formar parte de su stack de agentes.
Por qué el grupo de navegadores acaba con los VPS pequeños
Cada pestaña de navegador abierta es un proceso de renderizado independiente que mantiene su propio DOM (modelo de objetos del documento) y su propio heap de JavaScript. Por tanto, el consumo de memoria aumenta con las páginas abiertas al mismo tiempo, no con las páginas consultadas al día. Dos de estos proyectos reflejan ese coste en sus propios archivos compose.
The data behind this chart
[
{
"label": "Firecrawl api",
"memory_limit_gb": 8
},
{
"label": "Firecrawl playwright",
"memory_limit_gb": 4
},
{
"label": "Hound (browser included)",
"memory_limit_gb": 3
}
]El archivo compose de Firecrawl limita el contenedor api a 8 GB y el contenedor de Playwright a 4 GB, con límites de swap equivalentes. El compose de Hound establece 3 GB para un contenedor que incluye un Chromium integrado. Estos son los límites que eligieron los proyectos, cifras publicadas y no mediciones de un sistema en reposo. Además, Redis, RabbitMQ, PostgreSQL y FoundationDB siguen necesitando su parte por encima de las cifras de Firecrawl.
Un límite superior a la RAM disponible no sirve de nada. Cuando el sistema se queda sin memoria, el kernel finaliza un proceso mediante el out-of-memory killer. Por eso, un contenedor puede desaparecer de docker compose ps sin que se escriba ningún error en el registro de la aplicación. Consulte dmesg -T | tail después de cualquier reinicio cuya causa no pueda explicar. Reserve 8 GB para el stack completo de Firecrawl y considere 4 GB el mínimo para un equipo de pruebas. La configuración de los límites por servicio se explica en límites de memoria en Docker Compose.
Hay otro detalle del navegador que puede hacer perder una tarde. Docker proporciona a cada contenedor 64 MB de memoria compartida en /dev/shm, y Chromium coloca allí los búferes de renderizado. Por eso se bloquea con páginas pesadas. Ambos stacks de navegador aumentan este valor: el compose de Hound incluye shm_size: "1gb". Copie esa línea en cualquier imagen que construya alrededor de Playwright.
Calidad de extracción en páginas con mucho JavaScript
En HTML estático, un blog renderizado en el servidor, una página de documentación o un artículo de noticias devuelven markdown casi idéntico, y gana la opción más rápida. La diferencia aparece en las páginas renderizadas en el cliente, donde el HTML entregado es una estructura vacía y el texto llega mediante JavaScript después de la carga.
Draco escala por niveles. Los niveles 0 y 1 analizan el HTML sin ejecutar JavaScript. El nivel 2 ejecuta el JavaScript de la página dentro de un aislamiento V8 en el mismo proceso. Es decir, usa el motor de JavaScript sin un navegador alrededor, y el README indica que el código de la página no recibe enlaces a capacidades del host. Esto cubre muchas aplicaciones de una sola página con una fracción de la memoria de un navegador. Cuando Draco encuentra un bloqueo que no puede superar, draco scrape termina con el código 3, needs_browser. Compruébelo en los scripts, porque un archivo vacío con un código de salida 0 es el fallo que contamina silenciosamente el contexto de un agente:
draco scrape https://example.com > page.md
echo "exit=$?"El servicio playwright-service de Firecrawl controla un Chromium real, por lo que renderiza lo mismo que renderiza un navegador. La compilación autoalojada sigue sin ser el producto alojado: la documentación indica que las instancias autoalojadas no tienen acceso a Fire Engine. Por tanto, no disponen de las funciones contra bloqueos ni de la rotación de IP del servicio en la nube, y los endpoints /agent y /browser no son compatibles. Hound se sitúa deliberadamente entre ambos enfoques. Obtiene el contenido mediante HTTP y escala por petición. Su navegador permanece activo y se cierra después de un tiempo de inactividad, por lo que un equipo sin actividad se mantiene cerca de su consumo habitual.
Instalar Draco con una versión fijada
El README documenta un instalador de una sola línea. Lea lo que hace antes de pasarlo a un shell: instala en $HOME/.draco/bin/draco, siempre obtiene la versión latest y no comprueba ninguna firma ni hash. En un servidor, fije la versión y verifique la descarga.
cd /tmp
curl -fsSLO https://github.com/0xchasercat/draco/releases/download/v0.20.5/draco-linux-x86-64.tar.gz
curl -fsSLO https://github.com/0xchasercat/draco/releases/download/v0.20.5/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMSEsto muestra draco-linux-x86-64.tar.gz: OK. Una línea FAILED significa que los bytes que tiene no coinciden con los que publicó el proyecto. Elimínelos y vuelva a empezar.
mkdir -p draco-v0.20.5
tar -xzf draco-linux-x86-64.tar.gz -C draco-v0.20.5
sudo install -m 755 "$(find draco-v0.20.5 -type f -name draco | head -n1)" /usr/local/bin/draco
draco scrape https://example.comEl último comando muestra la página de ejemplo en formato markdown en bastante menos de un segundo. find no es decorativo: la estructura del archivo no forma parte del contrato público del proyecto, y el instalador oficial localiza el binario de la misma forma.
Ejecute el daemon con su propia cuenta, no con su usuario de inicio de sesión. Escriba /etc/systemd/system/draco.service:
[Unit]
Description=Draco fetch daemon
After=network-online.target
Wants=network-online.target
[Service]
User=draco
ExecStart=/usr/local/bin/draco serve --host 127.0.0.1 --port 3002 --max-concurrency 4
Restart=on-failure
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.targetsudo useradd --system --no-create-home --shell /usr/sbin/nologin draco
sudo systemctl daemon-reload
sudo systemctl enable --now draco
curl -s http://127.0.0.1:3002/health/health responde en cuanto el daemon está escuchando. Connection refused significa que no lo está, así que lea journalctl -u draco -n 50. La causa habitual es que otro proceso ya ocupa el puerto 3002, porque también es el puerto predeterminado de Firecrawl, y --port cambia uno de los dos. Consulte más información sobre los archivos de unidad en: unidades y temporizadores de servicio de systemd.
Ahora obtenga el contenido de la forma en que lo hará su agente:
curl -X POST http://127.0.0.1:3002/v1/scrape \
-H 'content-type: application/json' \
-d '{"url": "https://example.com", "formats": ["markdown"]}'Mantenga el demonio de fetch fuera de Internet pública
Una API de fetch sin autenticación es un proxy abierto. Cualquiera que pueda acceder al puerto puede hacer que su servidor solicite cualquier URL usando su dirección IP, y el informe de abuso llegará a su proveedor, no a esa persona. Los flags documentados de Draco serve no incluyen una clave de API, por lo que la protección debe estar en la red. Mantenga el bind predeterminado 127.0.0.1 cuando el agente se ejecute en el mismo equipo. Cuando el agente esté en otro equipo, conecte ambos extremos mediante un túnel privado; una VPN de WireGuard alojada por usted suele ser la opción habitual, y debe hacer bind a la dirección del túnel en lugar de 0.0.0.0. Después, compruebe desde otro equipo que la IP pública no responda. Los conceptos básicos del firewall ufw y las cuentas de usuario con privilegios mínimos cubren las dos partes.
¿Cambiará el código del agente? Compatibilidad de API en la práctica
Draco responde a las rutas de Firecrawl v1: /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape y /v1/search, y su README indica que los campos desconocidos se aceptan y se ignoran. Un agente que ya envía peticiones a /v1/scrape sólo necesita una nueva URL base. No es necesario cambiar nada más. Compruebe qué cambió en el otro extremo: la propia página de self-hosting de Firecrawl ahora prueba con /v2/crawl, y los SDK actuales usan v2. Por tanto, un cliente v2 dirigido a Draco solicita una ruta que Draco no publica. Pruebe cada llamada con curl antes de editar el código del agente y lea el cuerpo JSON en lugar del código de estado, porque las diferencias entre estas implementaciones aparecen en los nombres de los campos.
Robots.txt, límites de tasa y el límite que no debe superarse
Draco lee robots.txt de forma predeterminada, y --ignore-robots desactiva ese comportamiento. Firecrawl documenta el mismo valor predeterminado. No cambie ninguno de los dos. Después, establezca su propio ritmo: --delay inserta milisegundos entre las peticiones y --max-concurrency limita los trabajos en paralelo, con 8 como valor predeterminado del daemon. Un valor de dos a cuatro es más adecuado para un enlace compartido de un VPS y rara vez resulta más lento en conjunto, porque un sitio que empieza a aplicar límites de tasa le hace perder más minutos que los que ahorra la concurrencia. Almacene en caché lo que descargue para que una segunda ejecución del agente no genere ningún coste para la fuente. También es la partida más barata de controlar cuánto le cuesta un agente de IA.
Los muros de desafíos son un asunto distinto, y Trawl está diseñado precisamente para ellos: Cloudflare Turnstile, reCAPTCHA, hCaptcha y GeeTest. Un muro de desafíos es, en términos simples, un sitio que rechaza el tráfico automatizado. Evitarlo puede infringir las condiciones de uso del sitio y, en algunos lugares, también la ley, por lo que esta guía se limita a la infraestructura de descarga. Las mismas técnicas que permiten superar un muro son las que los propietarios de los sitios supervisan y bloquean, lo que hace que cualquier canalización basada en ellas sea frágil además de inapropiada. Cuando una fuente es tan importante, busque su fuente RSS, su API pública o una exportación masiva. Todas estas opciones son más baratas de ejecutar y ninguna deja de funcionar durante una semana porque cambie el muro.
Conéctelo a un agente mediante MCP
MCP (model context protocol) es la interfaz que usa un agente para llamar a una herramienta. El nivel superior, mediante el entorno donde se ejecuta el modelo, decide qué herramientas llegan al modelo y si puede llamar a una sin pedirle permiso antes. Por tanto, hacer que el daemon escuche es sólo la mitad de la integración. Draco incluye un servidor MCP en el mismo binario y se comunica mediante stdio:
{ "mcpServers": { "draco": { "command": "draco", "args": ["mcp"] } } }Las herramientas aparecen en el agente como draco_scrape, draco_search y el conjunto draco_interact_*. Stdio sólo funciona cuando el proceso del agente y el binario están en la misma máquina, porque el transporte utiliza la entrada estándar de ese proceso. Para un agente en otro host, Hound sirve MCP mediante HTTP: hound --http --host 127.0.0.1 --port 8765 publica un endpoint en http://127.0.0.1:8765/mcp, al que se accede a través del túnel. Las opciones de transporte y los elementos que se pueden exponer se describen en ejecutar servidores MCP en un VPS.
Obtención de pares mediante búsqueda. Un agente que sólo puede obtener contenido espera a que le proporcione las URL. Añada una instancia de búsqueda SearXNG autohospedada y podrá encontrarlas por sí mismo, con la misma estructura que la capacidad de búsqueda del navegador basada en SearXNG. Cuando el daemon esté activo, será un servicio compartido para cualquiera de los agentes de IA autohospedados que ejecute. Si la parte del agente es la que menos domina, escribir primero un bucle de agente pequeño a mano deja claro dónde se conecta una herramienta de obtención y qué hace el modelo con el markdown que recibe.
FAQ
¿Necesito un navegador sin interfaz gráfica para obtener páginas para un agente de IA?
No para la mayoría de las páginas. La documentación, los blogs y los artículos de noticias generados en el servidor se devuelven completos con una solicitud HTTP simple seguida de una conversión de HTML a Markdown. Eso es lo que Draco hace en sus niveles inferiores, con aproximadamente 300 ms por página sin navegador, según las cifras del proyecto. Un navegador justifica su consumo de memoria en aplicaciones renderizadas en el cliente, donde el HTML entregado es una estructura vacía. El aislamiento V8 de Draco cubre gran parte de ese punto intermedio sin iniciar un proceso de navegador. Cuando no puede hacerlo, termina con el código 3, needs_browser.
¿Cuánta RAM necesita Firecrawl autoalojado en un VPS?
Su archivo compose establece un límite de 8 GB para el contenedor api y de 4 GB para el contenedor de Playwright. La misma pila también inicia Redis, RabbitMQ, PostgreSQL y FoundationDB. Planifique 8 GB. En un equipo con 2 GB, el asesino de procesos por falta de memoria del kernel elimina contenedores bajo carga. El primer indicio es un contenedor reiniciado en docker compose ps sin información útil en el registro de la aplicación. Confírmelo con dmesg -T | tail.
¿Es Draco un reemplazo directo de la API de Firecrawl?
Para los endpoints de v1, la compatibilidad es alta. Sirve /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape y /v1/search. También ignora los campos de solicitud que no reconoce. Por eso, un cliente escrito para Firecrawl v1 normalmente sólo necesita una URL base nueva. No es el producto alojado. No incluye un conjunto de proxies administrados y las rutas nuevas de v2 de Firecrawl no forman parte de su superficie. Verifique primero cada llamada que haga su agente con curl.
¿El autoalojamiento de un scraper significa que puedo ignorar robots.txt?
No. El lugar donde se ejecuta el código no cambia lo que un sitio ha publicado ni lo que permiten sus condiciones. Draco y Firecrawl respetan robots.txt de forma predeterminada. La opción de anulación existe para sitios que usted posee o para los que tiene permiso escrito de rastreo. Los límites de tasa se aplican en el destino de todos modos. Por tanto, un --delay prudente con baja concurrencia ayuda a mantener operativa su dirección IP. Una pila que sólo funciona al superar una pantalla de desafío deja de funcionar sin previo aviso.