Dynamic rendering

Serving bots a pre-rendered HTML snapshot while people get the JavaScript app. A workaround for crawlers that cannot render the app.

send bots a pre-rendered pageshow Google HTML instead of JavaScriptcrawler gets a static versionmy JavaScript site is blank to botsspecial server rendering for Googlebotwe run prerender for Googlebotdo I still need prerendering for my React sitedinamic rendering

See it

Live demo coming soon

What it is

Dynamic rendering serves a crawler a pre-rendered HTML snapshot while ordinary visitors receive the JavaScript-heavy version of the same URL. A headless browser runs the page ahead of time, captures the DOM, and hands that result to bots that struggle with client-side rendering. Google's own Rendertron and the hosted Prerender.io service are the machinery most teams ended up using. It is different from server-side rendering, which sends useful HTML to everyone.

Reach for it as a temporary bridge around a legacy single-page app when important crawlers genuinely cannot see its content and a full rendering rewrite cannot ship yet. It can also cover non-search scrapers with weak JavaScript support. For new work, server-side rendering or static generation is usually simpler because users and bots share one output path.

The gotcha is maintaining two renderings. If the bot snapshot becomes stale, loses links, returns the wrong status, or contains meaningfully different content, debugging gets ugly and the difference can look like cloaking. Google describes dynamic rendering as a workaround, not a recommended long-term solution. Cache keys also have to separate crawler HTML from the normal app or one audience can receive the other audience's response.

Ask AI for it

Implement a temporary dynamic-rendering layer with Puppeteer and headless Chromium for the explicit crawler user agents I provide. Render each requested URL to HTML after the main content settles, preserve its HTTP status, canonical tag, meta robots tag, structured data, and real <a href> links, and cache the snapshot by full canonical URL plus renderer version. Send Vary: User-Agent so CDN caches cannot mix crawler and browser responses. Add an automated Playwright parity test that compares headings, body text, links, canonicals, and status codes between both versions and fails on a meaningful difference. Document the server-side rendering migration that will remove this layer.

You might have meant

server side renderingclient side renderingstatic site generationcrawlingindexingmobile first indexing