Self-hosted alternatywy dla Firecrawl na VPS
Porównanie wydajności Draco, Hound oraz Firecrawl pod kątem zużycia RAM i wymagań headless browser. Instrukcja instalacji konkretnej wersji i konfiguracji protokołu MCP.
Wymagania wobec self-hosted alternatywy dla Firecrawl
Self-hosted alternatywa dla Firecrawl ma jedno zadanie: pobrać adres URL i zwrócić zawartość strony w postaci czystego formatu markdown, który może odczytać agent. Hostowane API naliczają opłaty za każdą stronę, więc koszty rosną wraz z aktywnością agenta, podczas gdy opłacany już serwer VPS może wykonać tę samą pracę. Projekty różnią się w jednej kwestii: czy na Twoim serwerze musi zostać uruchomiona przeglądarka typu headless (silnik przeglądarki działający bez interfejsu graficznego)?
Odpowiedź na to pytanie determinuje zużycie pamięci, koszt przetworzenia każdej strony oraz to, które strony zostaną zwrócone jako puste. Niniejszy przewodnik porównuje Draco, Hound oraz self-hosted wydanie Firecrawl, instaluje najlżejsze z nich w przypisanej wersji i łączy je z agentem za pośrednictwem protokołu MCP (model context protocol).
Cztery projekty i opis ich rzeczywistego przeznaczenia
Draco to pojedynczy plik binarny napisany w języku Rust, udostępniony na licencji MIT lub Apache-2.0. Wersja v0.20.5 została opublikowana 16 lipca 2026 roku. draco scrape <url> wyprowadza markdown na standardowe wyjście (stdout). draco serve uruchamia demona, który nasłuchuje na 127.0.0.1:3002, czyli porcie używanym przez Firecrawl. Projekt nie dostarcza obrazu kontenera i nie uruchamia przeglądarki.
Firecrawl self-hosted to silnik napędzający usługę hostowaną, udostępniony na licencji AGPL-3.0. Jego docker-compose.yaml definiuje siedem usług: playwright-service, api, redis, rabbitmq, nuq-postgres, foundationdb oraz foundationdb-init. Użytkownik otrzymuje pełnoprawną kolejkę zadań (crawl queue), płacąc za to koniecznością utrzymania niewielkiego systemu rozproszonego.
Hound znajduje się w repozytorium master-fetch i jest publikowany w PyPI jako hound-mcp na licencji MIT; wersja 13.0.1 została wydana 3 sierpnia 2026 roku. Wymaga środowiska Python 3.11 lub nowszego. Jest to przede wszystkim serwer MCP, a dopiero w drugiej kolejności narzędzie do pobierania danych: podejmuje próbę zwykłego połączenia HTTP, a przeglądarkę Patchright uruchamia tylko wtedy, gdy standardowe pobieranie zostanie zablokowane.
Trawl został uwzględniony, ponieważ użytkownicy często trafiają na niego podczas poszukiwań pozostałych narzędzi, mimo że pełni on inną funkcję. Rozwiązuje wyzwania JavaScript oraz CAPTCHA przy użyciu zmodyfikowanej pod kątem fingerprintingu przeglądarki Firefox, stanowiąc zamiennik dla FlareSolverr w stosie mediowym *arr. Nie jest to ekstraktor markdownu. Sekcja dotycząca etyki poniżej wyjaśnia, dlaczego to rozróżnienie decyduje o tym, czy narzędzie to w ogóle powinno znaleźć się w Twoim stosie agentowym.
Dlaczego pula przeglądarek to miejsce, w którym padają małe serwery VPS
Każda otwarta karta przeglądarki to osobny proces renderujący, utrzymujący własny DOM (Document Object Model) oraz własny stos JavaScript. Zużycie pamięci skaluje się zatem wraz z liczbą stron otwartych w tym samym momencie, a nie z liczbą stron pobranych w ciągu dnia. Dwa z tych projektów uwzględniają ten koszt w swoich plikach 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
}
]Plik compose dla Firecrawl ogranicza kontener api do 8 GB, a kontener Playwright do 4 GB, przy zachowaniu odpowiednich limitów swap. Plik compose dla Hound ustawia 3 GB dla jednego kontenera, który zawiera wbudowany Chromium. Są to limity wybrane przez autorów projektów, opublikowane wartości, a nie pomiary systemu w stanie spoczynku. Ponadto Redis, RabbitMQ, PostgreSQL oraz FoundationDB również wymagają przydziału pamięci ponad wartości podane dla Firecrawl.
Limit ustawiony powyżej posiadanej pamięci RAM nie przynosi żadnego efektu. Gdy serwerowi kończy się pamięć, mechanizm OOM (Out-Of-Memory) killer jądra systemu kończy proces, przez co kontener znika z docker compose ps bez żadnego błędu zapisanego w dzienniku aplikacji. Po każdym niewyjaśnionym restarcie sprawdź dmesg -T | tail. Zaplanuj 8 GB pamięci dla pełnego stosu Firecrawl i traktuj 4 GB jako absolutne minimum dla środowiska testowego. Ustawianie limitów dla poszczególnych usług opisano w limitach pamięci w Docker Compose.
Jeszcze jeden szczegół dotyczący przeglądarek kosztuje użytkowników wiele straconego czasu. Docker przydziela kontenerowi 64 MB pamięci współdzielonej w /dev/shm, a Chromium umieszcza tam bufory renderowania, co powoduje awarie przy złożonych stronach. Oba stosy przeglądarkowe zwiększają tę wartość: plik compose dla Hound zawiera shm_size: "1gb". Skopiuj tę linię do każdego obrazu budowanego w oparciu o Playwright.
Jakość ekstrakcji na stronach intensywnie korzystających z JavaScript
W przypadku statycznego HTML, blogów renderowanych po stronie serwera, stron dokumentacji czy artykułów informacyjnych, wszystkie zwracają niemal identyczny kod markdown, a najszybsze rozwiązanie wygrywa. Różnica pojawia się na stronach renderowanych po stronie klienta, gdzie dostarczony HTML jest pustą powłoką, a tekst dociera za pośrednictwem JavaScript dopiero po załadowaniu strony.
Draco eskaluje działania w ramach poziomów. Poziom 0 i poziom 1 parsują HTML bez użycia JavaScript. Poziom 2 uruchamia własny kod JavaScript strony wewnątrz izolowanego procesu V8, czyli silnika JavaScript bez otoczki przeglądarki. Dokumentacja README wskazuje, że kod strony nie otrzymuje tam żadnych powiązań z możliwościami hosta. Obejmuje to wiele aplikacji typu single-page przy ułamku zużycia pamięci przeglądarki. Gdy Draco napotyka przeszkodę, której nie może pokonać, draco scrape kończy działanie z kodem 3, needs_browser. Należy to sprawdzać w skryptach, ponieważ pusty plik z kodem wyjścia zero jest błędem, który po cichu zatruwa kontekst agenta:
draco scrape https://example.com > page.md
echo "exit=$?"Usługa playwright-service w Firecrawl steruje rzeczywistym Chromium, więc renderuje to, co renderuje przeglądarka. Wersja self-hosted nadal nie jest produktem chmurowym: dokumentacja wskazuje, że instancje self-hosted nie mają dostępu do Fire Engine, więc brakuje mechanizmów antyblokujących i rotacji IP dostępnych w usłudze chmurowej, a punkty końcowe /agent oraz /browser nie są wspierane. Hound celowo znajduje się pomiędzy tymi rozwiązaniami. Pobiera dane przez HTTP i eskaluje działania w zależności od żądania, a jego rozgrzana przeglądarka zamyka się po przekroczeniu limitu czasu bezczynności, dzięki czemu cicha maszyna pozostaje blisko poziomu bazowego.
Instalacja Draco z przypiętą wersją
Plik README opisuje instalator jednowierszowy. Przed przekazaniem go do powłoki przez potok należy sprawdzić jego działanie: instaluje on oprogramowanie w $HOME/.draco/bin/draco, zawsze pobiera wydanie latest i nie weryfikuje podpisu ani sumy kontrolnej. Na serwerze należy przypiąć wersję i zweryfikować pobrany plik.
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 SHA256SUMSPolecenie to wypisuje draco-linux-x86-64.tar.gz: OK. Linia FAILED oznacza, że posiadane bajty nie są zgodne z tymi, które opublikował projekt, dlatego należy je usunąć i rozpocząć proces od nowa.
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.comOstatnie polecenie wyświetla przykładową stronę w formacie markdown w czasie znacznie krótszym niż sekunda. Ścieżka find nie jest przypadkowa: struktura archiwum nie stanowi części publicznego kontraktu projektu, a oficjalny instalator lokalizuje plik binarny w ten sam sposób.
Uruchom demona na dedykowanym koncie zamiast na użytkowniku, na którym jesteś zalogowany. Utwórz /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 odpowiada, gdy tylko demon nasłuchuje. Connection refused oznacza, że tak nie jest, więc należy przeczytać journalctl -u draco -n 50. Typową przyczyną jest inny proces zajmujący port 3002, ponieważ jest to również domyślny port Firecrawl, a --port pozwala zmienić port dla jednej z tych usług. Więcej informacji o plikach jednostek: jednostki usług i timery systemd.
Teraz pobierz dane w sposób, w jaki zrobi to Twój agent:
curl -X POST http://127.0.0.1:3002/v1/scrape \
-H 'content-type: application/json' \
-d '{"url": "https://example.com", "formats": ["markdown"]}'Ograniczenie dostępu do demona pobierania z sieci publicznej
Interfejs API służący do pobierania danych bez uwierzytelniania stanowi otwarte proxy. Każdy, kto uzyska dostęp do portu, może wymusić na serwerze żądanie dowolnego adresu URL z wykorzystaniem adresu IP serwera, co skutkuje otrzymywaniem zgłoszeń o nadużyciach przez dostawcę usług. Dokumentacja flag serve dla Draco nie przewiduje klucza API, dlatego zabezpieczenie musi zostać zrealizowane na poziomie sieci. Należy zachować domyślne powiązanie 127.0.0.1, jeśli agent działa na tej samej maszynie. Gdy agent znajduje się w innej lokalizacji, oba końce połączenia należy umieścić w prywatnym tunelu; standardowym rozwiązaniem jest samodzielnie hostowana sieć WireGuard VPN, a powiązanie powinno wskazywać adres tunelu, a nie 0.0.0.0. Następnie należy sprawdzić z innej maszyny, czy publiczny adres IP nie odpowiada na zapytania. Zagadnienia te obejmują podstawy zapory sieciowej ufw oraz konta użytkowników z minimalnymi uprawnieniami.
Czy kod agenta ulegnie zmianie? Kompatybilność API w praktyce
Draco obsługuje ścieżki Firecrawl v1: /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape oraz /v1/search, a dokumentacja README wskazuje, że nieznane pola są akceptowane i ignorowane. Agent, który wysyła żądania do /v1/scrape, wymaga jedynie zmiany bazowego adresu URL. Należy monitorować zmiany po stronie serwera: własna strona Firecrawl dotycząca self-hostingu testuje teraz rozwiązanie z /v2/crawl, a bieżące zestawy SDK korzystają z wersji v2. Klient v2 skierowany na Draco wywoła ścieżkę, której Draco nie udostępnia. Przed edycją kodu agenta należy przetestować każde wywołanie za pomocą curl oraz analizować treść JSON zamiast kodu statusu, ponieważ to w nazwach pól najczęściej występują rozbieżności między implementacjami.
Robots.txt, limity szybkości i granice przyzwoitości
Draco domyślnie odczytuje robots.txt, a --ignore-robots wyłącza to zachowanie. Dokumentacja Firecrawl wskazuje na te same ustawienia domyślne. Należy pozostawić je bez zmian. Następnie należy określić własne tempo pracy: --delay definiuje liczbę milisekund między żądaniami, a --max-concurrency ogranicza liczbę zadań równoległych, przy czym wartość 8 jest domyślna dla demona. Ustawienie od 2 do 4 jest bezpieczniejsze dla współdzielonego łącza VPS i rzadko skutkuje wolniejszym działaniem, ponieważ witryna, która zaczyna nakładać limity szybkości, generuje większe opóźnienia niż zysk z równoległości. Pobierane dane należy buforować, aby kolejne uruchomienie agenta nie obciążało źródła. Jest to również najtańszy element w kontrolowaniu kosztów agenta AI.
Zapory typu challenge wall to odrębne zagadnienie, a Trawl został stworzony właśnie do ich obsługi: Cloudflare Turnstile, reCAPTCHA, hCaptcha oraz GeeTest. Zapora typu challenge wall oznacza, że witryna wprost odmawia obsługi zautomatyzowanego ruchu. Próby obejścia tych zabezpieczeń naruszają warunki użytkowania witryny, a w niektórych jurysdykcjach są niezgodne z prawem, dlatego niniejszy przewodnik ogranicza się wyłącznie do infrastruktury pobierającej dane. Techniki pozwalające na przejście przez zaporę są jednocześnie tymi, które właściciele witryn monitorują i blokują, co czyni każdy potok danych oparty na takich metodach zarówno kruchym, jak i nieetycznym. Jeśli dane źródło jest istotne, należy poszukać jego kanału RSS, publicznego API lub eksportu zbiorczego. Każde z tych rozwiązań jest tańsze w utrzymaniu i żadne z nich nie przestanie działać w momencie zmiany konfiguracji zapory.
Podłączanie do agenta przez MCP
MCP (model context protocol) to interfejs, którego agent używa do wywoływania narzędzi. Draco zawiera serwer MCP w tym samym pliku binarnym, działający przez stdio:
{ "mcpServers": { "draco": { "command": "draco", "args": ["mcp"] } } }Narzędzia są następnie widoczne dla agenta jako draco_scrape, draco_search oraz zestaw draco_interact_*. Stdio działa tylko wtedy, gdy proces agenta i plik binarny znajdują się na tej samej maszynie, ponieważ transportem jest standardowe wejście tego procesu. W przypadku agenta na innym hoście, Hound udostępnia MCP przez HTTP: hound --http --host 127.0.0.1 --port 8765 publikuje punkt końcowy pod adresem http://127.0.0.1:8765/mcp, do którego uzyskuje się dostęp przez tunel. Wybór transportu oraz zakres udostępnianych zasobów opisano w uruchamianiu serwerów MCP na VPS.
Pobieranie par za pomocą wyszukiwania. Agent, który potrafi tylko pobierać, oczekuje na dostarczenie adresów URL. Dodaj własną instancję wyszukiwarki SearXNG, aby umożliwić mu samodzielne znajdowanie zasobów; działa to w ten sam sposób, co umiejętność wyszukiwania w przeglądarce oparta na SearXNG. Gdy demon jest uruchomiony, stanowi współdzieloną usługę dla dowolnego z hostowanych samodzielnie agentów AI, których używasz.
FAQ
Czy do pobierania stron dla agenta AI potrzebna jest przeglądarka typu headless?
W przypadku większości stron nie. Dokumentacja renderowana po stronie serwera, blogi oraz artykuły informacyjne są zwracane w całości po zwykłym pobraniu HTTP i konwersji HTML do formatu markdown. Jest to metoda stosowana przez Draco w niższych warstwach, co według danych projektu pozwala uzyskać czas rzędu 300 ms na stronę bez użycia przeglądarki. Przeglądarka jest niezbędna w przypadku aplikacji renderowanych po stronie klienta, gdzie dostarczony kod HTML jest pustą powłoką. Izolacja V8 w Draco obsługuje większość takich przypadków bez uruchamiania procesu przeglądarki, a w razie niepowodzenia kończy działanie z kodem 3, needs_browser.
Ile pamięci RAM wymaga samodzielnie hostowany Firecrawl na serwerze VPS?
Plik compose ustala limit 8 GB dla kontenera api oraz 4 GB dla kontenera Playwright. Ten sam stos uruchamia również Redis, RabbitMQ, PostgreSQL oraz FoundationDB. Należy zaplanować 8 GB pamięci RAM. Na maszynie z 2 GB pamięci mechanizm kernel out-of-memory killer usuwa kontenery pod obciążeniem. Pierwszym objawem jest restart kontenera w docker compose ps bez użytecznych informacji w dzienniku aplikacji, co można potwierdzić za pomocą dmesg -T | tail.
Czy Draco jest bezpośrednim zamiennikiem API Firecrawl?
W przypadku endpointów v1 jest to rozwiązanie zbliżone. Obsługuje /v1/scrape, /v1/map, /v1/crawl, /v1/batch/scrape oraz /v1/search i ignoruje nieznane pola żądań, więc klient napisany dla Firecrawl v1 zazwyczaj wymaga jedynie zmiany bazowego adresu URL. Nie jest to produkt hostowany: w tle nie działa zarządzana pula proxy, a nowsze trasy v2 z Firecrawl nie są częścią interfejsu. Każde wywołanie wykonywane przez agenta należy najpierw zweryfikować za pomocą curl.
Czy samodzielne hostowanie scrapera oznacza, że można ignorować plik robots.txt?
Nie. Miejsce uruchomienia kodu nie zmienia zasad publikacji treści ani warunków korzystania z serwisu. Zarówno Draco, jak i Firecrawl domyślnie respektują robots.txt, a flaga nadpisująca istnieje z myślą o stronach własnych lub takich, na których indeksowanie uzyskano pisemną zgodę. Limity częstotliwości zapytań są egzekwowane przez serwery docelowe, dlatego uprzejme --delay przy niskiej współbieżności pozwala zachować sprawność adresu IP. Stos technologiczny, który działa wyłącznie dzięki omijaniu zabezpieczeń, jest rozwiązaniem, które przestanie działać bez ostrzeżenia.