Public boards
WCXB (both splits), WCEB, Zyte article extraction, WebMainBench, CleanEval and DAnIEL — the numbers from a from-scratch run, who was run here beside the engine, and what each board cannot see.
Six public corpora, seven boards, every one re-run from a fresh clone on 21 September 2026
with the runners in benchmark/ — the morning at main@fcc2c9f
(docs/research/2026-09-21-benchmarks-from-scratch.md: every corpus revision, checksum,
command and log), the evening at 928cf84 after the page-type router change that the
morning's numbers demanded (2026-09-21-router-canonical-and-multilingual.md). The
figures below are the evening's. Two rules, both new this day:
- Only corpora that ship their own HTML. Every number here can be produced again by anyone with the clone. Firecrawl's scrape-evals, which fetches a thousand live URLs of which ninety are already gone, is out of the boards for that reason (it is listed under "not run" on the benchmarks page with the one figure it produced here).
- The engine's row is the production path: the page-type router, its per-type policy,
the content boundary and the title — what
stream_page, the API and the CLI run. Until this run the boards scored the boundary step alone and called it production. Both rows are shown; the headline is the shipped one.
Where a rival could be installed it was run here, with its defaults, through the corpus's own scorer over the same bytes — marked "run here". Other rows are their authors' published figures and say so.
What every board shares
Cached HTML, no network, one page per site. That switches off geometric reading order (every page falls back to DOM order; each runner prints the distribution) and cross-page chrome detection. What is measured is the single-page half of the engine.
What the morning run found, and what the evening changed
Off WCXB the shipped path was behind its own rules boundary — Zyte −0.015, CleanEval −1.0
word-F, WCEB −0.024, DAnIEL −0.218 — and the cause was the page-type router: it typed 987
of DAnIEL's 1,689 news articles as listings. Two things fixed most of it the same day.
The router now reads the URL block from the page's declared canonical rather than the
address it was fetched under (a DAnIEL page under its host root routed listing 118
times in a 200-page sample, 9 under an article-shaped path). And the router now trains
on five languages: DAnIEL's 711 canonical-URL pages joined WCXB dev, grouped folds,
class-weighted as before. DAnIEL 0.582 → 0.783; held out one language at a time, the
unseen language routes article 81–94% of the time (2% before). Cost: WCXB dev routed
out of fold 0.862 → 0.861, test 0.879 → 0.878. A prose-run guard was measured and
rejected (WCXB test −0.003 at every threshold).
Web Content Extraction Benchmark (Murrough Foley): 2,008 human-reviewed pages across
seven page types, the only public board that labels type. Metric: per-page word-level F1,
averaged. Protocol, exactly as the corpus README prescribes: each system writes
{file_id: text} and the corpus's own evaluate.py --results scores it
(benchmark/wcxb/run.py --out for the engine, benchmark/wcxb/baselines.py for the
rest). rs-trafilatura is the benchmark author's extractor, built from its PyPI sdist.
A corpus fact the README does not state: 139 pages are in both dev/html and
test/html, byte-identical (metadata.json calls them test). The official scorer counts
them in both splits, so these tables do too; the runner prints the disjoint subsets.
Dev split, 1,497 pages — the router trained here, so the engine's row uses its out-of-fold predictions:
| system | F1 | article | docs | service | forum | collection | listing | product |
|---|---|---|---|---|---|---|---|---|
| webgraph (routed, out of fold) | 0.861 | 0.945 | 0.921 | 0.845 | 0.787 | 0.692 | 0.718 | 0.634 |
| rs-trafilatura, published | 0.859 | 0.932 | 0.932 | 0.844 | 0.808 | 0.716 | 0.707 | 0.641 |
| rs-trafilatura 0.1.1, run here | 0.847 | 0.934 | 0.938 | 0.825 | 0.760 | 0.672 | 0.669 | 0.636 |
| MinerU-HTML, published | 0.827 | 0.928 | 0.838 | 0.824 | 0.794 | 0.506 | 0.710 | 0.619 |
| trafilatura 2.2.0, run here | 0.813 | 0.928 | 0.914 | 0.759 | 0.689 | 0.564 | 0.559 | 0.618 |
| resiliparse 1.0.9, run here | 0.771 | 0.858 | 0.898 | 0.780 | 0.713 | 0.536 | 0.575 | 0.530 |
| readability-lxml 0.9, run here | 0.696 | 0.887 | 0.805 | 0.543 | 0.455 | 0.382 | 0.291 | 0.432 |
| jusText 3.0.2, run here | 0.691 | 0.847 | 0.684 | 0.583 | 0.677 | 0.343 | 0.339 | 0.449 |
Without routing 0.837. First of the systems run here by 0.014; 0.002 over the author's
published figure, which the Python build does not reproduce (forcing its page_type= to
the annotated type gives 0.847 too). The morning's router scored 0.862 here; the evening's
trades 0.001 of it for the five languages.
Held-out test split, 511 pages — the production path with the shipped router:
| system | F1 | article | docs | service | forum | collection | listing | product |
|---|---|---|---|---|---|---|---|---|
| rs-trafilatura 0.1.1, run here | 0.891 | 0.951 | 0.973 | 0.832 | 0.836 | 0.775 | 0.748 | 0.777 |
| webgraph (production) | 0.878 | 0.942 | 0.952 | 0.833 | 0.850 | 0.729 | 0.689 | 0.781 |
| trafilatura 2.2.0, run here | 0.858 | 0.937 | 0.931 | 0.817 | 0.767 | 0.628 | 0.746 | 0.721 |
| resiliparse 1.0.9, run here | 0.791 | 0.815 | 0.953 | 0.826 | 0.773 | 0.586 | 0.669 | 0.712 |
| readability-lxml 0.9, run here | 0.759 | 0.921 | 0.862 | 0.617 | 0.616 | 0.465 | 0.416 | 0.514 |
| jusText 3.0.2, run here | 0.713 | 0.826 | 0.653 | 0.685 | 0.752 | 0.379 | 0.382 | 0.629 |
Published test rows: rs-trafilatura 0.893, trafilatura 0.833, dom-smoothie 0.808,
readability 0.726. Second, 0.013 behind; the annotated type would score 0.886 — the
archiver stripped every <script> from these files, so the router's JSON-LD features are
zero and it mis-types listings (0.689 against a 0.763 ceiling). The 0.875 this page showed
before 21 September was not the production path.
Boards deliberately not run
Firecrawl's scrape-evals (live URLs; run once here, never a board), CrawlBench (LLM structured extraction, dataset not published), the Hydrafetch benchmark (the WCXB dev split under another name), the Dragnet and Boilerpipe corpora (inside WCEB), and trafilatura's own evaluation (the maintainer's corpus; WCEB covers it independently).