Prawie każde zestawienie „najlepszych open-source’owych scraperów” ma jedną cichą wadę: nikt nie uruchamia tych narzędzi na tych samych stronach. Scrapy testuje się na artykule newsowym, Playwright na jakimś e-commerce demo, Colly na czymś, co autor akurat miał pod ręką — a potem porównuje się je łeb w łeb, jakby te liczby w ogóle oznaczały to samo. Taki ranking mówi więcej o stronach niż o samych narzędziach.
Więc zrobiłem tę nudną, oczywistą rzecz, której zwykle brakuje w takich listach. Zbudowałem jeden zestaw fixture’ów i przepchnąłem przez niego wszystkie dziewięć narzędzi: statyczny katalog, katalog renderowany przez JavaScript, artykuł ukryty w nawigacji i śmieciach z footera, celowo uszkodzony błąd HTTP 500, mały graf linków wewnętrznych oraz dwie publiczne strony do ćwiczeń. Te same dane źródłowe, te same metryki, każdy pojedynczy test. Skrypty i surowe wyniki są w jednym publicznym repozytorium benchmarkowym, więc możesz samodzielnie odtworzyć dowolny wynik. To, co z tego wyszło, nie przypomina eleganckiej tabeli liderów obiecanej przez roundup’y — nie ma jednego zwycięzcy. Są trzy różne zadania, a dziewięć narzędzi niemal samoistnie układa się w te grupy.
Wypróbuj Thunderbit do ekstrakcji danych z sieci
Jak działał benchmark i jedyne ograniczenie, które powiem głośno

Każde narzędzie dostało te same typy fixture’ów: 12 statycznych produktów rozłożonych na dwóch stronach, 8 produktów wstrzykiwanych przez JavaScript po opóźnieniu, artykuł otoczony nawigacją i footerm, z trzema prawdziwymi akapitami, celowy serwerowy błąd 500 oraz graf linków wewnętrznych. To właśnie taki układ sprawia, że wyniki da się porównać — „8/8 dynamicznych produktów” oznacza dokładnie to samo, niezależnie od tego, czy wygenerował to Puppeteer, czy Crawlee.
Jest jednak granica, którą większość zestawień pomija. Każdy pakiet fixture’ów odpowiada własnej kopii tych samych testów, więc bezwzględne liczby znaków nie są ścisłe porównywalne między narzędziami — czytaj je jako sygnał wewnątrz jednego narzędzia, nigdy jako wynik cross-tool. To, co naprawdę da się porównywać, to recall (traktuj go jak wskaźnik skuteczności), zaliczenie JavaScriptu oraz zachowanie strukturalne. Jedna uwaga w tym samym duchu: w przypadku Crawl4AI test statycznego katalogu obejmował tylko pierwszą stronę, więc jego 6/6 to pełny recall na węższym wycinku, podczas gdy pozostałe narzędzia crawlowaly obie strony dla 12/12 — mniejszy zakres, nie częściowe nietrafienie. Pełne uzasadnienie, fixture po fixture, znajdziesz w opisie metodologii.
Jeszcze jedno zastrzeżenie przed liczbami. Każdy pakiet zawiera też tymczasowy wynik badawczy, ale celowo nie pokazuję go w formie tabeli rankingowej. To były wewnętrzne narzędzia pomocnicze do sprawdzania każdego projektu na tle jego własnych dowodów, a nie liga wyników — publikowanie ich jako jednego rankingu odtworzyłoby dokładnie ten problem fałszywej precyzji, którego cały ten eksperyment ma unikać. To synteza tego, co pokazał benchmark, a nie tabela punktów.
Całe pole w jednym benchmarku
Spójrz po dwóch kolumnach tej tabeli — „Renders JS?” i „Built-in crawl queue” — a trzy zadania praktycznie same się ujawnią.
| Tool | Language | Renders JS? | Static recall | Structured output | Built-in crawl queue | Setup weight | License |
|---|---|---|---|---|---|---|---|
| Crawl4AI | Python | Yes (browser) | 6/6 (page 1) | CSS schema | BFS/DFS built-in | Heavy (2 browser stacks) | Apache-2.0 |
| Firecrawl | Self-hosted | Yes (playwright-service) | Full Markdown | Yes | /v1/crawl | Heaviest (6 containers) | AGPL-3.0 |
| trafilatura | Python | No | 3/3 article | No (text only) | No | Light | Apache-2.0 |
| Crawlee | Node/TS | Engine-optional | 12/12 | Via extraction | Yes (RequestQueue) | Medium (+~80 MiB) | Apache-2.0 |
| Playwright | Node/multi | Yes | 12/12 | Manual | No (hand-written BFS) | Medium (browser) | Apache-2.0 |
| Puppeteer | Node | Yes (Chrome) | 12/12 | Manual | No (hand-written BFS) | Medium (Chrome) | Apache-2.0 |
| Scrapy | Python | No | 12/12 | Feed export (JSON/CSV/XML) | Yes (built-in) | Medium (Twisted deps) | BSD-3 |
| Colly | Go | No | 12/12 | Via callbacks | Depth control | Light (1 binary + Go) | Apache-2.0 |
| Scrapling | Python | No (HTTP fetcher) | 12/12 | Yes | No | Medium ([fetchers]) | BSD-3 |

