Googlebot runs JavaScript later; many AI crawlers and link previews don't run it at all. One click compares the page's server HTML with what you see: SSR, CSR or hybrid, with the evidence.
$ analysis runs locally · no account · telemetry is opt-out
↑ simulated preview — the installed extension runs the real diff on the live page
A client-rendered app answers the first request with a near-empty document and a script bundle. JavaScript then fetches the data and builds the page in the browser. You see the finished page; anything that reads only the HTML response sees the shell. A server-rendered page puts the content in that response.
<!DOCTYPE html> <html lang="en"> <head> <title>Acme Store</title> <script type="module" src="/assets/index.js"></script> </head> <body> <div id="root"></div> </body> </html>
No headings, text or links. The product title, description and prices exist only after index.js runs.
<!DOCTYPE html> <html lang="en"> <head> <title>Trail Running Shoes · Acme Store</title> <meta property="og:image" content="/og/shoes.jpg"> </head> <body> <div id="root"> <h1>Trail Running Shoes</h1> <p>Light, grippy, waterproof.</p> <a href="/shoes/trail-2">Trail 2: $129</a> </div> <script type="module" src="/assets/index.js"></script> </body> </html>
The content is in the response. JavaScript can still hydrate it to make it interactive.
You can check this by hand with view-source: or curl. The extension does it for you on any page: it measures how much of the visible text was in the server HTML, and which regions JavaScript filled in.
Your visitors' browsers run JavaScript. Many of the programs that read your pages run it later, or not at all.
Google crawls the HTML first and queues the page for rendering in headless Chromium. Google says a page may stay on this queue for a few seconds, but it can take longer than that
. Text that only appears after JavaScript waits for that pass and depends on your scripts running correctly in Google's renderer. Google still calls server-side or pre-rendering a great idea
, because not all bots can run JavaScript
.
When a link is pasted into a chat app or a social network, a bot fetches the URL and reads the title, description and image from the meta tags. Many of these preview bots don't run JavaScript, so tags your app sets in the browser may never reach them. Slack, for example, documents that its link expander fetches as little of the page as it can
to extract the meta tags.
Source: Slack, Slack Robots
In Vercel and MERJ's December 2024 analysis of crawler traffic, none of the major AI crawlers they measured (from OpenAI, Anthropic, Meta, ByteDance and Perplexity) rendered JavaScript. ChatGPT's and Claude's crawlers downloaded script files but didn't run them. Gemini, which uses Googlebot's infrastructure, and Applebot did render pages.
What the extension can and can't tell you. It re-fetches the page from your browser, with your cookies, so it shows the HTML your server sends to a browser. Some sites serve bots different HTML, and crawlers change over time, so read the result as a strong hint about what a reader without JavaScript gets, not as a replay of any particular bot.
Most detectors sniff for framework markers and call it a day. This one goes to the source: it re-fetches the page's server HTML and compares its text, word by word, with what the browser actually built.
On any page. The extension fetches the same URL again, which returns the server's HTML before any JavaScript runs, and reads the live page next to it. If the site refuses that second request, it falls back to a text measurement taken while the page was parsing, and lowers the confidence level.
Both sides are measured the same way: script/style/noscript and hidden elements are left out, and visible words are counted. If the server sent only a small share of the visible words, that's strong client-rendered evidence.
15+ weighted signals (hydration markers, serialized state, timing, meta) refine the comparison into SSR, CSR or hybrid, with a High, Medium or Low confidence level and a “Why this verdict” path you can inspect.
The content is already in the HTML the server sends. Readers that don't run JavaScript still get the full page, and slow devices see it sooner.
The server sends a shell and a bundle; JavaScript builds everything after load. Fast for apps, risky for content that needs to rank.
A static server-rendered shell with interactive islands hydrated on top — Astro, Next.js partial hydration, streamed Suspense boundaries.
High, Medium or Low, depending on how clearly the text could be measured. “Why this verdict” walks through the decision, and every signal is listed with its points and what it observed. No black box.
Built at build time, served from a CDN cache, or rendered for this request — read from the document's own response headers, with the CDN, cache state, age and TTFB.
What share of the visible text came from the server and what JavaScript added, then which parts of the page each one built, character by character. #root gained 12,400 characters after the scripts ran.
The whole report at full width in a “Rendering” panel, re-running on every navigation while you work.
Next.js (incl. App Router), Nuxt, React, Vue, Angular, SvelteKit, Astro, Gatsby, WordPress and more.
LCP, CLS, INP and TTFB measured on the live page — plus Long Animation Frame stats.
CSS framework, state management, build tool, hosting — Tailwind, Redux, Vite, Vercel…
Meta tags, Open Graph, structured data, alt-text coverage — the stuff crawlers and screen readers see.
Tracks client-side route changes, soft navigations and the Navigation API — not just the first load.
Timing is rebased on activationStart and skipped for speculative loads, so prerendered pages don't read as impossibly fast.
Recent analyses kept locally, exportable to JSON, CSV or Markdown — or copied as one line into a pull request.
Ctrl/Cmd+Shift+Y, a right-click entry, or the toolbar icon — and the analysis starts the moment the popup opens.
Detection runs entirely in your browser. The extension can optionally send anonymous, aggregate stats — render type, framework, the site's origin only, never full URLs or page content — to power a public dashboard of rendering trends. One toggle in settings turns it off completely. The code is open source (MIT), so you can check.
Because the server sent an empty shell. In a client-rendered app the HTML response is mostly a <div id="root"></div> and a script tag; the bundle then fetches data and builds the page. With JavaScript off, or for any reader that doesn't run it, nothing builds the page and the root stays empty. The usual fixes are server-side rendering, static generation at build time, or at least putting the title and meta tags in the server HTML. Run the extension before and after the change: the share of visible text from the server should go up.
Detection itself: nothing — the diff and scoring run locally. If telemetry is on (it is by default), the extension sends one anonymous record per analysis: render type, confidence, frameworks, Web Vitals, and the site's origin (e.g. example.com) — never the full URL, path, or page content. Response headers and the region breakdown are never sent at all; they are computed on your device, shown to you, and discarded. Disable telemetry in settings with one toggle.
Because frameworks lie. A Next.js App Router page ships no identifiable element, and a CSR app can leave SSR-looking meta behind. The raw-vs-rendered text diff is the ground truth: either the bytes the server sent contain the content, or they don't. Markers and timing only refine that verdict — and since v3.7 they require raw-HTML evidence before they can vote.
That's exactly what the Delivery tab is for. “SSR” covers a page rendered once at build time and served from an S3 bucket, a page answered by a warm CDN cache, and a page the origin renders on every request — three very different systems. The extension reads the document's own response headers and says which one you're looking at, along with the CDN, the cache state, how old the copy is and how long the first byte took. It is reported separately and never allowed to vote on the SSR/CSR verdict: how a document travelled is not the same question as where it was rendered.
Yes. It detects soft navigations and the Navigation API, re-analyzing on route changes. Speculative loads (speculation-rules prerender, navigational prefetch) get their timing signals rebased or skipped so they don't skew the verdict.
Chrome, Microsoft Edge and Firefox 128+ (Manifest V3). Edge Add-ons ships the same package as the Chrome Web Store; the Firefox build is generated from the same source and published on addons.mozilla.org — detection features are identical across all three.
Yes — free and open source under the MIT license. Read the code, open an issue, or star it.