Generative Engine Optimization Guide

Static HTML vs JavaScript Rendering: Why AI Crawlers Can't See Half Your Content

Most AI crawlers fetch raw HTML and never run your JavaScript, so client-rendered pages reach answer engines blank. Here's how to fix it.

June 18, 20269 min read
JavaScript renderingstatic HTMLAI crawlers
Static HTML vs JavaScript Rendering: Why AI Crawlers Can't See Half Your Content

A client-rendered page can rank number one on Google and arrive completely blank at every other AI answer engine. That's the conclusion Averi.ai reached on June 3, 2026, and it's the single most expensive misunderstanding in technical SEO right now.

The reason is JavaScript rendering. Googlebot runs your JavaScript. GPTBot, ClaudeBot and PerplexityBot do not. They fetch the raw HTML your server sends, parse what's there, and leave.

If your headline, body, and structured data only exist after a React or Vue bundle executes in the browser, the crawlers feeding ChatGPT, Claude and Perplexity see an empty <div id="root">.

TL;DR: Most AI crawlers read only static HTML and never execute JavaScript. Client-side rendering (CSR) hides your content from them even when Google indexes it fine. The fix is to ship real HTML at the source through SSR or SSG, then verify it with a one-line curl test.

Why can't AI crawlers see JavaScript-rendered content?

Most AI crawlers do not render JavaScript. They make a plain HTTP request, take the initial HTML response, and extract text from that markup. They don't execute scripts, wait for hydration, or retry.

The empirical anchor here is the Vercel/MERJ study of more than 500 million GPTBot fetches, which found zero evidence of JavaScript execution. GPTBot even downloads .js files in 11.5% of requests and ClaudeBot in 23.84%, per Capconvert's January 2026 analysis. It never runs them.

JavaScript files AI crawlers download but never executeGPTBot11.5% of requestsClaudeBot23.84% of requests
JavaScript files AI crawlers download but never execute

That gap matters because Google solved its own version of this problem years ago. Googlebot uses the Web Rendering Service (WRS), an evergreen Chromium renderer, so JavaScript SEO work you did for Google does not carry over. The AI crawlers run a different, dumber pipeline.

Onely reported in February 2026 that 42% of JavaScript-rendered content never gets indexed by AI systems. Capconvert put it more bluntly: roughly 69% of AI crawlers cannot execute JavaScript at all. These are vendor-adjacent figures, so treat them as directional, but every independent source points the same way.

Which AI crawlers render JavaScript and which don't?

Here's the rendering matrix as of June 2026, compiled from needle.sh and corroborated by Vercel, Averi, and HybridRanking. Treat operator behavior as changeable; verify against current docs before you write production rules.

Crawler Operator Renders JS? What it fetches
Googlebot Google Yes Chromium WRS
Google-Extended (Gemini) Google Yes Same WRS as Googlebot
Bingbot Microsoft Limited Evergreen Chromium
Applebot Apple Partial Can render
GPTBot OpenAI No Raw HTML only
OAI-SearchBot OpenAI No Raw HTML only
ChatGPT-User OpenAI No Raw HTML only
ClaudeBot / Claude-User Anthropic No Raw HTML only
PerplexityBot / Perplexity-User Perplexity No Raw HTML only
Bytespider ByteDance No Raw HTML only
CCBot Common Crawl No Raw HTML only

The one counterintuitive entry is Gemini. Google's Martin Splitt confirmed on May 5, 2025 that Google-Extended uses the same WRS as Googlebot. So Gemini inherits Google's rendering advantage. Every other major answer engine does not.

Anthropic states the limit in its own docs. Per its May 2026 documentation, cited by Mersel AI: "The web fetch tool currently does not support websites dynamically rendered via JavaScript."

Static HTML vs JavaScript rendering: what's the actual difference?

Static HTML means the full content of the page exists in the HTML document the server returns before any script runs. JavaScript rendering (client-side rendering) means the server returns a near-empty shell and the browser builds the page by executing a bundle. To a crawler that doesn't run JavaScript, the first is a complete page and the second is a blank one.

The Google Chrome team's canonical taxonomy on web.dev names three patterns: server-side rendering (SSR), static site generation (SSG), and client-side rendering with hydration. The team is explicit that CSR alone is not recommended for SEO-critical content.

Three failure modes show up constantly in audits.

First, the SPA shell. A React, Vue, or Angular app that mounts into <div id="root"> ships no readable content in raw HTML. AI crawlers see the div and the script tag, nothing else.

Second, JSON-LD injected through Google Tag Manager. If your structured data is added client-side via GTM without SSR, it's invisible to GPTBot, ClaudeBot and PerplexityBot. Server-render the JSON-LD instead.

Third, JavaScript-gated states. John Mueller warned on February 17, 2026 against showing "not available" via JavaScript before content loads, because Google may conclude the page doesn't exist and never index the real content.

How do I test what AI crawlers see on my site?

Fetch your own page with an AI crawler's user agent and read the raw response. If your core content isn't there, AI can't read it.

bash
# What GPTBot actually receives
curl -s -A "GPTBot" https://www.example.com/ | less

# Repeat for the others
curl -s -A "ClaudeBot" https://www.example.com/
curl -s -A "PerplexityBot" https://www.example.com/
curl -s -A "OAI-SearchBot" https://www.example.com/

