A founder told us recently that their product page ranks third on Google for a high intent category term. Good rankings, solid traffic, the kind of result that normally gets celebrated in a Monday standup. Then he asked ChatGPT the same question his prospects were typing into Google and found that his product did not appear.
The page in question was a React single page application – beautifully built, fast for users, animated transitions that made the product feel premium. But, totally invisible to the crawler that was supposed to be reading it.
This is not a rare misconfiguration – it is the default state of a large share of modern SaaS websites and most teams have no idea it is happening because the symptom never shows up in the tools they normally check.
The Quiet Assumption Most Teams Are Making
For the last decade, the working assumption in SaaS web development has been simple – build a fast, interactive front end in React, Vue or Angular, let the browser handle the rendering, and, trust that Google will figure out the rest. That assumption held up reasonably well because Googlebot has spent years building a headless Chromium based rendering pipeline that executes JavaScript, waits for content to populate and indexes what it sees.
AI crawlers were never built the same way.
GPTBot, ClaudeBot, and PerplexityBot fetch a URL, read whatever HTML comes back in that first response and move on. They do not run your JavaScript bundle, they do not wait for your API calls to resolve, they do not wait for hydration – whatever exists in the raw HTML is what they have. Whatever loads in afterward, through a client side framework simply does not exist for them.
Read — The Complete GEO Playbook
Vercel and the technical SEO firm MERJ ran the most rigorous test of this to date analyzing crawler behavior across Next.js sites and two independently built job board platforms and the result was unambiguous. (Link)
None of the major AI crawlers currently render JavaScript, a list that includes OpenAI’s OAI-SearchBot, ChatGPT-User, and GPTBot, Anthropic’s ClaudeBot, Meta’s external agent, ByteDance’s Bytespider, and Perplexity’s crawler. The only exception in their data was Gemini which inherits Google’s existing rendering infrastructure rather than building its own.

