Encited logo
PricingTalk to sales
Do AI Crawlers Render JavaScript? What GPTBot, ClaudeBot and PerplexityBot See

Do AI Crawlers Render JavaScript? What GPTBot, ClaudeBot and PerplexityBot See

Oct 16, 2026October 16, 2026·Updated Oct 29, 2026October 29, 2026·by Aki from Encited

Do AI crawlers render JavaScript? A sourced answer for GPTBot, ClaudeBot, PerplexityBot, Googlebot and Bingbot, why SPAs miss AI citations, and the fix.

Most AI crawlers don't render JavaScript. ChatGPT's crawlers (GPTBot, OAI-SearchBot and ChatGPT-User), ClaudeBot and PerplexityBot read the HTML your server sends and don't execute JavaScript in it. So if your SPA builds its content in the browser, ChatGPT can't read it. Googlebot, Applebot and Bingbot do render JavaScript, which is how a React or Vue site ranks in Google and still gets no AI citations. Server-rendered HTML, or dynamic rendering for AI crawlers, gets them the content in the first response. How Google itself handles the same pages is in JavaScript SEO, and the fixes for a single-page app are in SPA SEO.

TL;DR

  • GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot and PerplexityBot don't run JavaScript, in Vercel and MERJ's crawler measurements. ChatGPT's and Claude's crawlers fetch your JavaScript files but don't run them.
  • Claude-SearchBot, Claude-User and Perplexity-User haven't been measured, and their operators' docs don't mention rendering.
  • Googlebot renders after a delay, so Google Search, AI Overviews, AI Mode and Gemini see the rendered page. Applebot renders too. Bing renders but tells sites not to hide critical content behind client-side rendering.
  • JSON-LD added by JavaScript never reaches the crawlers that don't render.
  • Check with curl and each crawler's user agent, a crawler simulator, or your crawl log.
  • Fix it with server rendering, or with dynamic rendering, which serves crawlers a finished snapshot of each page.

Do AI crawlers render JavaScript?

Three crawlers in the table below render JavaScript: Googlebot, Applebot and Bingbot. The others that have been measured read only the raw HTML.

Crawler What it's for, per its operator Runs JavaScript? Source
GPTBot (OpenAI) Content that may be used to train OpenAI's models No Vercel and MERJ
OAI-SearchBot (OpenAI) Shows sites in ChatGPT search results No Vercel and MERJ
ChatGPT-User (OpenAI) Visits a page when a ChatGPT user asks a question No Vercel and MERJ
ClaudeBot (Anthropic) Collects content that may be used for training No Vercel and MERJ
Claude-SearchBot (Anthropic) Improves Claude's search results No data published Anthropic's docs don't say
Claude-User (Anthropic) Visits a page when a Claude user asks a question No data published Anthropic's docs don't say
PerplexityBot Shows and links sites in Perplexity search results No Vercel and MERJ
Perplexity-User Visits a page to answer a user's question No data published Perplexity's docs don't say
Googlebot Google Search, AI Overviews and AI Mode; Gemini uses the same infrastructure Yes, in a render queue Google, Vercel and MERJ
Google-Extended A robots.txt token with no crawler of its own Uses Googlebot's fetches Google
Applebot Search in Spotlight, Siri and Safari; may train Apple's models Yes Apple, Vercel and MERJ
Bingbot Bing search and Microsoft Copilot Yes, with limits Bing spells out Bing
Meta-ExternalAgent, Bytespider, CCBot Crawlers run by Meta, ByteDance and Common Crawl No Vercel and MERJ

OpenAI, Anthropic and Perplexity document what each bot is for and how robots.txt applies to it. None of their crawler pages mentions JavaScript or rendering. The rendering answers for their bots come from Vercel and MERJ, who tracked crawler traffic on nextjs.org, across the Vercel network and on two job board sites, and found that "none of the major AI crawlers currently render JavaScript."

That study is from December 2024. Crawlers can change without notice, so treat your own logs, read with the checks below, as the current answer.

Does ChatGPT render JavaScript?

No. All three crawlers on OpenAI's crawler page are on Vercel and MERJ's list of crawlers that don't render. They do different jobs, and each shows up under its own name in your logs.

