WSS
Web Specification Studio Home
On this page
BlogSEOJavaScriptCrawlingPublished

How Googlebot Renders JavaScript and How to Diagnose When It Fails

Is JavaScript stopping Google from indexing your website? Learn how to test if Google can see your content, find out what is broken, and learn the easiest way to fix it.

Last verified against Google Search Central documentation on August 2026

Googlebot can render JavaScript. But if your content only exists after JavaScript executes, Google must render the page successfully before it can see anything.

The question isn’t whether Googlebot supports JavaScript. It does. The question is whether your content is render-dependent, whether your rendering actually works, and whether you need a quick HTML fix or an architectural change.

Use this table to figure it out:

What you observeWhat it means
Content is in the initial HTMLGoogle can access it without rendering
Missing from initial HTML, present after renderingRender-dependent
Missing from bothRendering failure
Requires a user action to appearInteraction-dependent
Present after rendering but not indexedProbably not a rendering problem

Here is how to test your pages.

Step 0: Is JavaScript Actually Your Problem?

Check these symptoms first. If none apply, JavaScript isn’t your problem.

Your site may have a JavaScript rendering problem if:

  • Content appears in your browser but is missing from View Page Source.
  • Your page source is mostly <div id=**root**></div> with a script tag.
  • Important links only appear after JavaScript runs.
  • Google Search Console’s rendered HTML differs from what you see in your browser.
  • Content depends on an API request that may not complete during rendering.
  • URLs are only reachable by clicking, scrolling, or interacting with the page.

If none of these are true: JavaScript rendering is probably not the first thing to investigate. Check canonicalization, content quality, duplicate content, or indexability directives instead.

The Render Dependency Test

Run this test on any critical page.

Step 1: Is the content in View Source?

Right-click → View Page Source (not the Elements panel).

Yes: The content is in the initial HTML. Rendering is probably not the issue. Jump to Content present but not indexed.

No: The content is render-dependent. Continue to Step 2.

Step 2: Is it in Google’s rendered output?

Open Search Console → URL Inspection → Test Live URL. Check the rendered HTML tab.

Yes: Rendering works. The content is render-dependent but Google can access it. The risk is for non-rendering consumers. See State B.

No: Rendering is failing or the content has an unsupported dependency. Continue to Step 3.

Step 3: Does the content require a user action?

Yes: The content is interaction-dependent. Google does not click, scroll, or hover when rendering. See Problem 3.

No: Look for JavaScript errors, blocked resources, failed API requests, or timing dependencies. See Problem 4.

Step 4: Is the content critical?

Yes: Reduce the rendering dependency. Deliver the content in the initial HTML.

No: Client-side rendering may be acceptable. Verify using URL Inspection periodically.

A flowchart diagram demonstrating the four-step diagnostic test to identify if JavaScript rendering is blocking Googlebot from indexing content.
Figure 1: The Render Dependency Test, a step-by-step diagnostic workflow.
View text description of the flowchart

The flowchart starts with **Content missing**. It asks **In View Source?**.

If Yes, the issue is not rendering (check canonicals, quality, indexability).

If No, it asks **In Rendered HTML?**.

If Yes, it is Render-dependent but working.

If No, it asks **Requires a user action?**.

If Yes, it is Interaction-dependent (requires exposing via crawlable URLs).

If No, it is a Rendering failure (check JS errors or blocked APIs).

The Four States of JavaScript Content

Every piece of content sits in one of four states. Knowing the state tells you exactly what to fix.

State A: HTML-available

The content is in the initial HTML. Google can read it before JavaScript runs.

Risk: Low. This is the most interoperable state. No rendering dependency.

State B: Render-dependent, rendering works

The content is missing from the initial HTML but present in Google’s rendered output.

Risk: Manageable for Google. High for non-rendering consumers such as many AI crawlers, social scrapers, and other bots.

Do not automatically migrate to SSR. First verify the impact and decide whether the dependency is acceptable.

State C: Rendering failure

The content is missing from both the initial HTML and Google’s rendered output.

Risk: Critical. The content is invisible to Google. This requires an active fix.

