A website built on React, Vue, Angular, or Next.js can sit on a blind spot that most marketing teams have never had reason to check: a page that ranks perfectly on Google and reads as almost blank to ChatGPT, Claude, and Perplexity.
This isn’t a hypothetical edge case. It’s a structural gap in how these systems fetch web content, and closing it has become one of the highest-leverage technical fixes available right now, mostly because so few people are looking for it.
The assumption that’s quietly wrong
Ask a marketer why they’re not worried about AI visibility on a JavaScript-heavy site, and you’ll usually get some version of: if Google can crawl and render our site, AI crawlers can too. That held up for a decade. Then AI crawlers started operating at real scale, and the assumption quietly stopped being true — taking a chunk of AI search visibility down with it, for sites that never noticed the ground had shifted.
How Googlebot actually sees your site
Google has poured more than ten years and serious infrastructure spend into its Web Rendering Service — a headless Chromium system that fetches raw HTML, waits, runs the JavaScript, builds the full DOM, and only then indexes what’s left. Google’s own documentation frames this as crawl, then render, then index, with pages sitting in a rendering queue before a headless browser ever touches the JavaScript.
That queueing is the whole reason a React or Vue single-page app can land on page one of Google while shipping almost nothing in its raw HTML. Google is patient. It waits for the render before it judges the page.
How AI crawlers actually see your site
Patience isn’t really part of the design here. GPTBot and OAI-SearchBot from OpenAI, ClaudeBot and its siblings from Anthropic, PerplexityBot, Meta-ExternalAgent, Bytespider — each one fetches a URL, reads whatever text already exists in that first HTML response, and leaves. None of them wait around for a script to run. If your headline, your pricing, your FAQ content only shows up after the page hydrates in a browser, these bots never get to see it in the first place.
Google’s Gemini is the one exception worth naming, since it rides on Googlebot’s existing rendering pipeline rather than building its own. Everyone else feeding answers into ChatGPT, Claude, and Perplexity is working from raw, unrendered markup.
The data behind this isn’t anecdotal
A joint analysis from Vercel and MERJ, pulled from real server logs across Vercel’s network including nextjs.org, tracked more than 500 million GPTBot fetches and turned up zero instances of JavaScript execution. GPTBot did download the JS files themselves in roughly 11.5% of requests. It just never ran a single one. ClaudeBot showed the identical behavior, downloading without executing in around 23.8% of its requests.
The volume behind those numbers is worth sitting with too. In one month, GPTBot alone generated 569 million requests across Vercel’s network; Claude wasn’t far behind at 370 million. Combined, that’s somewhere around a fifth to a quarter of Googlebot’s total crawl volume over the same stretch — nowhere close to fringe traffic.
Anthropic says as much in its own documentation: its web-fetch capability doesn’t support content that’s rendered dynamically through JavaScript, full stop — only whatever HTML the server hands back on the initial request. Independent testing backs this up from a different angle. Glenn Gabe at GSQi has repeatedly shown fully client-rendered sites coming back blank or near-blank when queried directly through ChatGPT, Claude, and Perplexity, on the same URLs that were performing perfectly normally in Google Search at the time.
Put it all together and one pattern holds across every source: none of the major standalone AI crawlers render JavaScript today. Gemini gets a pass because it borrows Google’s infrastructure. Everyone else is reading static text, whether the page was built that way or not.
Why AI crawlers skip rendering in the first place
It’s not an oversight anyone’s rushing to patch — it’s a cost decision. Running a headless browser to fully render a page can slow a crawl by a factor of 10 to 100 compared with a plain HTTP fetch. Google can absorb that because rendering has been baked into its infrastructure for a decade. AI crawlers, by contrast, are built to pull enormous volumes of text off the entire web as fast as possible; bolting headless-browser rendering onto that isn’t a minor upgrade, it’s a fundamentally different cost model. There’s no strong reason to expect this to change on any predictable timeline, so it’s worth planning around rather than waiting out.
Why this bites harder here than it ever did with Google
A JavaScript problem on Google shows up as a delay. The page still gets crawled, still sits in the render queue, still gets indexed — just a little slower than a fully static page would be. Annoying, recoverable, rarely fatal.
AI crawlers don’t offer that grace period. There’s no queue, no retry, no second look later. GPTBot, ClaudeBot, and PerplexityBot fetch a page exactly once. Whatever isn’t in that first response simply isn’t there — no partial credit, no “we’ll pick it up on the next pass.” The page either has real content in its raw HTML, or it’s functionally blank to every one of these systems, every single time.
That produces a strange kind of split visibility: the same URL sitting at position one on Google while returning nothing useful to a ChatGPT or Perplexity query, with Search Console showing nothing but green lights the whole time. There’s no equivalent “AI Search Console” flagging this for anyone, which is exactly why it tends to go unnoticed until somebody thinks to test it on purpose.
Testing it yourself takes about five minutes
Pick a page that matters and work through this.
Start with View Page Source rather than Inspect Element — right-click, or Ctrl/Cmd+U. Inspect shows the DOM after JavaScript has already modified it, which is the browser’s view, not the crawler’s. Page Source shows what actually arrived over the wire. Look for your real copy in there: headline, body text, pricing, FAQ answers. If it’s present, you’re in decent shape. If all that’s sitting in the source is an empty <div id=”root”> or <div id=”app”> followed by a wall of script tags, the content is being injected after the fact, and standalone AI crawlers won’t be able to reach it.
A terminal confirms the same thing faster. Run curl -L https://yourpage.com | grep “a distinctive sentence from your page” — no match means a crawler gets nothing where that sentence should be. Or just ask directly: open ChatGPT, Claude, or Perplexity, point it at a specific URL, and ask it to summarize the first two paragraphs. A vague non-answer, an error, or an “I can’t access that page” response tells you what you need to know.
This is the same mechanism behind the crawlability issue we flagged on Ring A Mover’s site earlier this year — a JavaScript SPA rendering blank to anything that won’t execute its scripts. It just shows up everywhere JS-framework sites get built this way.
Where this bites hardest
A few patterns keep showing up in client audits, more than the rest:
Content that loads after the component mounts — a client-side fetch() call firing once the page is already up, rather than the text existing in the server’s response from the start. Tabs and accordions that only populate on click, since crawlers don’t click anything. Infinite scroll and “Load More” sections, because nothing scrolls or triggers a scroll-based API call on a crawler’s behalf, so anything gated behind that never loads. Product listings and pricing tables pulled from client-side API calls tend to be the worst offenders — often the single most valuable content on a commercial site, and often the most JavaScript-dependent by far.
One more that catches people off guard: schema and JSON-LD aren’t a safety net here. Search engines parse structured data fine, but language models generating an AI answer generally aren’t pulling facts out of JSON-LD. If something only exists in schema and never appears as visible page text, it’s probably not reaching the model either way.
How to actually fix it
There’s no single fix that applies everywhere — it comes down to the stack, the timeline, and how much of the site is affected.
Server-side rendering is the cleanest option where it’s feasible, and the right call for content-heavy pages: service pages, location pages, product pages, blog posts. Next.js (App Router with Server Components, or getServerSideProps), Nuxt for Vue, Angular Universal — all of them can render the important content on the server before anything reaches the client. The bot gets full HTML on the first request, and the user still gets the same interactive experience once hydration kicks in.
Static site generation works well for anything that doesn’t change per request — most location pages and blog content fall squarely into that bucket — and it’s often a lighter lift than full SSR while producing the same fully-formed HTML a crawler needs.
Where a framework migration isn’t realistic on a short timeline, dynamic rendering is a reasonable stopgap: a prerendering service like Prerender.io detects known bot user agents and serves them a pre-rendered snapshot, while human visitors still get the normal client-rendered app. That’s standard practice, not cloaking, as long as what the bot sees matches what a user sees — cloaking is about serving different information, not a different rendering method.
For bigger sites, the realistic path is usually incremental rather than a full rebuild: keep the interactive front-end where it earns its place, but move the pages most worth citing — comparisons, FAQs, pricing, category and location pages — onto SSR or SSG first, and expand from there.
None of that matters if the crawlers can’t reach the page once it’s fixed. Check robots.txt for explicit blocks on GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-SearchBot, and PerplexityBot — OpenAI and Anthropic both document these as independent toggles, so it’s entirely possible to allow OAI-SearchBot for ChatGPT Search visibility while still blocking GPTBot from training, if that distinction matters for a given client. Then check the CDN or WAF layer separately, because this is where things quietly break: Cloudflare, Akamai, and similar bot-management tools often rate-limit or challenge unrecognized traffic by default, which can return a 429 or 403 to GPTBot or ClaudeBot even when robots.txt explicitly allows them through. A clean robots.txt proves nothing about whether the request ever reaches the server — server logs are what actually confirm it.
Read More: How to Rank in AI Search Results: ChatGPT, Google AI Mode & Perplexity
The practical takeaway
None of this is an argument for abandoning React, Vue, or Next.js — that’s neither necessary nor realistic for most businesses. The real requirement is narrower: whatever content is actually worth citing — core copy, headings, pricing, FAQs, the facts that matter — needs to exist in the raw HTML response, with JavaScript layered on for interactivity rather than serving as the delivery mechanism for the content itself.
Google’s decade of rendering investment bought most teams a decade of not having to think about this distinction at all. AI search removed that cushion almost overnight. Sites that treat this as a one-time architectural fix now are the ones that’ll show up in AI answers over the next few years. The ones that don’t will keep looking perfectly healthy in Search Console while quietly losing an entire discovery channel underneath them.
Need a rendering audit for your own site? Get in touch — or read our related piece on technical SEO audits for Shopify and JavaScript-heavy sites for the broader crawlability checklist we run before any AI-visibility work begins.
Sanjeev Kumar is a digital marketing expert with over 14 years of experience in SEO, PPC, content marketing, and online growth strategies. He specializes in search engine optimization, AI-driven marketing, and digital strategy for businesses and agencies worldwide.