Key Takeaways:
Google renders JavaScript - but with possible rendering delay, additional resource overhead and a blind spot that grows more relevant as AI search gains weight. While Google’s Web Rendering Service has been processing JS for years, the most extensive publicly documented measurement of its kind that I know of found no JavaScript execution in any of the major AI crawlers (Vercel/MERJ, December 2024). Whether these bots execute JavaScript is not stated in the vendor documentation I checked; user agents, purposes and access rules are documented there. Sites relying on client-side rendering should therefore not count on being found in AI search.
- Crawling, rendering, indexing: Google first processes the HTTP response with the raw HTML; rendering with headless Chromium follows separately, from a queue. Google gives no fixed duration for it (“a few seconds, but it can take longer”); in my own observation the gap runs from hours to weeks.
- AI crawler problem: No JavaScript execution was measured for GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot, Bytespider or Meta-ExternalAgent (Vercel/MERJ, December 2024), and no vendor documents it either way. Critical content therefore belongs in the initial HTML.
- Recommendation for 2026: SSR, SSG or a hybrid model as the foundation for publicly relevant content; CSR mainly for interactive and non-indexable components. Dynamic rendering remains a migration workaround for existing applications, not a new-build strategy.
On March 4th, 2026, Google removed a warning from its official JavaScript SEO documentation. The “Design for accessibility” section - which recommended keeping pages functional without JavaScript - was dropped with the note that the information had become “outdated and no longer as helpful as before.” Google has been rendering JavaScript for years, so JS no longer makes indexing harder.
That sounds like an all-clear. It isn’t. The question “Can Google render JavaScript?” was largely settled back in 2019. The relevant question in 2026 is: Which crawlers actually reach your JavaScript-generated content? And that’s where things get uncomfortable. While Google has steadily improved its Web Rendering Service (WRS), no JavaScript execution was measured for GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot, Bytespider or Meta-ExternalAgent (Vercel/MERJ, December 2024). Not one of them, in that measurement.
In my technical audits, I regularly see single-page apps that are indexable for Google but whose client-side generated content is missing from the initial HTML. That can limit discoverability in AI services. Absent visibility cannot be proven from the rendering method alone. That is the real JavaScript SEO problem in 2026 - not whether Google can handle it, but who else can keep up.
In this article: How Google’s WRS works technically, what can go wrong in the two-wave crawl, what the measurement data shows about AI crawlers and JavaScript, and which rendering strategy is right for 2026.
Google’s Web Rendering Service: The Two-Wave Crawl
For rendering, Google uses a headless Chromium environment. In an SEO context this rendering step is commonly called the Web Rendering Service, or WRS. Since 2019 Googlebot has run on an evergreen version of Chromium that is updated regularly. This means modern JavaScript syntax (ES6+, async/await, Promises, Fetch API) is fully supported.
Google’s search process has three main phases: crawling, rendering and indexing. For JavaScript pages the sequence can be read, in simplified form, as two consecutive processing steps, and that is exactly how Phase 1 and Phase 2 below are meant:
Phase 1 - HTTP Crawl: Googlebot fetches the HTTP response and processes the HTML it contains. JavaScript is not executed at this point; that happens later, in the rendering phase. Whatever is in the initial HTML at that point is immediately evaluated and used for indexing. The initial HTML carries the important signals: links, title tags, meta descriptions, canonical URLs and robots meta tags. They should be present and consistent there wherever possible; Google can still process some of them after rendering. The fetch limit does apply here: each individual fetched URL or resource has a 2 MB ceiling, and bytes beyond it are not fetched, not rendered and not indexed.
Phase 2 - Rendering Queue: Pages containing JavaScript are queued by Googlebot for rendering. Once Google’s resources allow, the WRS renders the page with headless Chromium. Only then does Google see the JavaScript-generated content. How long does it take? Google provides no concrete numbers. In practice, the range spans from a few hours to several weeks - depending on the domain’s crawl frequency, server performance, and available WRS capacity.
What the WRS processes for rendering: CSS, JavaScript, XHR requests and API calls. The same does not hold in that form for image and video content, and Google’s JavaScript docs make no firm statement about it. For critical media, don’t rely on deferred JavaScript execution; verify it in the rendered HTML instead. If API requests fail, get blocked or answer too late, the content you need can be missing from the rendered HTML. You can check that in the URL Inspection tool in Search Console and in the Rich Results Test.
For a detailed look at Google’s overall crawling mechanism - crawl budget, priorities, frequency - see my article on Google crawling and indexation.
What Google Sees After Rendering - And What It Misses
When the subsequent rendering completes successfully, Google can evaluate the DOM it produces. Text, internal and external links and structured data in JSON-LD format can be processed from the rendered DOM, even when the script tag was injected via JavaScript. For images and videos, the URLs and the matching HTML elements also have to be present in the rendered HTML. Processed does not automatically mean indexed. How Google fundamentally parses and processes HTML - before rendering even comes into play - I cover in my article on HTML Parsing & SEO. Native lazy loading via loading="lazy" is generally fine, but belongs in the URL Inspection tool: what matters is that the image and video URLs are present in the rendered HTML. Infinite scroll becomes a problem where individual items have no standalone, crawlable URLs. An accessible pagination with normal links and consistent canonicals is more robust — a canonical alone does not replace pagination.
The Classic JS SEO Failures - Still Just as Relevant in 2026
In my technical SEO work, certain patterns keep appearing. The most frequent mistakes:
Setting canonical URLs via JavaScript: Canonical tags belong in the initial HTML wherever possible. Google can process a rel="canonical" injected with JavaScript, but states plainly “we don’t recommend using JavaScript for this”. If the canonical is set or altered after rendering, it must not diverge from the canonical URL given in the original HTML - otherwise Google may fall back on other signals or fail to canonicalise the URL as intended. This is especially critical for e-commerce sites with dynamically generated URL parameters.
Fragment-based routing (#): When your SPA uses fragment URLs (e.g., example.com/#/product/123), Googlebot sees these as a single page with fragments - not as separate pages. The correct solution is the browser’s History API, which generates clean URLs without fragments.
HTTP status codes via JavaScript: 404 pages that are only marked as “not found” client-side but return HTTP status 200 - this is a classic SPA problem. Google sees a 200 page and indexes it as empty or misleading content.
For a detailed overview of common structured data errors, see my article on FAQ Rich Results and schema markup - many of the foundational principles apply equally to JavaScript-generated markup. If you want to know whether structured data provides a specific advantage for AI Overviews, see my piece on structured data and AI Overviews.
AI Crawlers and JavaScript: The Overlooked Problem in 2026
This is the part that many 2026 JS SEO articles still overlook: Google’s ability to render JavaScript is the exception - not the rule. Many crawlers outside Google operate without demonstrated JavaScript execution.
An overview of the most relevant AI crawlers and their rendering status - individual platform infrastructure can change over time. The “JavaScript Rendering” column is based on the Vercel and MERJ analysis of 17 December 2024 (“none of the major AI crawlers currently render JavaScript”, over 500 million GPTBot fetches analysed). No vendor documents JavaScript execution for any of these bots, and no public re-measurement exists for 2026. Retrieved 16 August 2026.
| Crawler / Bot | Operator | JavaScript Rendering | Purpose / platform |
|---|---|---|---|
| Googlebot / WRS | Yes - headless Chromium | Google Search, AI Overviews | |
| Applebot | Apple | JavaScript execution measured† | Siri, Spotlight |
| GPTBot | OpenAI | No execution measured* | Training |
| OAI-SearchBot | OpenAI | No execution measured* | ChatGPT Search |
| ChatGPT-User | OpenAI | No execution measured* | Fetches on behalf of users |
| ClaudeBot | Anthropic | No execution measured* | Anthropic crawler‡ |
| PerplexityBot | Perplexity AI | No execution measured* | Perplexity |
| Bytespider | ByteDance | No execution measured* | TikTok Search |
| Meta-ExternalAgent | Meta | No execution measured* | Training / Meta AI |
* Based on the Vercel/MERJ analysis of December 2024. There is no official vendor statement on this, and no public re-measurement for 2026 that I have been able to confirm. Since crawler infrastructure can change at any time, site owners should regularly check their own visibility in AI-powered search.
† Apple: Applebot may render pages in a browser; the same analysis calls it “a browser-based crawler, similar to Googlebot”.
‡ Anthropic documents three crawlers with separate purposes: ClaudeBot (training), Claude-User (fetching in response to a user question) and Claude-SearchBot (search quality inside Claude). Only ClaudeBot was part of the 2024 analysis; for the other two I have no measurement. I could also not confirm the purpose given for Bytespider (TikTok) against a vendor source.
What does this mean in practice? In the Vercel/MERJ analysis the ChatGPT crawlers downloaded JavaScript files in 11.50% of requests and the Claude crawlers in 23.84%, without executing them. For the remaining bots this behaviour should not be generalised without your own measurement. Content that only comes into being through client-side rendering in the browser stays unread by them. If your product descriptions, pricing, or main content are only rendered via JavaScript into the DOM, these crawlers see an empty page - or at best the HTML skeleton.
In my work with clients, this is no longer an abstract problem. In an e-commerce project I reviewed, running a Vue.js SPA without SSR, the server logs showed no verified GPTBot fetch across the period I analysed. Verified here means matched against OpenAI’s published IP ranges, because a user agent alone can be spoofed. Across the search queries I checked, no visibility in ChatGPT Search was detectable for that project. That is an observation from one project, not proof that rendering was the cause.
How AI crawlers affect overall traffic and visibility is a topic that goes beyond the scope of this article. Relevant in this context: Google has introduced a dedicated user agent for AI agents - what that means, I cover in my article on the Google user agent for AI agents. If you want to make your content specifically visible for AI searches, see the llms.txt guide. And how Google weights its algorithm for AI-powered search is covered in my piece on the Google algorithm: crawling, indexing and ranking.
Rendering Strategies Compared: CSR, SSR, SSG and Dynamic Rendering
The four common rendering approaches differ fundamentally in where and when HTML is generated (technical background: web.dev: Rendering on the Web):
Client-Side Rendering (CSR)
The browser receives a minimal HTML page with an empty <div id="app"></div>. JavaScript loads, executes, and only then generates the visible content. This is the classic SPA approach with React, Vue or Angular without server-side rendering.
For Google: Works after Phase 2 - but with possible delay and additional resource fetches that can weigh on the crawl budget. For crawlers that do not execute JavaScript, the content usually stays uncaptured.
Server-Side Rendering (SSR)
The server renders the page fully on each request and delivers complete HTML. Next.js, Nuxt.js and Remix support SSR natively. Every crawler receives complete HTML on fetch and does not depend on client-side JavaScript execution.
Downside: Server load under high traffic. Upside: a very good starting position for crawlers that process HTML without JavaScript, and no additional wait for client-side rendering.
Static Site Generation (SSG)
HTML is generated once at build time and served as a static file. Astro, Next.js (getStaticProps), Nuxt.js (nuxt generate) or 11ty are typical SSG tools. Very good performance, a very good starting position for crawlers without JavaScript execution, no server-side rendering overhead.
Limitation: Dynamic content (user-specific, real-time data) requires client-side loading or ISR.
Dynamic Rendering
Middleware detects crawlers via user agent and delivers statically pre-rendered HTML only to bots. Regular users receive the SPA. Since Google recommends SSR frameworks, dynamic rendering is officially a migration workaround - not a preferred approach for new projects.
The problem with dynamic rendering for AI crawlers: many AI bots aren’t included in standard bot-detection lists. You’d need to manually add GPTBot, ClaudeBot, PerplexityBot etc. and update the list as new crawlers emerge. That’s maintenance-heavy and error-prone.
| Strategy | Google SEO | AI Crawlers | Performance | Effort |
|---|---|---|---|---|
| CSR (SPA) | Depends on implementation (queue delay) | Usually not captured | Good post-hydration | Low |
| SSR | Very good | Very good | Higher TTFB | Medium |
| SSG | Very good | Very good | Optimal | Medium |
| Dynamic Rendering | Good (if correct) | Partial (manual) | Good for users | High (maintenance) |
| Hybrid (SSR + CSR) | Very good | Good | Good | High |
Framework Check: Which JavaScript Framework Is SEO-Friendly?
The framework doesn’t determine SEO success or failure. The rendering configuration does. That said, there are clear differences in how easily a framework enables good rendering:
Next.js is the market leader for React-based SSR and SSG projects. App Router, Server Components, getStaticProps and ISR (Incremental Static Regeneration) offer granular control over what gets rendered server-side versus client-side. Technically very strong for SEO when rendering modes are used deliberately - not on autopilot.
Nuxt.js is the Vue.js equivalent of Next.js and equally capable in rendering flexibility. SSR, SSG and hybrid modes are natively supported. The natural choice for teams with a Vue background.
Astro takes a different approach: “Islands Architecture” or “Partial Hydration.” By default, static HTML pages are served without any client-side JavaScript. JavaScript is only loaded where interactive components actually need it. From an SEO perspective - and especially from an AI crawler perspective - this is the cleanest approach. Downside: highly dynamic applications are more complex to build with Astro.
Remix is strongly oriented toward web standards and native browser APIs. Server-side rendering is the default. A very solid choice for content-driven sites.
Angular (without Universal) and plain React/Vue without SSR require extra work on SEO-relevant projects if the content also needs to be readable by AI crawlers. Without SSR, SSG or prerendering it isn’t in the initial HTML, and that is exactly what these crawlers depend on according to the available measurement.
One technical aspect that often gets underestimated: oversized JavaScript bundles can cause timeouts during WRS rendering. The Googlebot 2 MB crawl limit applies to external resources too. Bundle splitting and code splitting are therefore not just performance optimizations - they’re directly SEO-relevant.
Monitoring: Detecting Rendering Problems in Search Console
Google has removed an outdated note from its documentation: the browser quick-check where you disabled JavaScript to see what Googlebot sees. That was a widespread method for years - it’s now outdated. The correct workflow:
URL Inspection Tool in Search Console: Returns the rendered HTML that Googlebot last saw, including a screenshot. Click “View tested page” - there you’ll see exactly which resources were loaded, which errors occurred, and how the page looks rendered. This is the most direct signal Google offers.
Rich Results Test: For JSON-LD validation and structured data verification. Shows whether Google can read your markup - whether it’s directly in the HTML or injected via JavaScript.
Lighthouse in Chrome DevTools: Provides performance metrics (LCP, CLS, INP) and shows how JavaScript rendering affects Core Web Vitals. High JavaScript execution times directly translate into poor INP scores. A complete optimization guide for all three metrics is in my article on Core Web Vitals: LCP, INP & CLS optimization.
Log file analysis: Server logs show Googlebot fetches and the intervals between them. They do not prove which fetch belongs to the rendering phase: Google documents no separate user agent for the renderer, so a differing user agent is not proof on its own. Large gaps between Phase 1 and Phase 2 signal that your pages are being given low priority in the rendering queue.
For broader technical SEO monitoring - including Core Web Vitals, crawl budget management and indexation status - see my articles on Google crawling and the indexation process.
Frequently Asked Questions (FAQ)
Does Google render JavaScript for all pages?
Yes - in principle, Google queues all pages with HTTP status 200 for rendering, unless a robots meta tag or X-Robots header excludes them. Being queued is neither a successful render nor indexation, though. However, the rendering happens asynchronously in a queue, not immediately on the first crawl. Google gives no fixed duration; the documentation says a few seconds or longer. In my own observation, individual projects show markedly longer gaps between the first fetch and rendering, in bad cases hours to weeks. That range is my own observation, not a figure from Google.
Why don’t AI crawlers render JavaScript?
It comes down to infrastructure and cost: full JavaScript rendering with headless Chromium requires significant compute per crawled page. Google can afford this because rendering is built into the core infrastructure. The available measurement shows the behaviour but does not explain its cause. Likely factors are infrastructure, cost, speed and the differing purpose of each crawler. Headless browser rendering costs a multiple in time and compute per page; I’m not aware of a reliable published figure for these crawlers. For crawler operators and crawled servers alike it remains the more expensive path.
Do I need to avoid JavaScript for good rankings?
No - avoiding JavaScript entirely is not a requirement. The requirement is that critical content (text, links, heading structure, structured data) is available in the initial HTML or delivered through server-side rendering. Interactive UI elements, animations, dynamic filter options - all of that should and can use JavaScript. The problem only arises when content-relevant material is generated exclusively through client-side rendering.
Is dynamic rendering a valid solution for JavaScript SEO?
As a migration workaround for existing SPAs - yes. For new projects - no. Google itself has removed dynamic rendering from its list of recommended solutions for new websites. The core problem: dynamic rendering is based on user-agent detection. That means you need to manually maintain and update the list of bots to serve, whenever new AI crawlers emerge. That’s error-prone. SSR or SSG solve the problem structurally, not symptomatically.
Can I inject JSON-LD structured data via JavaScript?
Technically it works - Google reads JSON-LD even when injected into the DOM via JavaScript, provided the subsequent rendering completes successfully. For maximum reliability and AI crawler compatibility, it’s best to place JSON-LD directly in the initial HTML. If schema markup is only important for Google and you’re confident rendering is reliable, JavaScript injection is acceptable. For pages with high commercial importance, I’d take the safer route.
Conclusion: The Right Rendering Strategy for 2026
Google’s decision to drop the “disable JavaScript” recommendation from its docs is a signal: the war “Can Google render JS?” is won. Anyone who has migrated their stack to SSR or SSG in recent years is in good shape.
The new front is AI search. And there, according to the last solid measurement, the answer to the rendering question is no, without any vendor confirming or denying it officially. In my work with clients, I see how underestimated this point is - especially in teams with a strong developer background who argue “but Google renders it.” True for Google. For GPTBot and PerplexityBot, the measurement drawn on here found no JavaScript execution, and there is no current official vendor confirmation either way. That is becoming increasingly traffic-relevant.
The action framework for 2026 is clear: SSG as the preferred option for largely static, content-heavy pages, SSR for dynamic content, hybrid models where both come together, client-side JavaScript only for interactive elements - never for content-relevant material. Dynamic rendering only as a migration workaround for legacy SPAs, not as a new-build approach.
Last updated: mid-2026. In particular, the information about JavaScript rendering behavior of AI crawlers is based on observation and may change as crawler infrastructure evolves. Recommendation: regularly audit AI search visibility via log analysis or dedicated crawler testing.
- Check initial HTML output in browser DevTools for completeness (don’t disable JS)
- Use URL Inspection Tool in Search Console, not the old “JS-off test”
- Set canonical URLs exclusively in the initial HTML
- Return HTTP status codes correctly server-side (no “soft 404” via JS)
- Place JSON-LD in the initial HTML, don’t inject it via JS after load
- Use Screaming Frog with GPTBot user agent for AI crawler visibility check
- Check JavaScript bundle size - anything over 2 MB is ignored by the WRS