GPTBot and JavaScript

GPTBot crawls "content that may be used in training our generative AI foundation models." In Vercel's data, 11.50% of requests from ChatGPT's crawlers were for JavaScript files, and the study says "they don't execute them. They can't read client-side rendered content."

So a GPTBot request for /assets/index-XXXX.js in your logs doesn't mean it saw your page. It fetched the file and didn't run it.

OAI-SearchBot

"OAI-SearchBot is used to surface websites in search results in ChatGPT's search features." Sites that block it "will not be shown in ChatGPT search answers."

Its user agent string looks like a browser: it contains Chrome/131.0.0.0 Safari/537.36 before the OAI-SearchBot/1.4 token. A server rule that checks for "Chrome" first will treat it as a visitor. And if you allow both GPTBot and OAI-SearchBot, OpenAI says "we may use the results from just one crawl for both use cases," so one crawl may feed both training and search.

ChatGPT-User

ChatGPT-User visits a page when a ChatGPT user asks something that needs it. OpenAI says it "is not used for crawling the web in an automatic fashion," that "robots.txt rules may not apply" because a person started the request, and that it "is not used to determine whether content may appear in Search." It's on the non-rendering list too, so a link pasted into ChatGPT gets read from the raw HTML.

ChatGPT and single-page apps

ChatGPT reads whatever text is in the HTML your server returns. A client-rendered SPA returns an empty container and builds the page with JavaScript, so all three OpenAI crawlers get the container. The title from your index.html is often the only text they can use.

To see that container for yourself, run one of your URLs through the ChatGPT crawler simulator and search the raw HTML it returns for a sentence from the page.

ChatGPT's Cloud browser

OpenAI's help center also describes a Cloud browser in ChatGPT Work, which Akamai, HUMAN and Vercel list under the bot name ChatGPT Agent. Its requests carry a Signature-Agent header set to "https://chatgpt.com" and an HTTP message signature (RFC 9421). The header alone can be faked, so a firewall confirms the agent by checking the signature against the keys OpenAI publishes at https://chatgpt.com/.well-known/http-message-signatures-directory. It isn't on OpenAI's crawler page, and OpenAI doesn't publish how it renders. Whether ChatGPT search shows your pages still depends on OAI-SearchBot.

Can Claude and Perplexity crawlers execute JavaScript?

ClaudeBot and PerplexityBot don't. Claude-SearchBot, Claude-User and Perplexity-User haven't been measured.

Anthropic lists three bots:

  • ClaudeBot collects "web content that could potentially contribute to their training."
  • Claude-SearchBot "navigates the web to improve search result quality for users."
  • Claude-User: "When individuals ask questions to Claude, it may access websites using a Claude-User agent."

Vercel and MERJ measured ClaudeBot: JavaScript files made up 23.84% of Claude's requests, and none of them ran. Anthropic's page doesn't mention rendering, and says its bots honor robots.txt.

Perplexity lists two:

  • PerplexityBot "is designed to surface and link websites in search results on Perplexity." Perplexity says it "is not used to crawl content for AI foundation models."
  • Perplexity-User visits a page when a user asks Perplexity a question. "Since a user requested the fetch, this fetcher generally ignores robots.txt rules."

For the bots nobody has measured, plan for the worst case: if the content isn't in the first HTML response, assume they miss it. Which pages Claude and ChatGPT choose to read in the first place is a separate question, covered in how to rank in LLMs.

Google, Gemini, Apple and Copilot: the crawlers that render

Googlebot, AI Overviews, AI Mode and Gemini

Google's JavaScript SEO basics say "Googlebot queues all pages with a 200 HTTP status code for rendering," and then "a headless Chromium renders the page and executes the JavaScript." A page "may stay on this queue for a few seconds, but it can take longer than that."

Vercel and MERJ measured that wait in a separate study published in July 2024, with data from April 2024. Across more than 100,000 Googlebot fetches on nextjs.org, every HTML page was fully rendered. The median render came 10 seconds after the crawl, the 90th percentile about 3 hours later, and the 99th percentile about 18 hours later.