If the output is a shell with a bundle and no article text, you've found your problem. Cross-check with Chrome DevTools by disabling JavaScript and reloading. And grep your server logs to see who's actually visiting:

bash
grep -iE "GPTBot|ClaudeBot|PerplexityBot|OAI-SearchBot|ChatGPT-User|CCBot|Bytespider" /var/log/nginx/access.log

AI bots now make up roughly 4.2% of all HTML requests, per multiple 2026 sources, so this traffic is real and worth measuring.

Key takeaways

  • GPTBot, ClaudeBot, PerplexityBot and most non-Google AI crawlers do not execute JavaScript. They read raw HTML only.
  • Googlebot and Gemini render via WRS; almost no one else does. Ranking on Google tells you nothing about ChatGPT or Claude visibility.
  • Client-side rendering hides content from AI answer engines. A 500M-fetch Vercel/MERJ study found zero GPTBot JS execution.
  • JSON-LD via GTM is invisible to non-rendering crawlers unless server-rendered.
  • Verify with curl -A "GPTBot" before spending money on any remediation layer.

How do I fix JavaScript rendering for AI crawlability?

Ship complete HTML at the source. The durable fix is SSR or SSG, which puts your content in the initial response for every crawler regardless of whether it runs JavaScript. Pick the lowest-friction path that gets you there.

The remediation ladder runs fastest-to-best:

Approach Time to ship Verdict
Prerender service Hours Fast win, recurring cost
Dynamic rendering Days Deprecated stop-gap only
Full SSR/SSG migration Weeks to months Best long-term

Audit before you buy. Prerendering.com noted in April 2026 that some teams buy a managed prerender plan and discover months later their framework already shipped complete HTML and the new layer was duplicate work. Run the curl test first.

Skip dynamic rendering as a strategy. Google deprecated it in 2022 and its docs call it "a workaround and not a long-term solution," recommending SSR, static rendering, or hydration. A prerender service like Prerender.io ($49 to $149+/mo) is a reasonable bridge while you migrate, but Google's own Rendertron was archived in 2022, so don't build on it.

Migrate to a framework that renders on the server. As of June 2026, the canonical path is Next.js App Router (current stable 16.2.9), where Server Components render on the server by default and use client opts a component into the browser. The official CRA-to-Next.js guide walks through moving files into app/ and keeping interactive pieces as client islands. Strong alternatives ship complete HTML too: Astro 6.4.4 (Islands, zero JS by default), Angular v22 (SSR with incremental hydration), SvelteKit 2 with Svelte 5, and React Router v7, the official successor to Remix.

Whatever you pick, the principle outlives the version number: the content must exist in the HTML before any script runs.

What this means for you

Decouple your AI-visibility decision from your Google ranking. They're different pipelines now, and a green Search Console report is not evidence that Perplexity or Claude can read your page.

Run the curl -A "GPTBot" test on your top 20 pages this week. It takes ten minutes and tells you exactly which content is reaching answer engines and which is vanishing into an empty div.

If content is missing, fix it at the rendering layer, not with llms.txt. That file is a content index, not a renderer, and three 2026 studies (SE Ranking, OtterlyAI, ALLMO) found no correlation between it and AI citation frequency. It cannot expose content your raw HTML never contained.

One more operational note: blocking AI crawlers in robots.txt is now leakier than it used to be. OpenAI updated its docs on December 9, 2025 so that ChatGPT-User, being user-initiated, may not honor robots.txt. Control at the CDN layer with something like Cloudflare AI Crawl Control if you need hard rules.

What would change my mind: if OpenAI, Anthropic, or Perplexity shipped a rendering pipeline like Google's WRS, the static-HTML mandate would soften. As of June 2026, every empirical study says they haven't. Build for the crawler that doesn't run your code, and you're covered either way.

Sources

Frequently asked questions

Do AI crawlers like GPTBot execute JavaScript?

No. As of June 2026, GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, PerplexityBot, Bytespider and CCBot fetch raw HTML and do not run JavaScript. A Vercel/MERJ study of 500M+ GPTBot fetches found zero evidence of JS execution. Only Googlebot, Google-Extended (Gemini), Applebot and Bingbot render.

Why can my page rank on Google but be invisible to ChatGPT?

Google's WRS renders JavaScript, so Googlebot sees your client-rendered content. Non-Google AI crawlers do not render, so they see only your initial HTML. If your content is injected client-side, it ranks on Google and reaches ChatGPT or Claude as an empty shell.

How do I test what an AI crawler sees on my site?

Run `curl -s -A "GPTBot" https://yoursite.com/` and read the output. If your headlines, body copy and JSON-LD aren't in that raw HTML, AI crawlers can't see them. Repeat with ClaudeBot and PerplexityBot user agents.

Is dynamic rendering still a good fix in 2026?

No. Google deprecated dynamic rendering in 2022 and labels it a workaround, not a long-term solution. Use server-side rendering (SSR) or static site generation (SSG) instead. Dynamic rendering remains a short-term stop-gap at best.

Does adding llms.txt fix the rendering problem?

No. Llms.txt is a content index, not a rendering fix, and three 2026 studies found no link between it and AI citation frequency. If your pages don't ship content in raw HTML, llms.txt won't make that content visible.