Uwaga do metadanych w tej tabeli i wszędzie poniżej: liczby gwiazdek i wersje zostały zrzutowane na początku lipca 2026 i obie rzeczy szybko się zmieniają. Przed uznaniem czegokolwiek za aktualne sprawdź to ponownie na GitHubie i stronie pakietu danego projektu.
Indeks recenzji dla pojedynczych narzędzi
Każdy projekt w tym zestawieniu ma odpowiadającą mu szczegółową recenzję:
- Recenzja Crawl4AI
- Recenzja Firecrawl
- Recenzja trafilatura
- Porównanie Playwright vs Puppeteer
- Recenzja Crawlee
- Recenzja Scrapy
- Recenzja Colly
- Recenzja Scrapling
Oto ich okładki — plus dwa prawdziwe zrzuty ekranu z testu renderowania JavaScriptu, żeby twierdzenie o „8/8 dynamicznych” nie było tylko liczbą na stronie.










Zadanie pierwsze: zamienić stronę w tekst gotowy dla LLM

Jeśli chcesz czystego Markdowna do zasilenia pipeline’u RAG, konkurują tu trzy narzędzia — i każde jest zbudowane zupełnie inaczej.
Crawl4AI pod marketingową warstwą jest generatorem Markdowna opartym na przeglądarce. Warto od razu zdjąć z niego historię o „adaptive intelligence self-learning selector”, która krąży po wynikach wyszukiwania: czegoś takiego tam nie ma — to trik innej biblioteki (wrócę do tego przy Scrapling). To, co naprawdę robi, robi dobrze. Na stronie testowej Books to Scrape wygenerował 13 476 znaków Markdowna, obsługuje ekstrakcję CSS schema do pobierania strukturalnego i ma wbudowany BFS deep crawl, który przeszedł przez 5 stron w fixture’ze grafu crawlowania, równocześnie renderując stronę JavaScriptową i zapisując zrzut ekranu. Są jednak dwa konkretne minusy. Surowy Markdown niesie boilerplate strony, jeśli nie włączysz filtra treści, a celowy błąd 500 wrócił jako success=false — nie dlatego, że Crawl4AI elegancko złapał błąd HTTP, tylko dlatego, że jego własna heurystyka treści spojrzała na małe ciało błędu i oznaczyła je jako minimal_text ... blocked. Do tego instalacja dorzuca na dysk dwa stosy przeglądarkowe. Wersja 0.9.0, Apache-2.0, około 71 tys. gwiazdek na początku lipca.
Firecrawl jest tu ciężkim zawodnikiem i self-hosting naprawdę działa — mówię „naprawdę”, bo sześciokontenerowy stack (api, playwright-service, redis, rabbitmq, nuq-postgres i foundationdb) faktycznie wystartował i wygenerował 9 222 znaki Markdowna gotowego dla LLM z tej samej strony Books to Scrape. Renderował stronę JavaScriptową przez dołączony playwright-service, a po skrypcie cytat Einsteina pojawił się w wyniku, co potwierdziło, że render był rzeczywiście wykonany. Dwa problemy, na które trafiłem, wynikały ze środowiska, nie z Firecrawl, i chcę to powiedzieć precyzyjnie, żeby nikt nie kopiował złego fixa: build z kodu źródłowego potknął się o błąd snapshottera containerd w colima (przełączyłem się na gotowe obrazy), a zakres DNS 198.18.x.x w colima uruchomił zabezpieczenie SSRF w Firecrawl, które obejrzałem przez ALLOW_LOCAL_WEBHOOKS=true — to obejście do lokalnego developmentu, nie coś do wyłączania w prawdziwym wdrożeniu. Sam rdzeń self-hosted nie ma też Fire-engine, czyli chmurowej warstwy antyblokad, a API chmurowego nie testowałem. Ważniejszy sygnał to licencja: self-hosted core Firecrawl jest na AGPL-3.0, co wymaga realnego sprawdzenia prawnego przed jakimkolwiek komercyjnym użyciem, a nie tylko wzmianki na marginesie. Około 148 tys. gwiazdek na początku lipca.
trafilatura jest w tej grupie kontrarianem i tym, o którym listy napędzane hype’em AI ciągle zapominają. Bez przeglądarki. Bez struktur wierszy. Po prostu szybki, czysty tekst artykułu w czystym Pythonie. Na fixture’ze artykułu pobrał tytuł oraz wszystkie 3 z 3 prawdziwych akapitów, całkowicie usuwając boilerplate — żadnych przecieków typu „Login”, „Subscribe” czy „Copyright” — i dodatkowo odzyskał autora oraz datę. Na publicznej stronie produktowej zwrócił 1 324 znaki czystego tekstu. Jego ograniczenie dokładnie wynika z konstrukcji: skieruj go na katalog, a odda 12 nazw produktów jako tekst, ale 0 wierszy strukturalnych — tekst jest, struktury nie ma, a JavaScriptu nie renderuje. Wersja 2.1.0 (aktualne wydanie), Apache-2.0, około 6,2 tys. gwiazdek. Do czystej ekstrakcji artykułów to byłoby moje pierwsze narzędzie.
Te dwie liczby znaków Markdowna — 13 476 z Crawl4AI i 9 222 z Firecrawl — pochodzą z tej samej publicznej strony, ale nie czytaj ich jako różnicy jakości. Pokazują różne strategie Markdowna (ile elementów strony każde narzędzie zachowuje), a nie werdykt, który wynik jest lepszy. To właśnie ta wcześniejsza zasada sygnału wewnątrz narzędzia w praktyce.
Zadanie drugie: niezawodnie renderować JavaScript