State D: Interaction-dependent

The content requires clicking, scrolling, hovering, or user state to appear.

Risk: High. Google does not interact with pages when rendering for indexing. This content may never be accessible.

Jump to your situation:

Why You Should Care About Rendering

Content is render-dependent when it doesn’t exist in the initial HTML. It only appears after your JavaScript runs.

Why does this matter? Because if Google’s rendering process fails—or if a background API times out—your content is entirely invisible. You could have the best article in the world, but if it’s trapped behind a broken JavaScript file, it will never rank.

The question isn’t whether Googlebot can execute JavaScript. It can. The real question is: are you willing to bet your organic traffic on that extra rendering step working perfectly every single time?

Content typeIs it safe in the initial HTML?Is it at risk of rendering failure?
Server-rendered articleYesNo
Client-side-rendered appNoYes
Standard HTML navigationYesNo
API-generated linksNoYes
Interaction-loaded contentNoYes, and user action required

How Googlebot Processes JavaScript

Google’s official pipeline is: Crawl → Render → Index

Googlebot reads the initial HTML first. It extracts links and metadata before running any JavaScript.

The page then enters a rendering queue. The Web Rendering Service (WRS) loads it in Chrome and executes the scripts.

After rendering, Google reads the page again to find any new links or content.

A three-wave pipeline diagram illustrating Googlebot's crawling, rendering delay, and final indexing sequence.
Figure 2: The Two-Wave Indexing Pipeline showing the crawl, render, and index phases.
View text description of the pipeline

The diagram shows three stacked blocks representing the pipeline phases.

Wave 1: Initial Crawl includes URL Discovered, followed by HTML Fetched, followed by HTML Processed.

Wave 2: Render Delay includes Render Queue, followed by JavaScript Executed.

Wave 3: Indexing includes Rendered HTML Processed, followed by the Indexing Decision.

Google queues pages that return a 200 status code for rendering. The exception: a robots meta tag or HTTP header that prevents indexing. A URL disallowed by robots.txt is handled before normal fetching. Googlebot skips the HTTP request and does not render JavaScript from the blocked page.

Crawling, rendering, and indexing are three separate steps. A page can render correctly and still not appear in search results. Indexing depends on content quality, canonical setup, and other signals unrelated to JavaScript.

The industry calls this two-wave indexing. Wave one is the initial HTML. Wave two is the rendered content.

What Google Actually Sees: Four Code Examples

Example 1: Empty application shell

<body>
  <div id=**root**></div>
  <script src="/assets/app.js"></script>
</body>

What Google sees initially: almost nothing.

JavaScript adds the actual content later:

document.querySelector(**#root**).innerHTML = `
  <h1>Best Running Shoes</h1>
  <p>Our guide compares the top options for 2026.</p>
  <a href=**/shoes/nike**>Nike</a>
  <a href=**/shoes/adidas**>Adidas</a>
`;

Before that script runs, the initial HTML has no heading, no content, and no internal links. All of that information is render-dependent.

State: B if rendering succeeds, C if it fails. Fix: SSR, prerendering, or static generation for critical content.

Initial HTML:

<nav id=**menu**></nav>

After JavaScript runs:

<a href=**/products**>Products</a>
<a href=**/pricing**>Pricing</a>

State: B. Link discovery depends on rendering. Fix: Output the <a href> links in the initial HTML.

Example 3: Content behind a user action

window.addEventListener(**scroll**, loadMoreProducts);

Google does not scroll. The content will never appear in its rendered output.

State: D. Interaction-dependent. Fix: Expose paginated URLs directly.

<body>
  <main>
    <h1>Best Running Shoes</h1>
    <p>Our guide compares the top options for 2026.</p>
    <nav>
      <a href=**/shoes/nike**>Nike</a>
      <a href=**/shoes/adidas**>Adidas</a>
    </nav>
  </main>
  <script src="/assets/app.js"></script>
</body>

Google reads the heading, content, and links from the initial HTML. JavaScript still runs for interactive features. None of the critical information depends on rendering.

State: A. No rendering dependency for the important content.

Example 5: Broken JavaScript asset

GET /assets/main-abc123.js → 404 Not Found

The HTML shell loads, but the JavaScript bundle that mounts the application is missing. The page appears blank or partially rendered to both users and Googlebot.

State: C. Rendering failure caused by a broken asset. Fix: Restore the JS file or update the reference. Check URL Inspection resource errors and your CDN/deployment pipeline.

Running the Test on Your Site

Step 1: Pick a high-value page

Choose a page with a primary heading, body content, internal navigation links, a canonical tag, and structured data if applicable.

Step 2: View Source

Right-click → View Page Source. Search for your <h1>, main content, an internal link, the canonical tag, and any JSON-LD.

Found: Content is in the initial HTML. Rendering is not the bottleneck.

Missing: The content is render-dependent. Continue.

View Source shows the initial HTML your browser received. Your server might return different content based on user-agent or redirects. Treat this as a first check, not a perfect test.

Step 3: Confirm with curl

curl -sL https://example.com/products/running-shoes | grep -i **running shoes**

If the content is missing here, it is not in the raw response. This confirms the content is render-dependent.

To estimate the response size (check this if you suspect unusually large HTML or resource files):

# Avoid -L  it can combine headers from multiple redirects into one file
curl -sS -D headers.txt -o body.html https://example.com/products/running-shoes
wc -c headers.txt body.html

The last line gives the combined header and body size. Google’s 2MB per-URL limit includes HTTP header bytes.

Step 4: Check Google’s rendered output

Open Search Console → URL Inspection → Test Live URL. Review the rendered HTML, screenshot, loaded resources, and any JavaScript exceptions. Google also recommends the Rich Results Test for JavaScript debugging.

Compare against Step 2:

CheckInitial HTMLGoogle’s rendered output
H1 present✓ or ✗✓ or ✗
Main content present✓ or ✗✓ or ✗
Internal links present✓ or ✗✓ or ✗
Canonical present✓ or ✗✓ or ✗
Structured data present✓ or ✗✓ or ✗

Missing in initial HTML, present after rendering: State B. Render-dependent but working.

Missing in both: State C or D. Rendering failure or interaction dependency.

Present in initial HTML: State A. JavaScript rendering is not the core issue.

Step 5: Check server logs

Server logs show when Googlebot requested HTML and resources. They do not confirm rendering worked.

The WRS may skip non-essential requests. Don’t use analytics to verify rendering. Use Search Console URL Inspection instead.

A Complete Example

The page: /products/running-shoes. It looks correct in your browser.

Step 2: View Source:

<body>
  <div id=**root**></div>
  <script src="/assets/app.js"></script>
</body>

The <h1>, product description, and category links are missing.

Step 3: curl:

curl -sL https://example.com/products/running-shoes | grep -i **running shoes**

No result. Content is not in the raw response.

Step 4: URL Inspection:

Google’s rendered output contains the <h1>, description, and category links.

CheckInitial HTMLRendered output
H1
Main content
Internal links
Canonical

Diagnosis: State B. The page is render-dependent. Google can process the content after rendering, but the initial response has neither the content nor the internal links. Any non-rendering consumer sees an empty page.

Fix: Server-render the product title, description, and category links. Keep interactive filters in client-side JavaScript. The goal isn’t to remove JavaScript—it’s to put important content in the initial HTML.

Common Failures and Fixes

Problem 1: Empty application shell

Symptom:

<body>
  <div id=**root**></div>
  <script src="/app.js"></script>
</body>

State: A if rendering succeeds. C if it fails.

Fix: Use SSR for pages where search visibility matters. Use SSG for content that rarely changes. Not every page needs to change. Only pages where the render-dependent content is critical.

Symptom:

fetch(**/api/categories**)
  .then(res => res.json())
  .then(data => renderNav(data));

The initial HTML has no category links.

Why it matters: Links missing from the initial HTML depend on a successful render before Google can discover the pages they point to.

Fix:

<nav>
  <a href=**/category/shoes**>Shoes</a>
  <a href=**/category/clothing**>Clothing</a>
</nav>

Client-side navigation can still enhance the experience. But the important links should be in the initial HTML as well.

Problem 3: Content only appears after user interaction

Symptom:

window.addEventListener(**scroll**, loadMoreProducts);
// or
document.querySelector(**button**).onclick = loadProducts;

Why it matters: Google does not interact with pages when rendering. Interaction-dependent content will not be available in the rendered output.

Fix: Expose paginated content through crawlable URLs:

/products?page=2
/products?page=3

Google can discover these without user interaction when they appear in crawlable links, a sitemap, or another discoverable source.

Problem 4: Rendering fails because a resource is inaccessible

Symptom: URL Inspection shows a broken or incomplete page. Content that works in your browser is missing from Google’s rendered output.

Rendering failures come from several places:

  • A CSS or JavaScript file is blocked by robots.txt
  • A required resource returns a 403, 404, or 5xx response when Google requests it
  • An API endpoint requires authentication or a cookie the crawler does not have
  • A third-party script fails or times out during rendering
  • A JavaScript exception stops the page from completing its render

How to check:

  1. Look for inaccessible resources required for important content, especially JavaScript, CSS, and API/XHR requests. Images, fonts, and media can affect page appearance but WRS does not fetch them the same way as JavaScript and CSS.
  2. Review errors in URL Inspection.
  3. Check the Console and Network panels in your browser for failed requests.

Fix: Make every resource needed to render important content accessible and returning a success response. Each cause has a different fix.

Content present but not indexed

Symptom: The content exists in the initial HTML and Google’s rendered output, but the page does not appear in search results.

This may not be a JavaScript problem at all. Check:

  • Canonical tags pointing elsewhere
  • noindex directive
  • Thin or duplicate content
  • Manual actions in Search Console
  • Crawl budget issues on large sites
  • Indexability of the URL

Do not change your JavaScript architecture until you confirm that rendering is actually the failing stage.

Common Mistakes to Avoid

Don’t make these common mistakes.

  • Google renders JavaScript does not mean all JavaScript implementations are equally safe. Rendering can fail, be delayed, or be unavailable to non-Google consumers.
  • Successful rendering does not guarantee indexing. These are separate steps with separate requirements.
  • curl does not reproduce Googlebot. It confirms what the server returns to that specific request, not what Google receives.
  • View Source is not the same as the Elements panel. Elements shows the rendered DOM. View Source shows the initial HTML.
  • Missing from search results does not mean JavaScript is the cause. Canonicalization, content quality, and indexability problems can all produce the same symptom.
  • Not every page needs SSR. Identify the state your content is in before choosing an architectural solution.
  • Google’s rendered output is not what every other crawler sees. Other crawlers may not render JavaScript at all.

The Rule for Important Content

If the JavaScript never ran, what would be missing?

Put these in the initial HTML:

  • Page title and headings
  • Main body content
  • Important navigation links (as <a href> elements, not JavaScript click handlers)
  • Canonical URL
  • Open Graph tags
  • Structured data where practical

Google supports JSON-LD injected by JavaScript. Putting it in the initial HTML is a strong recommendation, but not a strict rule.

Leave these to JavaScript:

  • UI state (menus, tabs, accordions)
  • Personalised content
  • Analytics
  • Non-critical below-the-fold features

Why Other Bots Need Your Initial HTML

Google can render JavaScript. Many other consumers cannot.

A 2024 Vercel study measured how major AI crawlers handle JavaScript. They tested crawlers from OpenAI, Anthropic, Perplexity, Meta, and ByteDance.

The findings:

  • ChatGPT-related crawler traffic: JavaScript files accounted for 11.50% of measured requests. No evidence of execution.
  • Claude-related crawler traffic: JavaScript files accounted for 23.84% of measured requests. No evidence of execution.

No evidence of JavaScript execution was found among the major AI crawlers measured. This is a snapshot in time. Crawler behaviour changes.

If your content is in the initial HTML, all bots can read it. If it relies on rendering, you are gambling on each bot’s rendering capabilities.

How to Fix Rendering Problems

Decide which content must live in the initial HTML.

SSR and SSG deliver critical content in the initial HTML. Google and other bots can read it immediately without executing JavaScript.

Google may still render an SSR page. But an HTML-first approach protects your core content from rendering failures.

Google’s official documentation page for renderer-based serving is now titled Dynamic Rendering as a workaround. Dynamic rendering was a temporary workaround. Google now recommends server-side rendering, static generation, or hydration.

Dynamic rendering isn’t cloaking as long as the crawler receives the same content users see.

How to Decide What to Fix

Your situationRecommended action
Content is in the initial HTMLKeep it. Investigate non-JS causes for indexing problems
Content is render-dependent, rendering worksDecide if that dependency is acceptable
Critical content fails renderingFix the rendering failure or move the content to the initial HTML
Critical links depend on JavaScriptOutput them as <a href> in the initial HTML
Content requires user interactionExpose crawlable URLs or content directly
Multiple crawlers need accessUse initial HTML
Not sure which stage is failingRun the Render Dependency Test from the top

Troubleshooting Reference

What you observeLikely causeHow to prove itFix
Content missing from View SourceRender-dependentView Source / curlSSR, SSG, or prerendering
Content missing from rendered outputRendering failure (JS error, blocked resource, API failure)URL Inspection errors + ConsoleFix the failing dependency
Links appear only after JavaScript runsAPI or JS-generated navCompare source vs rendered HTMLOutput <a href> links in initial HTML
Content appears only on scroll or clickInteraction dependencyURL Inspection rendered outputExpose content via crawlable URLs
API-dependent content missingAPI blocked or returns different response during renderNetwork panel + server logsMake data available during server render
JS bundle returns 404Deployment or cache issueResource errors in URL InspectionFix asset delivery
Rendered page looks brokenCSS or JS resource inaccessiblerobots.txt review + ConsoleEnsure resources return successfully
Links present, child pages not indexedDiscovery vs indexing gapCheck child page URL InspectionCheck canonical, quality, crawl budget
Page rendered, not indexedNot a JavaScript issueURL Inspection indexing tabCheck canonical, noindex, thin content
Response size concernOversized serialised statecurl -sS -D headers.txt -o body.html URL && wc -c headers.txt body.htmlReduce initial payload

Publication Checklist

Before launching a JavaScript-heavy page:

  • Main content exists in the initial HTML (View Source check)
  • Important links use real <a href> elements, not only JavaScript handlers
  • Content does not require clicking or scrolling to appear
  • CSS, JavaScript, and API resources required for rendering are accessible to Googlebot
  • Critical HTML and individual resources stay well below Google’s per-URL byte limits
  • URL Inspection confirms the rendered page matches intent
  • SSR or SSG is used where critical content is needed for discovery and compatibility

Common Questions

Does Googlebot execute JavaScript?

Yes. Googlebot uses a Web Rendering Service (WRS) running Chromium to execute JavaScript. However, your content only becomes visible to Google after this rendering step completes successfully.

How long does Googlebot take to render JavaScript?

There is no guaranteed timeframe. Pages enter a rendering queue and can take anywhere from a few seconds to several days to process. Never assume rendering happens instantly during the initial crawl.

Does client-side rendering hurt SEO?

No, but it adds significant risk. If your rendering fails or times out, your content becomes invisible to search engines. You should always ensure your most critical content is in the initial HTML to minimize this risk.

How do I know if Googlebot sees my JavaScript content?

Use the URL Inspection Tool in Google Search Console. Check the View Tested Page tab to see exactly what HTML Google generated after rendering. If your content is missing there, Google cannot see it.

Does Googlebot click buttons or scroll?

No. Googlebot does not interact with your page. Any content hidden behind Load More buttons, clicks, or scroll events will be completely ignored during rendering.

My page renders correctly but still is not indexed. Why?

Rendering does not guarantee indexing. Even if Google can read your JavaScript content, it might still reject the page due to poor quality, duplicate content, or a canonical tag pointing elsewhere.

Written by

Platform Engineer and Technical Writer with 10+ years of full-stack development experience and 2+ years focused on DevOps and platform engineering.

Related posts