Google's AI features read from the same index. To show up in AI Overviews or AI Mode, Google says a page "must be indexed and eligible to be shown in Google Search with a snippet." For Gemini, Vercel and MERJ found that "Google's Gemini leverages Googlebot's infrastructure, enabling full JavaScript rendering."

Google-Extended doesn't fetch anything. Google says it "doesn't have a separate HTTP request user agent string." It controls whether content Google crawls may be used to train Gemini models and to ground answers in Gemini Apps and Vertex AI, and it "does not impact a site's inclusion in Google Search." For AI Overviews and AI Mode, Google points to your robots.txt rules for Googlebot and its snippet controls.

Google still recommends server output: "server-side or pre-rendering is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript."

Applebot

Apple says "Applebot may render the content of your website within a browser." Applebot powers search in Spotlight, Siri and Safari, and its data may be used to train Apple's foundation models. If robots.txt blocks the JavaScript, CSS or API calls a page needs, Apple says Applebot may not be able to render it properly. Vercel and MERJ found the same: Applebot "renders JavaScript through a browser-based crawler, similar to Googlebot."

Bingbot and Copilot

Bing's webmaster guidelines cover "Bing search experiences, Copilot, and grounding API results," and say "Bing and Copilot search experiences rely on the same core crawling, indexing, and ranking foundation as traditional search." Bingbot renders, and the guidelines list "Hiding critical content behind client-side rendering" as something to avoid. They add: "Content that cannot be reliably rendered may not be indexed or selected for grounding results."

Copilot wasn't in the Vercel study, because it "lacks a unique user agent for tracking."

Why your SPA ranks in Google and ChatGPT can't read it

A client-rendered React, Vue or Angular app answers every URL with the same file:

html
CopyDownload
<!doctype html>
<html lang="en">
<head>
<title>Your Store</title>
<script type="module" src="/assets/index-XXXX.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>

Googlebot fetches it, queues it, runs the bundle in Chromium and indexes what appears. Your copy, prices, internal links and per-route titles all exist after rendering, so the page can rank.

GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot and PerplexityBot stop at the file above. Every page on your site gives them the same title and an empty div, with nothing in it to quote or cite.

Any page where content arrives after the first response has the same gap:

  • Server-rendered pages that load reviews, prices or specs with a fetch after the page loads.
  • Tabs, accordions and "load more" buttons that fetch their content on click.
  • Next.js, Nuxt or Angular SSR pages with sections that load in the browser after hydration.

What each framework sends crawlers, and how to fix routes, titles and 404s, is in dynamic rendering in React, Vue and Angular, with framework guides for React SEO, Vue SEO and Angular SEO. For the problems Google itself has with JavaScript sites, start with JavaScript SEO.

JSON-LD injected by JavaScript

Structured data has the same problem. Many sites add JSON-LD from the browser, through a tag manager, a reviews app or component code like this:

jsx
CopyDownload
useEffect(() => {
fetch(`/api/products/${id}`)
.then((res) => res.json())
.then((product) => {
const tag = document.createElement("script");
tag.type = "application/ld+json";
tag.textContent = JSON.stringify({
"@context": "https://schema.org",
"@type": "Product",
name: product.name,
offers: { "@type": "Offer", price: product.price, priceCurrency: "USD" },
});
document.head.appendChild(tag);
});
}, [id]);

Google handles this after rendering. Its structured data guide says "Google Search can understand and process structured data that's available in the DOM when it renders the page." For Product markup it adds a warning: "dynamically-generated markup can make Shopping crawls less frequent and less reliable."

A crawler that doesn't run JavaScript never makes that fetch, so the <script type="application/ld+json"> tag isn't in the HTML it reads. JSON that's already in the server response is a different case. Vercel and MERJ note that "content included in the initial HTML response, like JSON data or delayed React Server Components, may still be indexed since AI models can interpret non-HTML content."

To check a page, compare two counts. In your terminal:

bash
CopyDownload
curl -sL -A "Mozilla/5.0 (compatible; GPTBot)" https://example.com/products/trail-runner \
| grep -o 'application/ld+json' | wc -l

In the browser console on the same page:

js
CopyDownload
document.querySelectorAll('script[type="application/ld+json"]').length

A higher number in the browser means some blocks are added by JavaScript, and only the rendering crawlers get them. Move those blocks into the server response, or serve crawlers a rendered snapshot. If the data arrives late, set window.prerenderReady = false in your index.html and true once the data is on the page. Encited's renderer waits for the flag before saving the snapshot and stops waiting after 30 seconds. Product pages carry the most structured data, and the store-side checks are in ecommerce SEO.

How to check what AI crawlers get from your site

1. View the source

View the page source and search for a sentence you can see on screen. The Elements panel in DevTools shows the page after JavaScript ran, so it can't answer this. You can also turn JavaScript off in Chrome DevTools (open the Command Menu and run "Disable JavaScript") and reload. What's left is close to what a non-rendering crawler reads.

2. Curl it with each crawler's user agent

Pick a sentence from the page and run this in a terminal:

bash
CopyDownload
URL="https://example.com/pricing"
TEXT="a sentence you can see on the page"
for bot in GPTBot OAI-SearchBot ChatGPT-User ClaudeBot Claude-SearchBot Claude-User PerplexityBot Perplexity-User Googlebot bingbot; do
html=$(curl -sL -A "Mozilla/5.0 (compatible; $bot)" "$URL")
if grep -qF "$TEXT" <<< "$html"; then found=yes; else found=no; fi
echo "$bot: $(printf '%s' "$html" | wc -c | tr -d ' ') bytes, text found: $found"
done

"text found: no" with a small byte count means that bot gets your shell. Different byte counts for different bots mean your server or CDN answers them differently. Some firewalls check that a request claiming to be GPTBot comes from OpenAI's published IP ranges, and send everything else a challenge page. If yours does, your own requests can fail where the real bots succeed, so confirm in the crawl log before you change anything.

3. Use a crawler simulator

The crawler simulators for ChatGPT, Claude and Perplexity request your URL with that crawler's user agent and show the status code, redirects, response headers and raw HTML that come back. The Googlebot simulator does the same for Google.

4. Run the AI crawl checker

The AI crawl checker reads your robots.txt rules for GPTBot, ClaudeBot, PerplexityBot, Google-Extended, Googlebot and Bingbot, looks for firewall challenge pages, then fetches the page as GPTBot and checks for text that's there without JavaScript.

5. Read your crawl log

A crawl log records what each bot actually got. Encited's crawl log lists every known crawler visit with the bot, the page, the status code and what was served, so you can see whether GPTBot, ClaudeBot or PerplexityBot reached a page and whether they got the rendered snapshot. To check one page step by step, see confirm a bot got your content.

Dynamic rendering for AI crawlers, SSR and pre-rendering

Every fix puts your content in the first HTML response.

Server-side rendering or static generation. Next.js, Nuxt and Angular SSR render each page on the server, and static generation builds the HTML at deploy time. Google prefers these. Its dynamic rendering page says dynamic rendering "was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines. Instead, we recommend that you use server-side rendering, static rendering, or hydration as a solution." For an existing SPA, that means migrating the app. Sections that load in the browser after hydration are still missing from the first response.

Pre-rendering at build time. A build step loads each route in a headless browser and saves the HTML. It works for routes you know at build time, and the HTML stays as it was until the next build. SSR vs pre-rendering compares the two.

Dynamic rendering. A rule at your CDN, edge or server checks the user agent. Crawlers get a snapshot of the page taken after JavaScript finished, and people get the app as before. Google's page says dynamic rendering "was a workaround for … content that uses JavaScript features that aren't supported by the crawlers you care about," which is the AI crawler case. It adds: "As long as your dynamic rendering produces similar content, Googlebot won't view dynamic rendering as cloaking." Dynamic rendering SEO covers the cloaking question in full, and dynamic rendering vs server-side rendering covers running both.

If you write the user agent check yourself, match the crawler tokens:

js
CopyDownload
const CRAWLER_TOKENS =
/Googlebot|bingbot|Applebot|GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|Claude-SearchBot|Claude-User|PerplexityBot|Perplexity-User/i;
const isCrawler = CRAWLER_TOKENS.test(request.headers.get("user-agent") ?? "");