This is what GeoRankers refers to as the rendering divide – the growing gap between what a page looks like to a human visitor or to Google and what it looks like to the crawlers now feeding answers into ChatGPT, Claude and Perplexity. It is not a future risk but is the current state of the AI search ecosystem and it explains why so many well ranked SaaS sites are quietly absent from AI generated answers.
Why This Keeps Getting Missed
Part of the reason this problem stays hidden is that every signal a marketing team normally watches says everything is fine. The page ranks, organic traffic looks healthy and core web vitals are all green. None of those metrics tell you what GPTBot actually received when it requested your URL because none of them simulate a crawler with JavaScript disabled.
The deeper reason is conceptual.
Most teams still think about crawler behavior as a single category – search engines versus everything else, when the more useful split runs along a different line. ChatGPT and Claude crawlers do fetch JavaScript files with ChatGPT requesting them in 11.5% of fetches and Claude in nearly 24% but fetching is not the same as executing. They are downloading the files likely as raw text for training purposes without ever running them to render the page a user would see.
This is the distinction GeoRankers keeps coming back to with clients. A crawler touching your JavaScript file is not evidence of comprehension – it is evidence of collection. The model never sees the rendered DOM – only a script it cannot execute sitting next to an HTML shell that may or may not contain anything useful on its own.
It also helps to know there is no single “ChatGPT crawler” or “Claude crawler.” OpenAI operates GPTBot for model training, OAI-SearchBot for its search index and ChatGPT-User for the live fetches that happen when someone pastes a URL into a conversation.
Anthropic runs a parallel structure with ClaudeBot, Claude-SearchBot, and Claude-User. None of these render JavaScript so the gap applies uniformly across the family but the distinction matters strategically since a site can block the training crawlers while leaving retrieval and search crawlers open.
And, the scale here is not small – in a single month across Vercel’s network, GPTBot generated 569 million fetches and Claude generated 370 million, together with AppleBot and PerplexityBot accounting for roughly 28% of Googlebot’s total volume.
What Actually Gets Lost When JavaScript Does Not Render
The practical consequence is binary in a way that surprises a lot of engineering teams used to thinking about rendering as a spectrum. A client side rendered page either has the meaningful content sitting in the initial HTML response or it does not – there is no middle path. If your pricing table, product description or documentation only populates after a JavaScript bundle executes and an API call resolves, a non-rendering crawler receives an empty container and nothing else.
There is one nuance worth noting here because it changes how teams should think about the fix.
Content that is included directly in the initial HTML response such as embedded JSON data or content from delayed React Server Components may still be picked up since AI models can interpret non-HTML content types as well. The failure mode is not JavaScript itself – it is content that exists exclusively inside the client side render cycle with nothing equivalent present in what the server actually returns on first request.
Read — Does Schema Markup Help With AI Search Visibility?
That distinction matters because it reframes the fix away from “remove JavaScript” toward something more precise – make sure the content that matters for AI visibility exists before any script runs regardless of how much interactivity you layer on top of it afterward.
A Framework for Thinking About the Fix
Most teams reach for one of three approaches once they understand the problem and each comes with real trade-offs worth naming honestly.
Server side rendering generates HTML on the server at request time so every visitor, human or bot, receives a fully populated page on first load. Frameworks like Next.js, Nuxt and Angular Universal handle this natively now which is part of why SSR has become the default recommendation for SaaS sites that care about cross engine visibility. The trade-off is infrastructure complexity and a small latency cost since the server does real work on every request rather than serving something pre-built.
Static site generation builds the HTML once at build time and serves the same cached file afterward. It is faster and cheaper to run than SSR but it does not suit pages with frequently changing or personalized content since every update requires a rebuild.
Prerendering sits between the two – it generates a cached HTML snapshot specifically for crawlers while continuing to serve the full interactive experience to human visitors. It is often the fastest path for an existing React or Vue application because it avoids a framework migration. The honest trade-off is that it introduces a second pipeline to maintain and if the cached snapshot drifts out of sync with what users actually see, it starts to resemble cloaking which carries its own risk with traditional search engines regardless of AI visibility goals.
| Server-Side Rendering | Static Site Generation | Prerendering | |
|---|---|---|---|
| When HTML is built | On every request | Once, at build time | Once, cached for crawlers only |
| Best for | Frequently changing content | Once, at build time | Existing SPAs avoiding a rewrite |
| Trade-Off | Server load, latency cost | Rebuild needed for updates | Second pipeline; risk of drift between bot and user versions |
None of these is universally correct though. A marketing site with mostly static content is well served by SSG, a documentation hub that updates daily probably needs SSR. An existing SPA with real engineering constraints around a full rewrite is often a realistic candidate for prerendering as an interim step with SSR as the longer term target.
The Inefficiency Problem Nobody Talks About
There is a second layer to this that rarely makes it into rendering discussions and it compounds the visibility problem rather than sitting separately from it.
ChatGPT spends close to 35% of its fetches hitting 404 pages with Claude showing a nearly identical pattern compared to Googlebot spending only about 8%. A meaningful share of that waste comes from crawlers repeatedly attempting outdated static assets which suggests these systems are still maturing in how they prioritize URLs before requesting them.
The implication is that crawl budget with AI bots is being spent inefficiently even before the rendering problem enters the picture. A site with messy redirects or stale sitemap entries is asking an already imperfect crawler to do more work to find less. Clean URL structures will not solve the JavaScript rendering gap on their own, but they remove one more variable working against visibility while these crawlers are still working out how to navigate the web.
Why This Matters More As AI Search Grows
It would be easy to read all of this and conclude the stakes are still small enough to defer. But, the crawler volume data suggests otherwise.
AI crawler traffic, while still a fraction of Googlebot’s overall scale, has grown fast enough that the gap between what ranks on Google and what gets cited in AI answers is no longer a rounding error. It is becoming a structural divide between two parallel discovery systems that increasingly determine different parts of the buyer journey.
A prospect doing early stage research is more likely than ever to start that research inside an AI assistant rather than a search bar. If the underlying architecture of your site means that assistant sees nothing where a human sees a fully formed product page, you are not losing a ranking position. You are absent from the conversation entirely in a way no amount of backlink building or keyword optimization will fix because the problem sits below the content layer in the architecture deciding what content even reaches the page in the first place.
Read — What Makes Content AI Citation Ready?
So the question worth sitting with is not whether your site ranks well today – it is whether you actually know what GPTBot, ClaudeBot, and PerplexityBot receive when they request your most important pages, or, whether you are assuming it matches what a human sees in a browser.
Frequently Asked Questions
1. Do AI crawlers like GPTBot and ClaudeBot execute JavaScript?
No. Direct analysis of crawler behavior by Vercel and MERJ found that none of the major AI crawlers, including GPTBot, ClaudeBot, OAI-SearchBot, ChatGPT-User, and PerplexityBot, currently render JavaScript. They fetch the raw HTML response and extract whatever content exists there, without executing any client side scripts. The only notable exception is Gemini, which uses Google’s existing rendering infrastructure.
2. If my site ranks well on Google, does that mean it is visible to AI crawlers too?
Not necessarily. Googlebot uses a headless Chromium based rendering engine that can execute JavaScript and index the fully rendered page, which is why a React or Vue single page application can rank well on Google. AI crawlers do not share that capability, so the same page can appear as an empty shell to ChatGPT, Claude, or Perplexity even while it ranks strongly in traditional search.
3. What is the difference between a crawler fetching Javascript and executing it?
Fetching means the crawler downloads the JavaScript file, often as plain text, typically for training data collection. Executing means running that script to generate the actual rendered content a browser would display. Data shows ChatGPT and Claude crawlers do fetch JavaScript files at meaningful rates, but fetching a script is not the same as running it, and the rendered content it would have produced never reaches the model.
4. What is the best fix for a JavaScript heavy site that wants AI search visibility?
Server side rendering is usually the best long term solution – it generates full HTML on the server for every request so that crawlers and users see the same thing. Static site generation is perfect for content that doesn’t change too often while prerendering, which serves a cached HTML snapshot to crawlers but still provides the full client side experience for users, is usually the quickest fix for existing apps that can’t be migrated to a framework straight away.
5. Does this only affect content pages, or does it also affect things like schema and metadata?
It affects anything that is injected into the page through client side JavaScript rather than present in the initial HTML response. This includes structured data and metadata if they are added dynamically after page load rather than rendered server side. Since AI crawlers only read the first HTML response, any schema markup, title tags, or descriptions added through client side scripts will not be visible to them.
6. Is dynamic rendering a permanent solution or a workaround?
It impacts anything that is injected into the page via client side JavaScript rather than being present in the initial HTML response. This includes structured data and metadata if they are added dynamically after the page loads rather than rendered server side. AI crawlers only read the first HTML response, so any schema markup, title tags or descriptions that are added via client side scripts will not be visible to them.



Leave a Reply