Why Googlebot Might Be Seeing a Blank Page (and Yours Doesn't Show It)
Quick answer: Google does execute JavaScript, but not in the same step as the initial crawl. It fetches the raw HTML response first, then renders the page in a separate pass using its own headless…
Quick answer: Google does execute JavaScript, but not in the same step as the initial crawl. It fetches the raw HTML response first, then renders the page in a separate pass using its own headless browser, a pass that has its own resource limits and can fail without any visible error on your end. Plenty of other bots, including many SEO tools, link-preview crawlers, and some AI crawlers, don't render JavaScript at all and only ever see that raw HTML. If your content depends on a client-side fetch, an interaction, or a script that errors out partway through, you can end up with a page that looks complete in your browser and is effectively blank to a crawler. The fix starts with checking the raw response and the rendered result separately, instead of trusting what you see in your own browser.
Developers rarely catch this by eye, for a simple reason: your browser always has JavaScript enabled and always runs it successfully in your normal testing. You never see the in-between state a crawler sees, because your own workflow skips straight past it.
In short: what you see in your browser is the end state, after your JavaScript ran without error on a fast connection with no restrictions. A crawler's view is the state before and during that process, and it doesn't always reach the same end state you do.
What Your Browser Does That a Crawler Might Not
Open DevTools and look at two different things: "View Source" and the Elements panel. View Source shows the raw HTML your server sent, before any JavaScript ran. The Elements panel shows the current state of the DOM, after your JavaScript has executed, fetched data, and rendered content. For a typical developer, these two rarely get compared, because the Elements panel is what you actually work with day to day.
That gap between "what the server sent" and "what's on screen after JavaScript runs" is exactly what a crawler has to bridge, except it doesn't always bridge it the way your browser does.
How Googlebot Actually Handles JavaScript
Google has been public for years about rendering pages with a headless, Chromium-based renderer, so the old idea that "Google can't run JavaScript" isn't accurate. What's less widely understood is that this rendering happens as a separate step from the initial crawl, not inline with it. Google fetches the raw HTML first, queues the page for rendering, and runs the JavaScript in that later pass, a pass that has its own resource and time constraints and isn't guaranteed to succeed for every page on every attempt.
Beyond Google, plenty of other crawlers only ever read the raw HTML response and don't execute JavaScript at all: many SEO auditing tools, a number of link-preview bots used by chat apps and social platforms, and various crawlers used by other services and AI tools. For all of them, content that only exists after your JavaScript runs is genuinely invisible, not delayed or deprioritized, just absent.
The Specific Patterns That Cause Problems
1. Content loaded after the initial render
A common pattern is fetching content client-side after the page mounts (a useEffect call, a componentDidMount fetch, a similar hook in another framework) rather than including it in the server's initial response. Your browser runs that fetch instantly and you never notice a gap. A renderer has to wait for that same fetch to complete during its own constrained pass, and if it's slow, requires a cookie or session state the crawler doesn't have, or simply doesn't finish in time, the content it was supposed to show never makes it into what gets indexed.
2. Content gated behind an interaction
Tabs, accordions, and "load more" buttons that fetch or render their content only after a click work fine for a real visitor. Crawlers generally don't click, hover, or type, so content that only appears after a user interaction, rather than existing in the DOM and simply being toggled with CSS, doesn't get seen.
3. A render that fails silently
JavaScript errors, a missing browser API your script assumes is available, or a dependency on local storage or a cookie the crawler never sets, can all cause a render to fail partway through. When that happens, what gets indexed can be just the initial shell, an empty <div id="root"></div> with nothing in it. This is the hardest version to catch, because it never shows up when you test the page yourself. Your browser has none of the restrictions the crawler's renderer does, so the failure simply doesn't happen for you.
4. Blocking the resources the renderer needs
If robots.txt disallows the JavaScript or CSS files your page depends on, the renderer can't fetch them, and can't produce an accurate rendered version even though the page works perfectly for a real visitor who isn't subject to that same block. This used to be a common, well-documented mistake, and it's worth a direct check rather than an assumption that it's not happening.
How to Check What a Crawler Actually Sees
| Check | What it shows | What to look for |
|---|---|---|
| curl the page URL | The exact raw HTML response, no JavaScript executed | Is your key content, headline, body text, actually present in this output, or only a shell? |
| Browser DevTools, Elements panel | The fully rendered DOM after your JavaScript runs | Compare this against the curl output. A big gap between the two is the thing to investigate. |
| Google Search Console, URL Inspection, "Test Live URL" | The rendered HTML and screenshot Google's own renderer produced, plus any JavaScript console errors it hit | Does Google's rendered version match what you see in your own browser? Are there console errors you haven't seen before? |
| A public rendering/testing tool (such as Google's Rich Results Test) | A rendered view and console errors, without needing Search Console access | Same as above, useful as a quick check without verifying site ownership first |
| robots.txt | Which paths are disallowed | Confirm your JavaScript bundles and CSS files aren't blocked |
The Search Console and Rich Results checks are worth doing specifically because they show you JavaScript console errors from Google's own render, errors that may never appear in your own browser if your environment differs even slightly from the crawler's.
What to Do If Content Is Missing From the Rendered Version
The most reliable fix is making sure the content that matters for search is present in the initial HTML response rather than depending entirely on a client-side fetch, whether that's through server-side rendering, static generation, or just moving critical text into the server response instead of a JavaScript-only render. For interactive content, keep the underlying text in the DOM and use CSS to show or hide it, rather than fetching or constructing it only after a click. Fix any console errors the render tools surface, and make sure your JavaScript and CSS aren't disallowed in robots.txt.
None of this requires abandoning a JavaScript framework. It requires treating the raw HTML response as something worth checking on its own, separate from however good the page looks once your own browser has finished running everything. A technical SEO check that looks at crawlability directly is a useful second opinion alongside the manual checks above, especially across more pages than you'd want to check by hand.
Frequently asked questions
Final Thoughts
The core issue here isn't that JavaScript and search don't mix. It's that the view you test against, your own browser, with JavaScript always enabled and always succeeding, skips past every state a crawler actually has to deal with. That gap is invisible by default, which is exactly why it's worth checking on purpose rather than assuming a page that looks right to you looks the same way to everything else reading it.
The checks themselves are quick: a raw HTML fetch, a look at Search Console's rendered view, a scan of robots.txt. None of them require deep SEO expertise, just a willingness to look at the version of the page that isn't the one you're used to seeing.
If your site leans on client-side rendering for anything you actually want indexed, it's worth running these checks now rather than after noticing pages that should be ranking aren't.
How FlawPilot helps
FlawPilot finds security and quality issues in your AI-built app and shows you how to fix them. It checks your deployed site across security, performance, infrastructure, and SEO, and scans your source code for vulnerabilities, hardcoded secrets, and vulnerable dependencies.
Every finding is prioritized and explained in plain English, with the actual fix: the configuration change, DNS record, security header, or code change needed. For supported findings, AI-powered guidance adds step-by-step instructions and suggested code fixes.
Connect your Git provider to scan your repository alongside your live site, so application findings, code vulnerabilities, secrets, and dependency issues all land in one place.
It fits your existing workflow too: a REST API for scores and findings, an embeddable security badge, and an MCP server so tools like Claude, Cursor, or ChatGPT can read your findings and help you work through them.
The boundaries are clear: the public website scan reads only publicly accessible signals, with no agent or credentials required, and source-code scanning is opt-in and read-only. Fixes are never applied or merged without your review.
Verify your AI-generated app is production-ready.
117 security checks in 60 seconds - free, no account needed.
Scan one page
Enter a URL - no account, no install.
Run a Site Health check
Requires a free accountCrawls every page we can reach and scores each one, so a slow template deep in the site stops hiding behind a healthy homepage.
Scan your source code
Requires a free accountConnect a Git provider to check for vulnerabilities, secrets, and risky dependencies.