Two details from the operators' docs: Google-Extended never appears in a request, because Google crawls with Googlebot, and OAI-SearchBot's string contains a Chrome version, so test for crawler tokens before any browser check.

With Encited, crawlers get the rendered page of any JavaScript site or storefront, with no code changes. Search engines and link previews get the finished HTML. AI crawlers get HTML, or Markdown when they ask for it (Essential plan and above), with the page's JSON-LD kept as a JSON block at the end of the Markdown. Snapshots are stored across 300+ locations and served from the one closest to the crawler in milliseconds. Setup is a DNS change or a middleware snippet for your host, and plans start at $19 a month.

Once crawlers get your content, the AI visibility tracker shows whether ChatGPT, Perplexity, Gemini and Claude mention your brand for the prompts you care about. To make sure the right crawlers are allowed in the first place, see how to get your pages indexed by ChatGPT.

FAQ

Can AI crawlers execute JavaScript? Most can't. Vercel and MERJ found that GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, PerplexityBot, Meta-ExternalAgent and Bytespider don't run it. Googlebot, Applebot and Bingbot do, so Google's AI features, Gemini, Apple's search and Copilot work from rendered pages.

Does GPTBot render JavaScript? No. GPTBot fetches JavaScript files but doesn't run them. Anything your page builds in the browser is missing from what it collects.

Can ChatGPT read my SPA? Only the text in the HTML your server sends. A client-rendered SPA sends an empty container, so ChatGPT's crawlers get the site title and little else. Server rendering or dynamic rendering gives them the full page.

Why does my SPA rank in Google but not show up in ChatGPT or Perplexity? Googlebot renders JavaScript before indexing, so Google sees your content. ChatGPT's and Perplexity's crawlers read the raw HTML, see the empty shell, and have nothing to cite.

What's the difference between GPTBot, OAI-SearchBot and ChatGPT-User? GPTBot collects content that may train OpenAI's models. OAI-SearchBot crawls for ChatGPT search, and sites that block it aren't shown in ChatGPT search answers. ChatGPT-User visits a page when a user's question needs it, and robots.txt may not apply to it. All three read raw HTML.

Can AI crawlers read JSON-LD added by JavaScript? No. If a script or tag manager adds the JSON-LD after the page loads, crawlers that don't run JavaScript never get it. JSON-LD in the HTML your server sends reaches every crawler.

Does dynamic rendering work for AI crawlers? Yes. Crawlers that don't run JavaScript get a snapshot taken after the page rendered, with the text, links, meta tags and JSON-LD in place. Your visitors keep getting the app.

Is serving AI crawlers a rendered snapshot cloaking? Google says dynamic rendering isn't cloaking as long as it "produces similar content." Bing's guidelines warn against "serving materially different experiences to crawlers and visitors." Serve crawlers the same content people see and you're within both.

How do I stop AI crawlers? Disallow each crawler's token in robots.txt, such as GPTBot, ClaudeBot or Google-Extended. Blocking OAI-SearchBot, Claude-SearchBot or PerplexityBot also costs you visibility in those engines' search results. User-triggered fetchers follow different rules: OpenAI says robots.txt "may not apply" to ChatGPT-User, and Perplexity-User "generally ignores robots.txt rules," so blocking them takes firewall rules based on the IP ranges each company publishes.

What does an AI crawler do? It fetches pages for an AI product. Some collect training data (GPTBot, ClaudeBot), some build the search index behind AI answers (OAI-SearchBot, Claude-SearchBot, PerplexityBot), and some fetch a page live when a user's question needs it (ChatGPT-User, Claude-User, Perplexity-User).

Google
Gemini
ChatGPT
Claude
Grok
Meta
Perplexity

Get discovered anywhere search happens

Readable, citable, outranking pages.

Talk to sales
Avatar
How can we help?
Get instant answers to your questions or leave a message for an engineer will reach out
Ask AI about Encited
See our docs
Contact support
Leave a message
We'll get back to you soon
Avatar
Ask AI about Encited
Product questions, troubleshooting and
Thinking
Preview
Drop an image to attach
Powered by ReplyMaven