FREE TOOL · NO SIGNUP · NO ACCOUNT

What’s in a page before JavaScript runs

Fetch a URL the way anything without a browser engine fetches it, and see what text actually comes back. This is what a fetch that does not execute JavaScript receives.

It does not compare that against a rendered version, and it does not tell you what any particular crawler sees — whether one runs JavaScript is not something we can verify from here. You get an accurate measurement and draw your own conclusion.

Sites serve different HTML to different agents, so the result is only meaningful next to the agent that produced it. The default identifies itself as this tool; the others are the published strings the crawler access check maintains.

What it measures

Six things, each one a fact about the response and not an opinion about the site. Where a number needs a threshold to mean anything, the threshold and the number are both printed.

  1. Words of text in the HTML

    Script, style, noscript and template content excluded, because none of it is text a reader or an extractor gets.

  2. Empty application containers

    The elements a single-page app mounts into — #root, #app, #__next and four more. An empty one is the clearest single observation available: the element the app renders into arrived with nothing in it.

  3. Hydration payloads, in context

    8 framework markers. A payload on its own means nothing — every server-rendered page emits one, including this one. What counts is a payload beside almost no text, which means the content is in the response as JSON but not as markup.

  4. Script bytes against text bytes

    How much of what came back is program and how much is prose. External scripts are counted but not fetched, so their size is excluded and the page says so.

  5. noscript content

    Present and substantial, present but only a notice, or absent. A framework's default “you need to enable JavaScript” banner is a notice, and counting it as content would be perverse.

  6. Metadata against body

    A title and description present while the body delivers almost nothing is the pattern where a page looks complete to a preview card and empty to a text extractor.

A low word count is not automatically a problem, and this tool will not tell you it is. Below 100 words we call the response low on text and print the number. Whether that matters depends on what else is in the response — an empty application container alongside it is a finding, a short brochure page is not — and on questions this tool cannot answer, which are listed below rather than buried in a FAQ.

The two halves of the same question

The crawler access check answers whether a bot is allowed in. This one answers what it finds when it gets there. A site can pass the first and still hand back an empty container, and a site full of server-rendered copy is no use if robots.txt refuses the fetch. They are one story in two steps, and the agent list here is the one that tool maintains.

What this cannot tell you

  • It cannot tell you what a crawler that executes JavaScript receives

    This is one fetch with no JavaScript engine attached. A client that runs the page's scripts gets something else, and we have no way to measure that from here. Whether any particular crawler runs them is not something we can verify, so this tool does not say.

  • A bot-protection challenge is measured instead of the site

    If the site answers a request like ours with a challenge page, everything below describes the challenge. We detect that where a vendor publishes a way to — Cloudflare's `cf-mitigated` header — and any non-2xx response is reported as the response it was, with no word count at all. Outside those two cases a challenge can still be served as a normal-looking page, and it would read here as a site with very little text.

  • A consent wall produces a low count either way

    A page that answers with a cookie or age gate delivers almost no text whether the site behind it is server-rendered or not. That makes the result uninformative rather than negative, and it is the most common reason a European site measures low here.

  • Our response may not be the visitor's

    We fetch from one server, in one location, with one user-agent, once. Geography, personalisation and A/B tests all mean the HTML you would get can differ from the HTML we got. The agent is named above the result for exactly this reason.

Where the markers came fromChecked 2026-08-14

Every marker is a string that is either in the HTML or is not, so you can check any result by opening view source. What the list records is where each spelling was read from:

  • Cloudflare documents `cf-mitigated: challenge` as present on every challenge page type, and states that `challenge` is the only valid value. It is the one bot-protection signal here that comes from a vendor rather than from observation.
  • Next.js emits two entirely different payload markers depending on the router: `__NEXT_DATA__` on the Pages Router and `self.__next_f` on the App Router. Verified against this repository's own served HTML, which contains `self.__next_f` and no `__NEXT_DATA__` at all. A list carrying only the older marker would fail to recognise every App Router site.
  • No bot-protection vendor other than Cloudflare publishes a stable way to identify its block page from the outside. Every list of body-text signatures for DataDome, Imperva, PerimeterX and Akamai traces back to scraping guides rather than to vendor documentation, so none of them is shipped — see `notShipped`.
  • Framework payload globals are almost never named in vendor documentation, even where the mechanism is documented at length: Nuxt's hydration page explains the payload without ever spelling the global. Each marker therefore carries where it was read from, and the result page shows the matched string next to the framework name so a reader can check the label against the evidence.

Deliberately absent:

  • DataDome, Imperva, PerimeterX and Akamai challenge pages. No vendor documents a header or body string that identifies its block page. The signatures in circulation come from scraping guides, change without notice, and would produce a confident vendor name attached to a guess. A challenge from any of them still arrives as a non-2xx status, which this tool reports as the status it was rather than as a measurement of the site.
  • Body-text interstitial phrases ("Just a moment…", "Checking your browser"). They are localised, they are edited by the vendor, and a page can legitimately contain them. Matching on them would misreport an article about bot protection as a challenge page.

Verified 2026-08-14. This page fails its own build if that check goes more than 90 days without being redone.

SIMPLYREPORT

The monthly version of this sits alongside GA4 and Search Console, in one branded report for your client.

SimplyReport pulls the data and writes the analysis; you send one link. Folding AI search visibility into the same report is what we are building next — it is not measuring anything yet. Built for solo consultants. Closed beta, from $29/month.

Other free tools: the GA4 channel group that catches AI referral traffic · find out why a site can't be read by AI crawlers · read the provenance record attached to an image