Auditing what a browser actually sees
A crawler that does not run JavaScript sees the HTML your server sent, which on a modern site is often an empty shell. We fetched notion.so twice: the served HTML contained 0 characters of text and 0 links, and the same page rendered in a browser contained 2,068 characters and 106 links.
Everything an audit would say about that page from the static fetch is wrong. Thin content, no internal links, no structured data — all artefacts of not running the code.
Who renders and who does not
Google renders JavaScript, on a second pass that can lag the first by days. That delay is the whole problem: new pages are discovered late, and internal link signal arrives late or not at all.
Most AI crawlers do not render at any point. To the crawlers behind ChatGPT and Perplexity, a client-rendered page is blank. If being cited in AI answers matters to you, server-side rendering is not an optimisation, it is the entry fee. We measured who is blocked from where separately.
How Docket does it
macOS ships a browser engine. WebKit is a system framework, so Docket renders through a 112 KB helper built against it rather than bundling a browser — the download is still 17 MB, and nothing is fetched at install time. The audit engine stays what it was: dependency-free Python that never needed a browser to do most of its job.
Rendering is off by default, for two reasons worth stating plainly. It executes the page's JavaScript, so analytics fire and advertising pixels load — requests to servers you did not intend to contact when you asked for an audit. And it is roughly ten to thirty times slower than fetching. Both are decisions for you to make rather than surprises to discover.
What it unlocked
Pages that only exist after hydration
The notion.so case. Docket now compares the served HTML against the rendered DOM and reports the difference as a measurement rather than a suspicion — 0 characters versus 2,068 is a fact you can take to whoever owns the front end.
What your tag manager actually loaded
GTM injects tags at runtime, so a static fetch sees the container and nothing else. Docket used to say "GTM is present, so your analytics may be configured inside it" and stop. Rendering notion.so surfaced 54 scripts that were not in the served HTML, among them Marketo, the LinkedIn Insight Tag and the X advertising pixel.
That matters beyond curiosity. Tags you cannot enumerate are tags nobody is auditing, and every one of them is a third party receiving your visitors' data.
Timings from a browser rather than from markup
First Contentful Paint and DOM Content Loaded now come from the browser's own performance API. Docket previously inferred layout-shift and paint risk from markup patterns, which is useful and is not measurement.
Where this stops, and where another tool is better
Rendering in WebKit is not rendering in Chrome. Google evaluates your site in a Chromium renderer, and while the two agree on nearly everything, a bug that only appears in Blink is a bug Docket will not see.
Rendering also says nothing about how much of the page Google read in the first place. It fetches at most 2MB of any URL and indexes that as though it were the whole file, so a heavy page can be truncated before the renderer is ever involved — measured here.
Nor does rendering give you Core Web Vitals. LCP, INP and CLS are field metrics — they come from real users on real connections, not from one machine on a fast desk. Docket can pull that data from the Chrome UX Report when you turn it on, which is the same source Search Console uses. Any tool presenting a single synthetic run as "your Core Web Vitals" is misrepresenting what the number is.
And if you want to crawl a large site with rendering at volume, Screaming Frog has been doing it for years with configurable wait strategies, JavaScript error capture and a rendered-versus-raw diff view built for exactly this. Docket renders a sample — the shallowest pages, ten by default — because that answers "is this site client-rendered and what is it costing me" without turning a five-minute audit into an hour.
Trying it
In the app, turn on rendering before you audit. From the command line:
docket audit https://example.com --render 10
The report says how many pages were rendered, which ones needed it, and what the tag manager loaded. If the helper is missing it says that too, rather than quietly falling back to a static crawl and letting you believe otherwise.
Common questions
Do search engines run JavaScript?
Google does, on a second pass that can lag the first crawl by days. Most AI crawlers do not render at all, so a client-rendered page is blank to the crawlers behind ChatGPT and Perplexity.
Does Docket bundle a browser?
No. macOS ships WebKit as a system framework, so rendering is a 112 KB helper built against it. The download is 17 MB and nothing is fetched at install.
Why is rendering off by default?
It executes the page's JavaScript, so analytics fire and ad pixels load — requests to servers you did not intend to contact by asking for an audit. It is also ten to thirty times slower than fetching.
Can rendering measure Core Web Vitals?
No, and nothing that runs on one machine can. LCP, INP and CLS are field metrics from real users on real connections. Docket reads them from the Chrome UX Report, the same source Search Console uses.