Mga Self-Hosted Firecrawl Alternative para sa VPS
Ihambing ang Draco, Hound, at self-hosted Firecrawl sa RAM, headless browser, API compatibility, pinned install, at MCP wire-up para sa VPS.
Ano ang kailangang gawin ng isang self-hosted na alternatibo sa Firecrawl
Iisa ang pangunahing gawain ng isang self-hosted na alternatibo sa Firecrawl: tumanggap ng URL at ibalik ang laman ng page bilang malinis na markdown na kayang basahin ng agent. Naniningil ang mga hosted API batay sa bawat page, kaya lumalaki ang bill depende sa dami ng page na gustong suriin ng agent. Magagawa rin ng VPS na binabayaran mo na ang parehong gawain. Nagkakaiba ang mga proyekto sa isang tanong: kailangan bang magsimula sa server mo ang isang headless browser (tunay na browser engine na tumatakbo nang walang window)?
Tinutukoy ng sagot na iyon ang memory footprint, gastos sa bawat page, at kung aling mga page ang babalik na walang laman. Inihahambing ng gabay na ito ang Draco, Hound, at self-hosted release ng Firecrawl, ini-install ang pinakamagaan sa mga ito gamit ang naka-pin na version, at ikinokonekta ito sa isang agent sa pamamagitan ng MCP (model context protocol).
Ang apat na project at ang aktuwal na gamit ng bawat isa
Ang Draco ay isang binary na isinulat sa Rust at lisensyado sa ilalim ng MIT o Apache-2.0. Inilabas ang release v0.20.5 noong 16 July 2026. Ang draco scrape <url> ay nagpi-print ng markdown sa stdout. Ang draco serve ay nagpapatakbo ng daemon na tumatanggap ng request sa 127.0.0.1:3002, ang port na ginagamit ng Firecrawl. Wala itong container image at hindi ito nagsisimula ng browser.
Ang Firecrawl self-hosted ang engine sa likod ng hosted product at lisensyado sa ilalim ng AGPL-3.0. Tinutukoy ng docker-compose.yaml nito ang pitong service: playwright-service, api, redis, rabbitmq, nuq-postgres, foundationdb, at foundationdb-init. Makukuha mo ang aktuwal na crawl queue, kapalit ng pagpapatakbo ng isang maliit na distributed system.
Ang Hound ay nasa master-fetch repository at inilalabas sa PyPI bilang hound-mcp. MIT licensed ito at bersyon 13.0.1 noong 3 August 2026. Kailangan nito ng Python 3.11 o mas bago. MCP server muna ito at fetcher lamang pagkatapos: sinusubukan muna nito ang plain HTTP, at nagsisimula lamang ng Patchright browser kapag blocked ang resulta ng plain fetch.
Nasa talakayang ito ang Trawl dahil nakikita ito ng mga tao habang hinahanap ang iba pang project, ngunit iba ang trabaho nito. Nilulutas nito ang JavaScript challenge at CAPTCHA gamit ang fingerprint-patched Firefox, bilang kapalit ng FlareSolverr sa isang *arr media stack. Hindi ito markdown extractor. Ipinapaliwanag sa seksyon tungkol sa wastong paggamit sa ibaba kung bakit ang pagkakaibang ito ang nagtatakda kung dapat ba itong isama sa agent stack mo.
Kung bakit sa browser pool bumibigay ang maliliit na VPS box
Ang bawat nakabukas na browser tab ay hiwalay na renderer process na may sarili nitong DOM (document object model) at JavaScript heap. Kaya nakabatay ang paggamit ng memory sa dami ng page na sabay-sabay na nakabukas, hindi sa dami ng page na na-fetch sa loob ng isang araw. Isinasama ng dalawang project na ito ang gastusing iyon sa sarili nilang compose files.
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
}
]Nililimitahan ng Firecrawl compose file ang api container nito sa 8 GB at ang Playwright container nito sa 4 GB, kasama ang katumbas na swap limits. Itinatakda naman ng compose ni Hound ang 3 GB para sa isang container na may bundled Chromium. Mga ceiling ang mga ito na pinili at inilathala ng mga project, hindi mga sukat mula sa tahimik na system. Kailangan pa rin ng Redis, RabbitMQ, PostgreSQL, at FoundationDB ang sarili nilang bahagi ng memory bukod sa mga numero ng Firecrawl.
Walang silbi ang ceiling na mas mataas sa RAM na mayroon ka. Kapag naubusan ng memory ang box, tinatapos ng kernel out-of-memory killer ang isang process. Dahil dito, nawawala ang container sa docker compose ps nang walang naisusulat na error sa application log. Basahin ang dmesg -T | tail pagkatapos ng anumang restart na hindi mo maipaliwanag. Maglaan ng 8 GB para sa buong Firecrawl stack at ituring ang 4 GB bilang minimum para sa test box. Tinalakay sa memory limits sa Docker Compose ang pagtatakda ng mga numero para sa bawat service.
May isa pang detalye tungkol sa browser na maaaring kumain ng isang buong gabi sa pag-troubleshoot. Nagbibigay ang Docker ng 64 MB ng shared memory sa isang container sa /dev/shm, at doon inilalagay ng Chromium ang renderer buffers nito. Kaya nagka-crash ito sa mabibigat na page. Tinaasan ng parehong browser stack ang limitasyong ito: nasa compose ni Hound ang shm_size: "1gb". Kopyahin ang linyang iyon sa anumang image na bina-build mo para sa Playwright.
Katumpakan ng extraction sa mga page na mabigat sa JavaScript
Sa static HTML, server-rendered na blog, documentation page, o news article, halos magkapareho ang markdown na ibinabalik ng mga ito, kaya ang pinakamabilis ang nananalo. Lumilitaw ang pagkakaiba sa mga client-rendered page, kung saan walang laman na shell ang delivered HTML at dumarating ang text mula sa JavaScript pagkatapos mag-load.
Umaakyat ang Draco sa magkakasunod na tier. Pino-parse ng Tier 0 at Tier 1 ang HTML nang walang JavaScript. Pinapatakbo ng Tier 2 ang sariling JavaScript ng page sa loob ng in-process V8 isolate. Ang V8 isolate ay ang JavaScript engine na walang browser sa paligid nito, at ayon sa README, walang host capability bindings na nakukuha roon ang page code. Sapat ito para sa maraming single-page application gamit ang maliit na bahagi ng memory na kailangan ng browser. Kapag nakatagpo ang Draco ng hadlang na hindi nito malampasan, lumalabas ang draco scrape na may exit code na 3, needs_browser. Suriin ito sa mga script, dahil ang walang-lamang file na may zero exit code ang tahimik na failure na sumisira sa context ng agent:
draco scrape https://example.com > page.md
echo "exit=$?"Kinokontrol ng playwright-service ng Firecrawl ang aktuwal na Chromium, kaya nire-render nito ang nakikita ng browser. Hindi pa rin katumbas ng hosted product ang self-hosted build: ayon sa documentation, walang access sa Fire Engine ang mga self-hosted instance. Dahil dito, wala ang anti-blocking at IP rotation ng cloud service, at hindi suportado ang mga endpoint na /agent at /browser. Sadyang nasa pagitan ang Hound. Kumukuha ito sa pamamagitan ng HTTP at nag-e-escalate bawat request. Nagsasara ang warm browser nito pagkatapos ng idle timeout, kaya nananatiling malapit sa baseline ang tahimik na server.
Mag-install ng Draco gamit ang naka-pin na version
Nakadokumento sa README ang one-line installer. Basahin muna kung ano ang ginagawa nito bago ito i-pipe sa shell: nag-i-install ito sa $HOME/.draco/bin/draco, palagi nitong kinukuha ang latest release, at hindi ito nagsi-check ng signature o hash. Sa server, i-pin ang version at i-verify ang download.
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 SHA256SUMSIpi-print nito ang draco-linux-x86-64.tar.gz: OK. Ibig sabihin ng linyang FAILED ay hindi tugma ang mga byte na hawak mo sa mga byte na inilabas ng project, kaya i-delete ang mga ito at magsimulang muli.
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.comIpi-print ng huling command ang example page bilang markdown sa loob ng wala pang isang segundo. Hindi dekorasyon ang find: hindi bahagi ng public contract ng project ang layout ng archive, at ganoon din hinahanap ng official installer ang binary.
Patakbuhin ang daemon gamit ang sarili nitong account sa halip na ang login user mo. Isulat ang /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/healthSumasagot ang /health kapag nakikinig na ang daemon. Ibig sabihin ng Connection refused na hindi pa ito nakikinig, kaya basahin ang journalctl -u draco -n 50. Karaniwang sanhi nito ang isa pang process na gumagamit na ng port 3002, dahil ito rin ang default port ng Firecrawl, at inililipat ng --port ang alinman sa mga ito. Para sa mas malalim na talakayan tungkol sa unit files: systemd service units at timers.
Ngayon, kunin ito sa paraang gagamitin ng iyong agent:
curl -X POST http://127.0.0.1:3002/v1/scrape \
-H 'content-type: application/json' \
-d '{"url": "https://example.com", "formats": ["markdown"]}'Panatilihing hindi accessible sa public internet ang fetch daemon
Ang fetch API na walang authentication ay isang open proxy. Kahit sino na makakaabot sa port ay maaaring magpagawa sa server mo ng request para sa kahit anong URL gamit ang IP address mo. Sa provider mo mapupunta ang abuse report, hindi sa gumawa nito. Kasama sa documented na serve flags ng Draco ang kawalan ng API key, kaya network ang kailangang magbigay ng protection. Panatilihin ang default na 127.0.0.1 bind kapag tumatakbo ang agent sa parehong box. Kapag nasa ibang machine ang agent, ilagay ang dalawang endpoint sa private tunnel. Karaniwang solusyon ang WireGuard VPN na ikaw mismo ang nagho-host, at dapat itong mag-bind sa address ng tunnel sa halip na sa 0.0.0.0. Pagkatapos, mula sa ibang machine, tiyaking walang sinasagot ang public IP. Sinasaklaw ng mga pangunahing konsepto ng ufw firewall at mga user account na may least privilege ang dalawang bahaging ito.
Magbabago ba ang code ng agent mo? API compatibility sa aktuwal na paggamit
Sinasagot ni Draco ang Firecrawl v1 routes: /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape at /v1/search, at sinasabi sa README nito na tinatanggap at binabalewala ang mga hindi kilalang field. Ang agent na nagpo-post na sa /v1/scrape ay nangangailangan lamang ng bagong base URL. Wala nang iba. Suriin kung ano ang nagbago sa kabilang panig: sinusubok na ngayon ng sariling self-hosting page ng Firecrawl gamit ang /v2/crawl, at v2 na ang ginagamit ng mga kasalukuyang SDK. Kaya kapag itinuro ang v2 client sa Draco, humihingi ito ng route na hindi inilalabas ni Draco. Subukan ang bawat call gamit ang curl bago baguhin ang code ng agent. Basahin din ang JSON body, hindi lamang ang status code, dahil sa mga pangalan ng field nagkakaiba ang mga implementation.
Robots.txt, mga rate limit, at ang hangganang hindi dapat lampasan
Binabasa ng Draco ang robots.txt bilang default, at pinapatay ito ng --ignore-robots. Pareho itong dokumentado ng Firecrawl bilang default. Huwag baguhin ang mga ito. Pagkatapos, itakda ang sarili mong bilis: naglalagay ang --delay ng pagitan na millisecond sa mga request, at nililimitahan ng --max-concurrency ang mga parallel job, na 8 ang default ng daemon. Mas maingat ang dalawa hanggang apat kapag shared ang VPS link, at bihira itong maging mas mabagal sa kabuuan dahil mas maraming minuto ang nawawala kapag nagsimula nang mag-rate limit ang isang site kaysa sa oras na natitipid sa concurrency. I-cache ang mga kinukuha mo para walang gastos sa source ang ikalawang agent run. Ito rin ang pinakamurang item sa pagkontrol sa gastos ng AI agent.
Hiwalay na usapin ang mga challenge wall, at para mismo rito ginawa ang Trawl: Cloudflare Turnstile, reCAPTCHA, hCaptcha, at GeeTest. Ang challenge wall ay tahasang pagtanggi ng isang site sa automated traffic. Kapag nilampasan ito, maaari kang lumabag sa terms of use ng site at, sa ilang lugar, sa batas, kaya fetching infrastructure lamang ang saklaw ng guide na ito. Ang mga technique na nakakalusot sa isang wall ay siya ring mino-monitor at bina-block ng mga site owner. Dahil dito, marupok at hindi rin kanais-nais ang anumang pipeline na umaasa sa mga ito. Kapag napakahalaga ng isang source, hanapin ang RSS feed nito, ang public API nito, o isang bulk export. Mas mura ang bawat isa na patakbuhin, at walang isa man sa mga ito ang masisira sa linggong magbago ang wall.
Iugnay ito sa isang agent gamit ang MCP
Ang MCP (model context protocol) ang interface na ginagamit ng isang agent para tumawag sa isang tool. May MCP server ang Draco sa parehong binary, gamit ang stdio:
{ "mcpServers": { "draco": { "command": "draco", "args": ["mcp"] } } }Lalabas sa agent ang mga tool bilang draco_scrape, draco_search, at ang set na draco_interact_*. Gumagana lamang ang stdio kapag nasa iisang machine ang agent process at ang binary, dahil ang transport nito ay standard input ng process na iyon. Para sa agent na nasa ibang host, naghahatid naman ang Hound ng MCP sa HTTP: nagpa-publish ang hound --http --host 127.0.0.1 --port 8765 ng endpoint sa http://127.0.0.1:8765/mcp, na ina-access mo sa pamamagitan ng tunnel. Makikita sa pagpapatakbo ng MCP servers sa isang VPS ang mga pagpipilian sa transport at kung ano ang dapat i-expose.
Pagkuha ng mga pair gamit ang search. Ang agent na fetch lamang ang kayang gawin ay naghihintay na magbigay ka ng mga URL. Magdagdag ng self-hosted na SearXNG search instance upang siya mismo ang makahanap ng mga ito, gamit ang parehong pattern ng browser search skill na nakabatay sa SearXNG. Kapag umaandar na ang daemon, isa itong shared service para sa alinman sa mga self-hosted AI agent na pinapatakbo mo.
FAQ
Kailangan ko ba ng headless browser para kumuha ng mga page para sa AI agent?
Hindi para sa karamihan ng mga page. Kumpleto nang nagbabalik ang server-rendered na documentation, blog, at news article gamit ang plain HTTP fetch at HTML-to-markdown step. Ito ang ginagawa ng Draco sa mas mababang tier nito, na humigit-kumulang 300 ms bawat page ayon sa sariling figures ng proyekto. Sulit ang memory ng browser sa client-rendered application, kung saan walang laman na shell ang naihahatid na HTML. Sinasaklaw ng V8 isolate ng Draco ang malaking bahagi ng ganitong kaso nang walang browser process. Lumalabas ito na may code 3, needs_browser, kapag hindi nito kayang i-render ang page.
Gaano karaming RAM ang kailangan ng self-hosted Firecrawl sa isang VPS?
Nagtatakda ang compose file nito ng limitasyong 8 GB sa api container at 4 GB sa Playwright container. Sinisimulan din ng parehong stack ang Redis, RabbitMQ, PostgreSQL, at FoundationDB. Maglaan ng 8 GB. Sa isang 2 GB na machine, inaalis ng kernel out-of-memory killer ang mga container kapag mataas ang load. Ang unang senyales ay isang container na nag-restart sa docker compose ps na walang kapaki-pakinabang na entry sa application log. Kumpirmahin ito gamit ang dmesg -T | tail.
Drop-in replacement ba ang Draco para sa Firecrawl API?
Malapit ito para sa mga v1 endpoint. Sineserbisyuhan nito ang /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape, at /v1/search. Binabalewala rin nito ang mga request field na hindi nito kilala. Kaya karaniwang bagong base URL lamang ang kailangang baguhin sa client na ginawa para sa Firecrawl v1. Hindi ito ang hosted product. Walang managed proxy pool sa likod nito, at hindi kasama sa surface ang mas bagong v2 route ng Firecrawl. I-verify muna ang bawat call na ginagawa ng iyong agent gamit ang curl.
Kapag nag-self-host ako ng scraper, maaari ko na bang balewalain ang robots.txt?
Hindi. Walang nagbabago sa kung ano ang inilathala ng isang site o sa pinapahintulutan ng mga tuntunin nito dahil lamang sa kung saan tumatakbo ang code. Bilang default, iginagalang ng Draco at Firecrawl ang robots.txt. Para lamang sa mga site na pagmamay-ari mo o sa mga site kung saan mayroon kang nakasulat na pahintulot na mag-crawl, ang override flag. Ipinatutupad pa rin sa dulo ng network ang rate limits. Kaya nakatutulong ang maingat na --delay na may mababang concurrency upang manatiling gumagana ang iyong IP address. Ang stack na gumagana lamang kapag nilalampasan ang isang challenge wall ay maaaring biglang tumigil nang walang babala.