Web page readers for local LLMs: Trafilatura vs Crawl4AI vs Firecrawl vs a Chromium farm — article mark

Web page readers for local LLMs: Trafilatura vs Crawl4AI vs Firecrawl vs a Chromium farm

A page reader (scraper) turns a URL into text an LLM can read. Measured on three robertz.co pages: U1 the homepage (a listing), U2 a long article, U3 a long post. Contender 5: chromium MCP fetch — headless Chromium render → Trafilatura → JSON envelope, 7-day shared cache.

Series — web scrapers for local LLMs: Overview · Readers compared · Token cost per page · Extraction quality · Output formats · Previous stage: Web search for local LLMs

Tokens per article page, by reader and config

Mean tokens per robertz.co article page (U2 and U3) — every reader lands between 4,728 and 5,877 tokens, chromium fetch adds a 573-token JSON envelope to 4,757 tokens of content, raw HTML is 16,979 Mean tokens / article page (robertz.co U2 + U3) no browser browser reader raw HTML JSON envelope Trafilatura chromium fetch (browser) readability-lxml Firecrawl onlyMainContent Crawl4AI fit_markdown Firecrawl raw Crawl4AI raw_markdown raw HTML (for scale) 4,728 4,757 + 573 = 5,330 4,947 5,544 5,609 5,697 5,877 16,979 Every reader cuts raw HTML ~3–3.6×; leanest to heaviest reader is +24% (4,728 → 5,877). The win is "not HTML", not which reader. chromium fetch: content ≈ Trafilatura, the envelope is extra.
Mean of U2 (auth article) and U3 (broker_parrot post). chromium fetch from a separate run (N=3, cache bypassed). Run locally on my fleet.

The comparison

Reader · configU1 homepageU2U3mean U2+U3config knobbrowserlicensedeploy weight
raw HTML29,55216,01017,94716,979————
Trafilatura 2.0.060 ✗5,5273,9284,728precision, no links, keep tables✓ noApache-2.01 pip lib, ~42 ms/page
readability-lxml 0.8.4.151 ✗5,7464,1474,947—✓ noApache-2.01 pip lib, ~19 ms/page
Crawl4AI 0.9.4 raw_markdown1,7206,8004,9535,877default raw✗ yesApache-2.01 container + Chromium, ~650 ms/page
Crawl4AI fit_markdown1,2696,5904,6285,609PruningContentFilter 0.48✗ yesApache-2.0—
Firecrawl (self-host) onlyMainContent:true1,4796,3644,7245,544default✗ yesAGPL-3.05 containers, ~4.3 GB images, ~7.5 min to healthy, ~940 ms/page
Firecrawl onlyMainContent:false1,7586,5194,8745,697full page✗ yesAGPL-3.0—
chromium MCP fetch mode=browser ‡405 (+300)5,527 (+549)3,986 (+597)4,757 (+573) = 5,330extract=text, max_age✗ yes—browser farm + shared cache, 5.4–8.3 s/page cold, 2–3 ms hit
Camoufox 0.5.8 → Trafilatura §1205,5273,9284,728headless="virtual", humanize✗ yesMIT (pip pkg)1 pip lib + Firefox build + Xvfb, 0.75–0.89 s/page; passed Cloudflare
nodriver 0.50.6 → Trafilatura §1205,5273,9284,728headless=False (Xvfb)✗ yesAGPL-3.01 pip lib + Chrome + Xvfb, 0.62–0.84 s/page; passed Cloudflare

↔ scroll sideways for every column. ✗ on U1 = the reader kept almost nothing (see below). ‡ separate run, N=3 medians; (+n) = JSON envelope tokens the model also reads. § stealth browser, separate run, N=3 medians, Trafilatura on the rendered DOM (rendered HTML 17.9k tok/article). Optional stack: Trafilatura → LLMLingua-2 @0.33 on U2: 16,010 → 5,527 → 1,709 tok (~9.4× total; MIT; +~8.8 s CPU).

Same run: browser farm vs controls

N=3, median ms · tokU1 homepageU2U3
chromium fetch mode=browser, cold8,293 ms · 7055,427 ms · 6,0766,671 ms · 4,583
chromium fetch, cache hit2 ms · 7053 ms · 6,0762 ms · 4,583
Trafilatura direct (fetch + extract)236 ms · 30229 ms · 5,710242 ms · 4,000
Crawl4AI raw_markdown372 ms · 1,840442 ms · 6,800467 ms · 4,953
Crawl4AI fit_markdown410 ms · 1,389396 ms · 6,590377 ms · 4,628
chromium fetch mode=http / mode=auto0/18 ok——

chromium tok = whole envelope. Cold medians = ~12–22× Crawl4AI, ~24–35× Trafilatura direct (single calls 4.9–9.0 s). mode=http/auto: http path broken at measurement time — not scored. Raw HTML this run: U1 31,159 tok (homepage grew), U2 16,010, U3 17,947.

The config knob, on a lean site

knobU1 homepageU2U3
Crawl4AI raw → fit_markdown−26%−3%−7%
Firecrawl onlyMainContent false → true−16%−2%−3%

Prior run (different pages, same day): on boilerplate-heavy third-party pages the same knobs cut −45…−89% (Crawl4AI) / −22…−69% (Firecrawl). The knob matters on bloated pages, not on lean ones.

Listing pages: main-content readers collapse

U1 homepagetokenskept
Trafilatura60the hosting blurb, printed twice
readability-lxml51the name, tagline and email
Firecrawl onlyMainContent1,479the listing
Crawl4AI fit_markdown1,269the listing
Crawl4AI raw_markdown1,720the listing
chromium fetch ‡405headline + 5 article links (rendered DOM → Trafilatura); Trafilatura direct same run: 30

Main-content readers are for articles, not index pages.

Extraction quality

Trafilatura 0.84 F1 (independent WCXB), readability 0.74; same 181 ScrapingHub pages run locally: Trafilatura 0.955, readability 0.922, Crawl4AI fit 0.790, Firecrawl main content 0.785; all four fail a Cloudflare JS challenge, Camoufox and nodriver pass it → Extraction quality.

Verdict

Questions? Let's Chat :)

ai llm engineering