Skip to content

What is prerendering? ​

The problem ​

A single-page application (SPA) ships a near-empty HTML document and builds the page in the browser with JavaScript:

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

A real browser runs app.js, fetches data, and renders the content. Many crawlers and scrapers do not. When they request the page they see an empty <div id="root"></div> - no headings, no text, no links, no meta tags.

This affects:

  • Search engines that do not execute JavaScript, or execute it on a delay.
  • Social media scrapers (Facebook, X/Twitter, LinkedIn, Slack, WhatsApp, Discord) that read <meta property="og:*"> tags but never run scripts, so link previews come out blank.
  • Other automated consumers - monitoring, archiving, link checkers.

The solution: prerendering ​

Prerendering (also called dynamic rendering) puts a renderer between your app and the crawler:

  1. A bot requests https://your-app.com/products/42.
  2. Your reverse proxy detects the bot and forwards the request to the prerender service instead of your static files.
  3. The prerender service loads the page in headless Chromium, waits for the client-side rendering to finish, and captures the resulting HTML.
  4. That fully-rendered HTML is returned to the bot.

Human visitors are unaffected - they still get the normal SPA and its client-side navigation.

                         ┌──────────────────────────┐
   Bot request ─────────▶│      Reverse proxy       │
                         │  (is this a crawler?)    │
                         └───────┬──────────┬───────┘
                            yes  │          │  no
                                 ▼          ▼
                   ┌──────────────────┐   ┌──────────────┐
                   │ headless-prerender│   │ static files │
                   │  headless Chrome │   │  / your CDN  │
                   └────────┬─────────┘   └──────────────┘
                            │
                     fully-rendered HTML

Google now renders JavaScript for most pages and describes dynamic rendering as a workaround rather than a long-term recommendation. It remains useful when:

  • Your content must be crawlable by engines and bots that do not run JavaScript (many do not).
  • You need reliable social link previews immediately after publishing.
  • Server-side rendering (SSR) is not practical for your stack right now.

If you can adopt SSR or static generation, that is usually the better long-term answer. headless-prerender exists for the cases where you cannot.

How it differs from SSR ​

SSRPrerendering
Where HTML is builtYour server, per requestA headless browser, on demand
App code changesYes - app must run server-sideNone
ServesEvery visitorUsually only bots
FreshnessReal-timeReal-time, or cached

Released under the MIT License.