Alternatives à Firecrawl auto-hébergées sur un VPS
Comparez Draco, Hound et Firecrawl sur la RAM, le navigateur headless et la compatibilité API. Installez Draco v0.20.5 et reliez-le à MCP.
Ce qu’une alternative auto-hébergée à Firecrawl doit faire
Une alternative auto-hébergée à Firecrawl a une seule fonction : recevoir une URL et renvoyer le contenu de la page sous forme de markdown propre, lisible par un agent. Les API hébergées facturent chaque page. La facture augmente donc avec la curiosité de votre agent, alors qu’un VPS que vous payez déjà peut effectuer le même travail. Les projets se distinguent sur un point : faut-il démarrer un navigateur headless (un véritable moteur de navigateur exécuté sans fenêtre) sur votre serveur ?
Cette réponse détermine l’empreinte mémoire, le coût de chaque page et les pages qui reviennent vides. Ce guide compare Draco, Hound et la version auto-hébergée de Firecrawl, installe la solution la plus légère à une version précise et la connecte à un agent via MCP (model context protocol).
Les quatre projets et ce qu’ils sont réellement
Draco est un binaire unique, écrit en Rust, sous licence MIT ou Apache-2.0. La version v0.20.5 est sortie le 16 juillet 2026. draco scrape <url> affiche du markdown sur stdout. draco serve exécute un daemon qui répond sur 127.0.0.1:3002, le port utilisé par Firecrawl. Il ne fournit aucune image de conteneur et ne démarre aucun navigateur.
Firecrawl self-hosted est le moteur du produit hébergé, sous licence AGPL-3.0. Son fichier docker-compose.yaml définit sept services : playwright-service, api, redis, rabbitmq, nuq-postgres, foundationdb et foundationdb-init. Vous disposez de la véritable file de crawl, au prix de l’exploitation d’un petit système distribué.
Hound se trouve dans le dépôt master-fetch et est distribué sur PyPI sous le nom hound-mcp, sous licence MIT, en version 13.0.1 au 3 août 2026. Il nécessite Python 3.11 ou une version ultérieure. C’est d’abord un serveur MCP, puis un fetcher : il tente une requête HTTP classique et ne démarre un navigateur Patchright que si cette requête est bloquée.
Trawl est mentionné ici parce que les utilisateurs le rencontrent en recherchant les autres projets, mais il remplit une fonction différente. Il résout les challenges JavaScript et les CAPTCHA avec un Firefox dont l’empreinte a été modifiée, comme remplacement de FlareSolverr dans une stack média *arr. Ce n’est pas un extracteur de markdown. La section suivante sur les bonnes pratiques explique pourquoi cette distinction détermine s’il a réellement sa place dans votre stack d’agents.
Pourquoi le pool de navigateurs fait tomber les petits VPS
Chaque onglet de navigateur ouvert correspond à un processus de rendu distinct. Il possède son propre DOM (document object model) et son propre tas JavaScript. La mémoire évolue donc selon le nombre de pages ouvertes au même moment, et non selon le nombre de pages récupérées par jour. Les deux projets inscrivent ce coût dans leurs propres fichiers 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
}
]Le fichier compose de Firecrawl limite le conteneur api à 8 Go et son conteneur Playwright à 4 Go, avec des limites de swap correspondantes. Le fichier compose de Hound définit 3 Go pour un conteneur qui embarque Chromium. Il s’agit des plafonds choisis par les projets et publiés par eux, pas de mesures effectuées sur un système peu chargé. Redis, RabbitMQ, PostgreSQL et FoundationDB ont encore besoin de leur part en plus des valeurs prévues pour Firecrawl.
Un plafond supérieur à la RAM dont vous disposez ne sert à rien. Lorsque le serveur n’a plus de mémoire, le tueur out-of-memory du kernel termine un processus. Le conteneur disparaît alors de docker compose ps sans qu’aucune erreur soit écrite dans le journal de l’application. Consultez dmesg -T | tail après tout redémarrage dont vous ne connaissez pas la cause. Prévoyez 8 Go pour l’ensemble de la stack Firecrawl et considérez 4 Go comme le minimum pour un serveur de test. Le réglage des valeurs par service est expliqué dans les limites mémoire dans Docker Compose.
Un autre détail lié au navigateur peut vous faire perdre une soirée. Docker attribue 64 Mo de mémoire partagée à un conteneur dans /dev/shm. Chromium y place les buffers des processus de rendu, ce qui provoque des crashs sur les pages lourdes. Les deux stacks de navigateur augmentent cette valeur. Le fichier compose de Hound contient shm_size: "1gb". Copiez cette ligne dans toute image que vous construisez autour de Playwright.
Qualité de l’extraction sur les pages fortement dépendantes de JavaScript
Sur du HTML statique, un blog rendu côté serveur, une page de documentation ou un article d’actualité renvoient tous un Markdown presque identique, et le plus rapide l’emporte. La différence apparaît sur les pages rendues côté client : le HTML livré est une coquille vide et le texte arrive après le chargement, via JavaScript.
Draco fonctionne par niveaux. Les niveaux 0 et 1 analysent le HTML sans exécuter JavaScript. Le niveau 2 exécute le JavaScript de la page dans un isolate V8 intégré au processus. Il s’agit du moteur JavaScript sans navigateur autour de lui, et le README indique que le code de la page n’y reçoit aucun binding vers les fonctionnalités de l’hôte. Cette approche prend en charge de nombreuses applications monopages pour une fraction de la mémoire nécessaire à un navigateur. Lorsque Draco rencontre un obstacle qu’il ne peut pas franchir, draco scrape se termine avec le code 3, needs_browser. Vérifiez ce cas dans les scripts, car un fichier vide avec un code de sortie nul est une erreur qui dégrade silencieusement le contexte d’un agent :
draco scrape https://example.com > page.md
echo "exit=$?"Le service playwright-service de Firecrawl pilote un véritable Chromium et restitue donc ce qu’un navigateur restitue. La version auto-hébergée ne correspond toutefois pas au produit hébergé : la documentation indique que les instances auto-hébergées n’ont pas accès à Fire Engine. Les mécanismes anti-blocage et la rotation d’adresses IP du service cloud sont donc absents, et les endpoints /agent et /browser ne sont pas pris en charge. Hound se situe volontairement entre les deux. Il récupère les pages via HTTP et passe à un niveau supérieur selon chaque requête. Son navigateur prêt à l’emploi se ferme après un délai d’inactivité, si bien qu’une machine peu sollicitée reste proche de sa consommation de référence.
Installer Draco avec une version figée
Le README documente un installateur en une ligne. Lisez ce qu’il fait avant de l’envoyer vers un shell : il installe dans $HOME/.draco/bin/draco, utilise toujours la release latest et ne vérifie ni signature ni hash. Sur un serveur, figez la version et vérifiez le téléchargement.
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 SHA256SUMSCette commande affiche draco-linux-x86-64.tar.gz: OK. Une ligne FAILED signifie que les octets que vous avez ne correspondent pas à ceux publiés par le projet. Supprimez-les et recommencez.
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.comLa dernière commande affiche la page d’exemple au format Markdown en bien moins d’une seconde. Le find n’est pas décoratif : la structure de l’archive ne fait pas partie du contrat public du projet, et l’installateur officiel localise le binaire de la même manière.
Exécutez le daemon avec son propre compte plutôt qu’avec votre utilisateur de connexion. Écrivez /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 répond dès que le daemon est en écoute. Connection refused signifie qu’il ne l’est pas. Consultez donc journalctl -u draco -n 50. La cause habituelle est qu’un autre processus utilise déjà le port 3002, qui est également le port par défaut de Firecrawl. --port déplace l’un ou l’autre. Pour plus de détails sur les unit files : unités de service et timers systemd.
Effectuez maintenant la récupération comme le fera votre agent :
curl -X POST http://127.0.0.1:3002/v1/scrape \
-H 'content-type: application/json' \
-d '{"url": "https://example.com", "formats": ["markdown"]}'Garder le daemon fetch hors de l’Internet public
Une API fetch sans authentification est un proxy ouvert. Toute personne qui peut atteindre le port peut faire demander à votre serveur n’importe quelle URL depuis votre adresse IP. Le signalement d’abus est alors envoyé à votre fournisseur, pas à cette personne. Les serve documentés de Draco n’incluent aucune clé d’API. La protection doit donc reposer sur le réseau. Conservez le bind 127.0.0.1 par défaut lorsque l’agent s’exécute sur le même serveur. Lorsque l’agent se trouve ailleurs, placez les deux extrémités dans un tunnel privé. Un VPN WireGuard que vous hébergez vous-même est généralement la solution retenue. Faites alors écouter le service sur l’adresse du tunnel plutôt que sur 0.0.0.0. Vérifiez ensuite, depuis une autre machine, que l’adresse IP publique ne répond à aucune requête. Les bases du pare-feu ufw et les comptes utilisateur dotés des privilèges minimaux couvrent les deux aspects.
Votre code d’agent va-t-il changer ? Compatibilité de l’API en pratique
Draco répond aux routes Firecrawl v1 : /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape et /v1/search. Son README indique que les champs inconnus sont acceptés et ignorés. Un agent qui envoie déjà des requêtes vers /v1/scrape nécessite seulement une nouvelle URL de base. Sur l’autre implémentation, vérifiez ce qui a changé : la page officielle d’auto-hébergement de Firecrawl utilise désormais /v2/crawl pour ses tests, et les SDK actuels parlent v2. Un client v2 configuré pour Draco demande donc une route que Draco ne publie pas. Testez chaque appel avec curl avant de modifier le code de l’agent. Lisez aussi le corps JSON plutôt que le seul code d’état, car ce sont les noms de champs qui diffèrent entre ces implémentations.
Robots.txt, limites de débit et limites à ne pas dépasser
Draco lit robots.txt par défaut, et --ignore-robots désactive ce comportement. Firecrawl documente le même réglage par défaut. Ne modifiez ni l’un ni l’autre. Définissez ensuite votre propre rythme : --delay insère un délai en millisecondes entre les requêtes et --max-concurrency limite le nombre de tâches parallèles, avec 8 comme valeur par défaut du daemon. Une valeur de 2 à 4 sollicite moins une connexion VPS partagée et est rarement plus lente au total, car un site qui commence à vous appliquer une limitation de débit vous fait perdre plus de minutes que la parallélisation n’en fait gagner. Mettez en cache les données récupérées afin qu’une seconde exécution de l’agent ne sollicite pas la source. C’est aussi le poste le moins coûteux dans la maîtrise du coût d’un agent IA.
Les pages de challenge sont un autre sujet, et Trawl est précisément conçu pour les gérer : Cloudflare Turnstile, reCAPTCHA, hCaptcha et GeeTest. Une page de challenge signifie clairement qu’un site refuse le trafic automatisé. La contourner vous expose à une violation des conditions d’utilisation du site et, dans certains pays, de la loi. Ce guide couvre donc l’infrastructure de récupération des données et s’arrête là. Les mêmes techniques qui permettent de franchir une page de challenge sont celles que les propriétaires de sites surveillent et bloquent. Toute pipeline fondée sur ces techniques est donc fragile et intrusive. Lorsqu’une source est aussi importante, recherchez son flux RSS, son API publique ou un export en masse. Ces solutions coûtent moins cher à exploiter et aucune ne cesse de fonctionner la semaine où la page de challenge est modifiée.
Connecter un agent via MCP
MCP (model context protocol) est l’interface qu’un agent utilise pour appeler un outil. Draco intègre un serveur MCP dans le même binaire, via stdio :
{ "mcpServers": { "draco": { "command": "draco", "args": ["mcp"] } } }Les outils apparaissent alors dans l’agent sous la forme de draco_scrape, draco_search et de l’ensemble draco_interact_*. Stdio ne fonctionne que lorsque le processus de l’agent et le binaire se trouvent sur la même machine, car le transport utilise l’entrée standard de ce processus. Pour un agent situé sur un autre hôte, Hound fournit MCP via HTTP : hound --http --host 127.0.0.1 --port 8765 publie un endpoint à l’adresse http://127.0.0.1:8765/mcp, accessible via le tunnel. Les choix de transport et les éléments à exposer sont décrits dans exécuter des serveurs MCP sur un VPS.
Recherche et récupération des paires. Un agent qui peut uniquement récupérer des données attend que vous lui fournissiez les URL. Ajoutez une instance SearXNG auto-hébergée pour la recherche pour qu’il puisse les trouver lui-même, selon le même principe que la compétence de recherche dans un navigateur basée sur SearXNG. Une fois le daemon démarré, il s’agit d’un service partagé par les agents d’IA auto-hébergés que vous exécutez.
FAQ
Ai-je besoin d’un navigateur headless pour récupérer des pages pour un agent d’IA ?
Pas pour la plupart des pages. La documentation rendue côté serveur, les blogs et les articles de presse sont généralement renvoyés complets avec une simple requête HTTP suivie d’une conversion HTML vers Markdown. C’est ce que Draco fait dans ses niveaux inférieurs, à environ 300 ms par page sans navigateur, selon les chiffres du projet. Un navigateur utilise sa mémoire à bon escient pour les applications rendues côté client, lorsque le HTML livré n’est qu’une structure vide. L’isolate V8 de Draco couvre une grande partie de ce cas sans lancer de processus de navigateur. Il se termine avec le code 3, needs_browser, lorsqu’il n’y parvient pas.
Quelle quantité de RAM faut-il à Firecrawl auto-hébergé sur un VPS ?
Son fichier Compose définit une limite de 8 Go pour le conteneur api et de 4 Go pour le conteneur Playwright. La même stack démarre également Redis, RabbitMQ, PostgreSQL et FoundationDB. Prévoyez 8 Go. Sur une machine de 2 Go, l’oom-killer du noyau supprime des conteneurs sous charge. Le premier signe est un conteneur redémarré dans docker compose ps, sans message utile dans le journal de l’application. Confirmez-le avec dmesg -T | tail.
Draco est-il un remplacement direct de l’API Firecrawl ?
Pour les endpoints v1, la compatibilité est bonne. Il expose /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape et /v1/search. Il ignore les champs de requête qu’il ne connaît pas. Un client écrit pour Firecrawl v1 nécessite donc généralement uniquement une nouvelle URL de base. Draco ne correspond pas au produit hébergé : aucun pool de proxy géré n’est fourni et les routes v2 plus récentes de Firecrawl n’en font pas partie. Vérifiez d’abord chaque appel effectué par votre agent avec curl.
L’auto-hébergement d’un scraper permet-il d’ignorer robots.txt ?
Non. L’emplacement d’exécution du code ne change rien à ce qu’un site a publié ni à ce que ses conditions autorisent. Draco et Firecrawl respectent robots.txt par défaut. Le flag de contournement est destiné aux sites dont vous êtes propriétaire ou pour lesquels vous avez obtenu une autorisation écrite d’exploration. Les limites de débit sont appliquées par le serveur distant dans tous les cas. Un --delay modéré avec une faible concurrence permet donc de conserver une adresse IP fonctionnelle. Une stack qui ne fonctionne qu’en contournant un système de challenge finit par tomber en panne sans avertissement.