Googlebot Rendering

Written by Backbone Tutorials Team

Last updated: June 2026 · 9 min read

It helps to picture the thing actually doing the work. When Google renders your page, a headless browser opens it on a server, runs your scripts, and hands the finished DOM to the indexer. That browser is the Web Rendering Service, and knowing how it behaves, what it keeps, what it throws away, and what it simply will not do, explains most of the surprising results in JavaScript SEO.

This guide opens that black box. It goes a level below how Google crawls JavaScript and rendering and indexing, and supports the SEO for single page apps overview.

Crawler and renderer Googlebot crawls a URL, the Web Rendering Service runs its JavaScript in headless Chromium, and the rendered DOM goes to indexing. Googlebotcrawls the URL Web Rendering Serviceevergreen headless Chromium Indexingrendered DOM
Googlebot fetches; the Web Rendering Service runs the JavaScript in headless Chromium; the rendered DOM is what gets indexed.

Meet the Web Rendering Service

The renderer is not a stripped-down approximation of a browser; it is Chromium. Google runs it headless on its own infrastructure, and it executes your JavaScript the way a visitor's Chrome would, building the same DOM.

Evergreen, headless Chromium

Just as important, it is evergreen: Google keeps the renderer close to the current stable Chrome rather than freezing it on an old version, which it did for years. In practice that means modern JavaScript and CSS features you would use for users generally work for the renderer too. The caution is that it runs headless and automated, so anything that assumes a real, interactive person can still behave differently.

Stateless by design

Each render starts from a clean slate. The renderer does not carry state from one page to the next, or from a user's earlier session, because there is no user and no session.

No persistent storage between renders

Cookies, localStorage, sessionStorage, IndexedDB, and service-worker caches are not a reliable place to keep anything the render depends on; treat each render as the very first visit. If your app shows content only after reading stored state, the renderer sees the empty first-run version. Anything that must be indexed has to render from the URL alone.

How resources are fetched and cached

To render, the service fetches your scripts, styles, and data, but it does not fetch the way a fresh browser does. To save work across the web, it caches resources aggressively and on its own schedule.

Aggressive caching of resources

<!-- Version the filename so a deploy is a new URL the renderer must refetch -->
<script src="/assets/app.4f9a2c.js"></script>

Because the renderer may reuse a cached copy and can ignore your cache-control headers, an old bundle can render against new HTML, producing strange, hard-to-reproduce bugs. The fix is fingerprinting: put a content hash in each filename so every deploy changes the URL, forcing a fresh fetch. This is also why a fix can seem to take a while to show up in rendered output.

Timeouts and resource budgets

Rendering at web scale cannot wait forever on any one page. The service works within time and resource limits, and a page that is slow or blocks on a critical resource risks being captured before it finishes.

Why slow resources risk a partial render

If a key script or data request is slow, the rendered snapshot can miss the content it would have produced, which then looks like thin or missing content to the indexer. The defense is the same as for users: keep critical resources fast and unblocked, avoid long chains of dependent requests, and get meaningful content into the markup early rather than after a slow round trip.

What the renderer refuses to do

The renderer behaves like a cautious, non-interactive browser. It will not perform the actions a curious human would, and it declines anything that would normally prompt the user.

Denied permissions and unavailable APIs

It does not click, scroll to load more, or accept dialogs, and it automatically denies permission requests such as geolocation, notifications, and camera access. Features that depend on a granted permission or a real interaction simply do not run. Design so that content never hides behind any of these: if a feature needs permission to work, its content must still render when that permission is refused.

Mobile-first, crawler versus renderer

Two roles are easy to conflate. Googlebot is the crawler that fetches URLs and resources; the Web Rendering Service is what runs the JavaScript afterward. They are stages in one pipeline, not the same thing.

Crawler, renderer, and the mobile viewport

Under mobile-first indexing, the crawling and rendering use a mobile configuration, so the mobile version of your page is what counts. Make sure your content, links, and structured data are present in the mobile rendering, not just the desktop one. A site that hides text or links on mobile is hiding them from the renderer that matters. With the renderer demystified, the next guide applies all of this to the hardest case, getting a full single page app indexed.

Frequently Asked Questions

What is the Web Rendering Service?

The Web Rendering Service is Google's headless, evergreen Chromium-based renderer. It loads a crawled page, runs its JavaScript, and produces the DOM that Google then indexes, so it is effectively a real browser working on your page behind the scenes.

Does Googlebot use the latest Chrome?

The renderer is evergreen, meaning Google keeps it close to current stable Chrome, so modern JavaScript and CSS features generally work. It is still wise to test, since there can be a small lag and some APIs behave differently in a headless, automated context.

Does Googlebot keep cookies or localStorage?

No. Renders are stateless. Cookies, localStorage, sessionStorage, and similar state are not carried between renders, so content that depends on stored state from a previous visit will not appear. Anything important must render without it.

Why does Googlebot render an old version of my JavaScript?

The renderer caches resources aggressively and may ignore your cache-control headers, so an old bundle can be reused. Fingerprint your filenames, so each deploy produces a new URL the renderer is forced to fetch fresh.

Read next: back to the JavaScript SEO hub, or revisit rendering and indexing for what the render produces.

Building for the renderer?

Fast, stateless-friendly pages start in the frontend. See how a single page app is structured in the complete Backbone guide.

Explore the Backbone Guide →