Math, as the author wrote it
A MathJax page comes back as the TeX the author typed, once per formula. A screen-reader of the rendered page gets every equation twice, with the fractions flattened.
Open source · Runs locally · MIT
Point it at a website, anywhere in the world. Every public page comes back as Markdown in the order a reader sees it, with a note of how each page was obtained — and a refusal, named, for every page it could not read.
Earth imagery: NASA
How it reads a page
Point a naive reader at a website and it returns the cookie banner as the article, a login page as the page, a 503 as text, sixty links no reader ever saw. This engine fetches twice, refuses the walls, drops what the browser hides, and writes the page in the order a reader sees it.
Every crawl starts by finding out what's actually there: robots.txt, then sitemap.xml, then the links each page turns up. A queue, not a guess. On one university site that queue held 17,000 URLs, a third of them PDFs, counted but never fetched.
A plain request and a real Chromium render, 1440×900. Neither alone is complete: rendering loses server markup on hydration; a plain fetch misses what scripts insert. Guessing which one a page needs was measured and dropped: the engine reads both.
A wall is not a page. A login redirect, a bot challenge, a 503 are refused in the engine's own words, never passed off as the page. What the browser hides stays hidden: cookie banners, closed dialogs, links parked off the screen, display:none. On one university site that was ~60 gambling links on every page; on one government site, 2,100 words in nine closed dialogs.
Every element is measured. Reading order is a recursive XY-cut over the boxes, so columns stay columns. The Markdown says whether its order was measured or assumed, how the page was fetched and what was refused. The Site Truth Report says the same for a whole site.
Pages, sections and the links between them become a graph: the site already is one, nothing here is LLM-inferred. Entities carry their schema.org identity across every page that mentions them.
Stay on any step as long as you like — the illustration keeps moving; it never freezes waiting for you to scroll on.
A MathJax page comes back as the TeX the author typed, once per formula. A screen-reader of the rendered page gets every equation twice, with the fractions flattened.
A page it cannot read is a refusal in the engine’s own words, not a guess. The message names the wall.
Every quote carries its address: the page, and the block on it. Check it without fetching again.
Each example is a real page; run the address yourself to see the same output. The Site Truth Report — what a site shows people against what it shows crawlers — runs on any site.
04 · The proof
0.861
WCXB, official split
first of nine; 0.002 over the published rival, 0.014 run here
0.860
WCEB, 3,985 pages
second to trafilatura 0.867; 0.885 with the comment field, first
0.650
WebMainBench, tables and code
second to MinerU-HTML 0.826; column mean
0.783
DAnIEL, five languages
fourth of nine; readability 0.840 leads
Rows for this engine measured 21 September 2026 on main@928cf84 with the runners in benchmark/. Every other row says whether it was run here or is its authors’ published figure. All boards, including the ones we lose →
A page it cannot read is a refusal, not a guess. The message names the wall.
A render answered with a server error is a failed side, not content.
The plain fetch stands alone and the render's status is reported beside it.
redirected to a login page (…); the page requires a sign-in and nothing of it was served
Vendor named: Cloudflare, AWS WAF, DataDome, PerimeterX, Akamai, Kasada, Imperva.
the site answered with a Cloudflare bot challenge — a script a browser must run before the page is served — and no page
it said: "You've been blocked…"
The block page's own words, quoted; never passed off as the page.
HTTP 404: page does not exist
Never rendered — a browser renders a 404 page too.
The site asked; the message says what it offers instead.
The rules that applied to this client are shown with the run.
What a browser hides from a reader stays hidden in the output, even when the HTML holds it.
Dropped.
php.net's hidden 100-link table of contents.
Dropped.
Injected links a reader never sees: ~60 gambling links on every page of vtu.ac.in.
Dropped.
2,100 words in nine display:none dialogs on one government site.
Left out of content.
Not page text.
Kept on request; a sighted reader never saw it.
Left out, and named.
The other fetch stands alone; the union does not put the wall's words back.
Refusal kinds are login · challenge · block · undeclared, from the engine’s own error types. An open cookie prompt is on the page and is judged like anything else.
| board | pages | metric | webgraph | leader | place |
|---|---|---|---|---|---|
| WCXB | 1,497 | word-level F1 | 0.861 | 0.861 | 1st of 9 (rs-trafilatura 0.859, published) |
| WCEB | 3,985 | ROUGE-LSum F1 | 0.860 | 0.867 | 2nd of 7; 1st with the comment field joined (0.885) |
| Zyte article | 181 | 4-gram shingle F1 | 0.931 | 0.970 | 11th of 35 |
| WebMainBench | 545 | edit distance, 5 columns | 0.650 | 0.826 | 2nd of 6 (column mean; tables 0.413) |
| DAnIEL (5 languages) | 1,689 | ROUGE-LSum F1, macro over languages | 0.783 | 0.840 | 4th of 9; was last before the router learned the languages |
On WCXB’s second, held-out split (511 pages) this engine scores 0.878; rs-trafilatura, run here on the same files, scores 0.891. Read every board →
05 · Run it
Runs on your machine. The only requests made are to the site you name.