Niektóre dane po prostu nie istnieją w HTML-u, dopóki nie uruchomią się skrypty, i wtedy prawdziwa przeglądarka przestaje być opcjonalna. Trzy narzędzia obsługują to zadanie — a dwa z nich okazały się niemal tym samym narzędziem.
Playwright i Puppeteer zremisowały we wszystkich testach, jakie im rzuciłem. Oba wyrenderowały 8/8 dynamicznych produktów w lokalnym fixture’ze i 10 na publicznej stronie Quotes JS, oba osiągnęły 12/12 statycznego recallu i oba poradziły sobie z błędem 500 bez problemu (Puppeteer zwraca obiekt odpowiedzi zamiast rzucać wyjątek). Żadne z nich nie ma własnej kolejki crawl, więc oba potrzebowały ręcznie napisanej BFS, która doszła do 12 stron na głębokości 0–2 w grafie crawlowania. Jedyna realna różnica to zasięg: Playwright obsługuje Chromium, Firefox i WebKit oraz mówi po Pythonie i .NET, a Puppeteer jest nastawiony na Chrome i działa tylko w Node. Dwa doprecyzowania, bo wersje w tym obszarze szybko się zmieniają: testowałem Playwright 1.56.0 względem aktualnej 1.61.1 i używałem wyłącznie Chromium; Puppeteer 24.16.0 względem aktualnej 25.3.0 — więc w razie potrzeby przetestuj ponownie albo uwzględnij tę różnicę. Oba są na Apache-2.0; około 92 tys. i 95 tys. gwiazdek odpowiednio.
Crawlee rozwiązuje problem kolejki, którego tamte dwa nie domykają. Oplata silnik Cheerio (HTTP) i silnik Playwright (browser) jedną API, a kontrast na jednej stronie to cała jego wartość: silnik Cheerio nie zobaczył 0 elementów wstrzykniętych przez JavaScript, silnik Playwright zobaczył wszystkie 8/8 lokalnie (i 10 na publicznej stronie), a przełączanie między nimi to zmiana jednej linijki. Dostajesz też prawdziwy RequestQueue, dzięki czemu narzędzie trafia do tego zadania, a nie do trzeciego. Haczyk, którego nikt nie wpisuje w nagłówek: silnik browser wymaga osobnego npx playwright install, czyli około 80 MiB, których npm install crawlee nie pobiera automatycznie. Wersja 3.17.0, TypeScript, Apache-2.0, około 24,6 tys. gwiazdek.
Zadanie trzecie: szybko crawlować bez przeglądarki
Brak JavaScriptu na stronie oznacza, że przeglądarka byłaby kosztownym przerostem formy nad treścią. W tym obszarze konkurują trzy narzędzia HTTP-first, po jednym na każdą filozofię językową, i ciekawie się między sobą różnią.
Scrapy to najbardziej inżynierski framework z całej piątki — spider’y, eksport feedów do JSON/CSV/XML, AutoThrottle i cały zestaw. Osiągnął 12/12 statycznego recallu, pobrał 3/3 akapitów artykułu, przeszedł przez 11 stron na głębokości 0–2 w grafie crawlowania i złapał błąd 500 przez handle_httpstatus_list. Najciekawsze jest jego podejście: nie renderuje, tylko odtwarza request. Rzucony na stronę JavaScriptową dostał 0 węzłów — a potem API JSON siedzące za tą samą stroną oddało mu 8/8. To filozofia Scrapy w jednym punkcie danych: znajdź request, który wykonuje strona, i go odtwórz, nie prowadź przeglądarki. Cena to spory stos zależności (Twisted, lxml, parsel), a testowałem go tylko na małych fixture’ach. Wersja 2.17.0, BSD-3-Clause, około 63 tys. gwiazdek.
Colly to odpowiedź świata Go i bardzo literalnie mówi, czym jest: jeden binarny plik, obsługa callbacków przez OnHTML, OnResponse i OnError oraz kontrola głębokości. Trafił w 12/12 statycznego recallu, pobrał 8/8 z JSON API przez OnResponse, złapał 500 przez OnError i doszedł do 17 stron przy crawlu o głębokości 2 — i celowo formułuję to właśnie w ten sposób, bo ta liczba stron pochodzi z licznika harnessu, a nie z gwarancji pełności ze strony Colly. Tego, czego nie robi, to JavaScript: fixture dynamiczny i strona Quotes JS wróciły z 0, zgodnie z założeniem. Do kompilacji potrzebujesz toolchaina Go, a wersja modułu (v2.3.0) wyprzedza obecne tagged release (v2.2.0). Apache-2.0, około 25 tys. gwiazdek.
Scrapling to specjalista i naprawdę zasługuje na tę etykietę. Jego adaptacyjne selektory są stworzone po to, by ponownie odnaleźć element po zmianie markup’u — więc kiedy zmieniłem klasę HTML celu z product-name na product-title, zwykły selektor dał 0, a adaptacyjne ponowne dopasowanie i tak odzyskało śledzony element. W zwykłej ekstrakcji HTTP trafił w 12/12 statycznych i 8/8 w JSON API. Czego nie ukrywają nawet jego własne dokumenty: w syntetycznym teście wieloelementowym odzyskał 1 z 3 — to odporne śledzenie elementu, nie pełne odzyskiwanie, więc nie należy tego wyolbrzymiać. Podstawowe pip install scrapling wymaga też dodatkowego [fetchers], żeby w ogóle ruszyć, a StealthyFetcher to raczej zastrzeżenie compliance niż funkcja, którą pokazywałbym na slajdzie. Wersja 0.4.10 (aktualne wydanie), BSD-3-Clause, około 68,7 tys. gwiazdek.
Wzorzec ukryty pod trzema zadaniami
Ustawienie tych dziewięciu narzędzi obok siebie pokazuje coś bardzo czystego. Pełny statyczny recall — płaskie 12/12 — to po prostu minimum dla każdego narzędzia HTTP-first; żadne z nich nie zawaliło łatwego przypadku, więc nie jest to cecha różnicująca. Narzędzia przeglądarkowe uzasadniają swój większy ciężar tylko wtedy, gdy JavaScript naprawdę wchodzi do gry, i wszystkie płacą za to w setupie: stos przeglądarkowy, dodatkowa instalacja albo cała flota kontenerów. A kolumna „built-in crawl queue” to w praktyce granica między frameworkiem a silnikiem — Scrapy i Crawlee dają orkiestrację, a Playwright i Puppeteer każą pisać BFS samemu. Taki jest kształt tego rynku. Nikt nie wygrywa globalnie, bo nikt nie gra w tę samą grę.
Więc co właściwie wybrać
Benchmark nie chce koronować zwycięzcy, bo właściwa odpowiedź nie brzmi „które narzędzie?”, tylko „które z trzech zadań wykonujesz?”
- Potrzebujesz Markdowna gotowego dla LLM? Sięgnij po trafilatura, jeśli chcesz czysty tekst artykułu, po Crawl4AI, jeśli oprócz tego potrzebujesz ekstrakcji CSS i renderowania JavaScriptu w jednej bibliotece, oraz po Firecrawl, jeśli zależy Ci konkretnie na self-hosted service i możesz zaakceptować zarówno licencję AGPL-3.0, jak i ciężar sześciu kontenerów.
- Potrzebujesz renderowania JavaScriptu? Wybierz Playwright albo Puppeteer do czystego renderowania — zdecyduj na podstawie silnika i języka, bo poza tym mamy remis — a Crawlee, gdy chcesz też dostać orkiestrację crawla zamiast pisać ją ręcznie.
- Crawl statycznych stron albo powtarzalnych API na dużą skalę? Scrapy, jeśli chcesz pełny framework w Pythonie; Colly, jeśli zależy Ci na surowej prędkości Go w jednym binarnym pliku; Scrapling, jeśli Twoim konkretnym, powracającym problemem jest odporność na zmiany markup’u.
Dopasuj narzędzie do zadania, a każde z nich będzie sensownym wyborem. Weź coś z niewłaściwej kategorii — narzędzie przeglądarkowe do stron statycznych albo parser HTTP do aplikacji JavaScriptowej — a nawet najlepiej oceniana biblioteka w internecie Cię zawiedzie.
Gdzie zamiast tego pasuje zarządzane API AI

Każde z powyższych narzędzi jest darmowe, open-source i możesz je uruchamiać samodzielnie. To też wspólny kompromis, który ten benchmark ciągle pokazuje: to Ty odpowiadasz za środowisko przeglądarki, kod crawla, wyścig z anty-botami i całą konserwację. Dla wielu zespołów właśnie ta kontrola jest celem samym w sobie, a mapa licencji ma znaczenie, gdy się na to decydujesz — większość pola jest liberalna (Apache-2.0 w Crawl4AI, Crawlee, Playwright, Puppeteer i Colly; BSD-3 w Scrapy i Scrapling), a self-hosted core Firecrawl na AGPL-3.0 to jedyny przypadek, który naprawdę wymaga analizy przed użyciem komercyjnym.
Ale zwróć uwagę, co jeszcze pokazał benchmark: czego te narzędzia nie robią. Renderowanie, crawl, strukturyzowanie i obchodzenie blokad — rzadko wszystko naraz, a już na pewno nie bez Twojej konserwacji. Zarządzane API do AI scraping’u zamyka ten stos w jednym wywołaniu. Nasz własny interfejs deweloperski w Thunderbit jest jedną z takich opcji, a dla technicznej publiczności liczą się API, serwer MCP i CLI, a nie rozszerzenie do przeglądarki. POST /distill zwraca czysty Markdown, a POST /extract zwraca JSON zgodny ze schematem, przy czym renderowanie JavaScriptu i anty-bot są obsługiwane po stronie serwera, nie na Twoim komputerze. Jest też oficjalny serwer MCP dla agentów i asystentów programistycznych — thunderbit_suggest_fields działa za darmo i pomaga zaplanować ekstrakcję, potem thunderbit_distill (1 credit) i thunderbit_extract (20 credits) wykonują pracę — oraz CLI, które możesz dodać przez npx @thunderbit/thunderbit-cli do terminala i zadań cron. Dla osób nietechnicznych w zespole jest też no-code’owe rozszerzenie Chrome, a cennik obejmuje oba scenariusze.
Kompromis jest ten sam, wokół którego krąży cały ten benchmark: możesz uruchamiać i utrzymywać do dziewięciu bibliotek samodzielnie za zerowy koszt per request albo oddać warstwę infrastrukturalną i płacić za każde wywołanie. Żaden z tych wyborów nie jest zły. Wszystko sprowadza się do tego, ile warstwy stosu naprawdę chcesz posiadać. Jeśli wolisz zobaczyć, jak to wygląda w praktyce, kanał Thunderbit na YouTube przeprowadza przez cały proces.
Werdykt
Nie istnieje jeden najlepszy open-source scraper, a każda lista, która z przekonaniem podaje Ci taki wybór, cicho ukrywa pytanie, które naprawdę decyduje o wyniku: które z trzech zadań wykonujesz? Zamiana strony w tekst, renderowanie JavaScriptu albo szybki crawl bez przeglądarki — rynek dzieli się dokładnie na te koszyki, a w każdym z nich wybór sprowadza się do języka i ciężaru konfiguracji, nie do jakiegoś uniwersalnego mistrza.
Jeśli masz wynieść z tego jedną praktykę, niech będzie taka: testuj na własnych stronach, zanim się na cokolwiek zdecydujesz. Każda liczba tutaj jest odtwarzalna w repozytorium benchmarkowym właśnie z tego powodu — bo narzędzie, które wygrywa w ogólnym zestawieniu, i narzędzie, które przeżywa Twoje realne cele, nie zawsze są tym samym.
Wypróbuj Thunderbit do ekstrakcji danych z sieci Get Started Free
FAQ
Jaki jest najlepszy open-source web scraper? Nie ma jednego najlepszego — to zależy od zadania. Do tekstu gotowego dla LLM: trafilatura albo Crawl4AI; do renderowania JavaScriptu: Playwright, Puppeteer albo Crawlee; do szybkiego crawlowania HTTP: Scrapy albo Colly. W testach na wspólnej ławce każde narzędzie było najmocniejsze w swojej kategorii i wyraźnie słabsze poza nią, dlatego rankingi „jeden rozmiar dla wszystkich” wprowadzają w błąd.
Które open-source’owe scrapery renderują JavaScript? Crawl4AI, Firecrawl, Playwright, Puppeteer oraz silnik Playwright w Crawlee renderują JavaScript. Scrapy, Colly, trafilatura i domyślny HTTP fetcher w Scrapling tego nie robią — potrzebują albo odtwarzalnego API za stroną (tak jak Scrapy, które pobrało 8/8 z endpointu JSON), albo osobnego trybu przeglądarki.
Czy do scrapowania strony potrzebuję headless browsera? Tylko wtedy, gdy dane pojawiają się dopiero po uruchomieniu JavaScriptu. Jeśli zwykły request HTTP plus parser wystarczy do pobrania treści, przeglądarka będzie kosztownym przerostem formy nad treścią — w takim przypadku Scrapy, Colly albo Scrapling będą znacznie lżejsze i szybsze.
Które z tych narzędzi mają najprzyjaźniejszą licencję do użycia komercyjnego? Większość ma licencje liberalne: Apache-2.0 (Crawl4AI, Crawlee, Playwright, Puppeteer, Colly) albo BSD-3-Clause (Scrapy, Scrapling). Wyjątkiem jest self-hosted core Firecrawl, który ma AGPL-3.0 i wymaga poważnej analizy licencji przed zbudowaniem na nim produktu komercyjnego.
Czy te liczby z benchmarku są odtwarzalne? Tak. Każdy runner, fixture i surowy wynik znajduje się w publicznym repozytorium na licencji MIT. Jedno zastrzeżenie, o którym trzeba pamiętać: recall i wyniki strukturalne są porównywalne między narzędziami, ale bezwzględne liczby znaków są tylko sygnałem wewnątrz narzędzia, ponieważ każdy pakiet odzwierciedla fixture’y zamiast dzielić jedną kanoniczną kopię — porównuj więc wskaźniki i zaliczenie/niezaliczenie, a nie surową liczbę znaków.


