Skip to main content
Beta: Front-End Checklist is currently in beta. Some issues are still being fixed. Thanks for your patience.

Use the Speculation Rules API to prefetch and prerender navigations

The Speculation Rules API is used to declaratively prefetch or prerender likely next pages, making navigation feel near-instant without the overhead of a full client-side router.

Utilities
Quick take
Typical fix time 20 min
  • Use prefetch rules to load the next page's HTML ahead of time
  • Use prerender rules to fully render the next page in the background (instant navigation)
  • Scope rules with href-matches or CSS selector patterns to avoid wasting bandwidth
  • Prefer document rules (CSS selectors) over URL list rules for dynamic sites
Why it matters: Navigation latency is one of the biggest contributors to poor Interaction to Next Paint (INP) and overall perceived performance. Prerendering the most likely next page eliminates all network and rendering latency — the user sees the new page in under 100 ms regardless of server response time. Google Search has used this API to deliver its "instant" results page experience.

Rule Details

The Speculation Rules API lets you declaratively tell the browser which pages to fetch or fully pre-render in the background. Unlike the legacy <link rel="prefetch">, it supports dynamic CSS-selector-based rules and reports speculation status in DevTools.

Code Example

Speculation rules are declared as a JSON blob in a <script type="speculationrules"> block:

<script type="speculationrules">
{
  "prefetch": [
    {
      "where": { "href_matches": "/blog/*" },
      "eagerness": "moderate"
    }
  ],
  "prerender": [
    {
      "where": { "href_matches": "/checkout/confirm" },
      "eagerness": "eager"
    }
  ]
}
</script>

Why It Matters

Navigation latency is one of the biggest contributors to poor Interaction to Next Paint (INP) and overall perceived performance. Prerendering the most likely next page eliminates all network and rendering latency — the user sees the new page in under 100 ms regardless of server response time. Google Search has used this API to deliver its "instant" results page experience.

Prefetch vs Prerender

ModeWhat happensUser benefitCost
prefetchDownloads the next page's HTMLFaster TTFB on navigationLow bandwidth
prerenderDownloads + fully renders the page in a hidden tabNear-instant navigation (~0 ms)Higher CPU + bandwidth

Start with prefetch — it is lower risk. Graduate to prerender only for pages where you have high confidence the user will navigate there (e.g., the single next step in a checkout flow).

Document rules use CSS selectors to target links on the page — much easier to maintain than explicit URL lists:

<script type="speculationrules">
{
  "prefetch": [
    {
      "source": "document",
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": { "href_matches": "/logout" } },
          { "not": { "href_matches": "/admin/*" } },
          { "not": { "selector_matches": "[data-no-prefetch]" } }
        ]
      },
      "eagerness": "moderate"
    }
  ]
}
</script>

<!-- This link will not be prefetched or prerendered -->
<a href="/sensitive-page" data-no-prefetch>Sensitive page</a>

Eagerness Levels

LevelWhen speculation fires
immediateAs soon as the rule is parsed — highest bandwidth cost
eagerSame as immediate in current implementations
moderateWhen the user hovers over the link for ~200 ms
conservativeWhen the user starts to click (mousedown / touchstart)
<script type="speculationrules">
{
  "prerender": [
    {
      "source": "document",
      "where": { "href_matches": "/product/*" },
      "eagerness": "moderate"
    }
  ]
}
</script>

Next.js Integration

In Next.js (App Router), inject the script tag in the root layout:

// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
  const speculationRules = {
    prefetch: [
      {
        source: 'document',
        where: {
          and: [
            { href_matches: '/*' },
            { not: { href_matches: '/api/*' } },
            { not: { selector_matches: '[data-no-prefetch]' } },
          ],
        },
        eagerness: 'moderate',
      },
    ],
  }
 
  return (
    <html lang="en">
      <head>
        <script
          type="speculationrules"
          dangerouslySetInnerHTML={{
            __html: JSON.stringify(speculationRules),
          }}
        />
      </head>
      <body>{children}</body>
    </html>
  )
}

URL List Rules (Explicit)

Use URL list rules when you know exactly which pages to target:

<script type="speculationrules">
{
  "prerender": [
    {
      "urls": ["/checkout/confirm", "/checkout/success"],
      "eagerness": "moderate"
    }
  ]
}
</script>

Dynamic generation in JavaScript:

function injectSpeculationRules(urls: string[]) {
  if (!HTMLScriptElement.supports?.('speculationrules')) return
 
  const script = document.createElement('script')
  script.type = 'speculationrules'
  script.textContent = JSON.stringify({
    prefetch: [{ urls, eagerness: 'moderate' }],
  })
  document.head.appendChild(script)
}
 
// Inject rules for the next step in a wizard
injectSpeculationRules(['/onboarding/step-2'])

Feature Detection and Progressive Enhancement

Speculation Rules are supported in Chromium 109+ and ignored gracefully in all other browsers:

function supportsSpeculationRules(): boolean {
  return (
    typeof HTMLScriptElement !== 'undefined' &&
    HTMLScriptElement.supports?.('speculationrules') === true
  )
}
 
// Safe to check before injecting — browsers without support simply ignore the script
if (supportsSpeculationRules()) {
  console.info('Speculation Rules supported — prerendering enabled')
}

Debugging in DevTools

  1. Open DevToolsApplicationBackground servicesSpeculative loads
  2. Review the list of speculation candidates, their status (pending, fetching, ready, failed), and any blocking reasons

What NOT to Prerender

Keep speculation conservative and follow MDN's Speculation Rules API guidance (opens in new tab), because prerendering the wrong destination can waste bandwidth or trigger side effects before the user commits.

ScenarioWhy to avoid
Logout / destructive actionsCould trigger state changes during prerender
Authenticated personalised pagesMight serve wrong content or consume rate-limited resources
Heavy server-side operationsDoubles the load on your server
External / third-party URLsBrowsers block cross-origin prerenders
Pages behind POST actionsPrerender only supports GET requests
Prerender counts as a page view in analytics

A prerendered page executes JavaScript, including analytics initialisation. If the user never completes navigation to the prerendered page, you may see inflated page view counts. Modern analytics libraries (GA4, Plausible) handle the visibilitychange event to suppress views for pages the user never saw. Verify your analytics implementation handles this before enabling prerender at scale.

Support Notes

  • Verify the effective browser and network behavior in the project target browsers before treating this optimization as universally active.
  • Use a fallback note when protocol, preload, caching, or background execution behavior depends on browser or intermediary support.

Verification

  1. Add speculation rules and open DevTools → ApplicationSpeculative loads — confirm the target URLs appear with status Ready.
  2. Navigate to a speculated page and check the Network tab — the main document should be served from cache (size shown as "(prefetch cache)").
  3. Confirm that /logout, /api/*, and any authenticated mutation pages are excluded from the rules.
  4. Measure navigation performance with and without speculation rules using the Performance panel's LCP and FCP metrics.

Use with AI

Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.

Check

Verify implementation

Check whether the site uses the Speculation Rules API or equivalent prefetch/prerender techniques for likely navigation targets.

Fix

Auto-fix issues

Add a Speculation Rules JSON block targeting the most likely next-page links, starting with prefetch and graduating to prerender.

Explain

Learn more

Explain how the Speculation Rules API differs from rel=prefetch and rel=prerender, and how prerendering achieves near-zero navigation latency.

Review

Code review

Review speculation rule selectors for over-eagerness — flag patterns that would prerender unrelated pages, third-party URLs, or pages with personalised/authenticated content that should not be pre-fetched.

Sources

References used to support the guidance in this rule.

Rules that often go hand-in-hand with this one.

Use resource hints for faster loading

Implement preload, prefetch, and preconnect hints to optimize resource loading priority.

Performance
Use fetchpriority to hint resource loading priority

The fetchpriority attribute is applied to critical images, scripts, and preload links to help the browser prioritise the most important resources and defer lower-priority ones.

Performance
Load non-critical code on user interaction

Defer JavaScript modules, widgets, and third-party code until the user signals intent through a click, focus, hover, or similar interaction.

Performance
Load non-critical code when content approaches the viewport

Use viewport-aware loading to fetch components, embeds, and feature code shortly before they become visible instead of shipping them on first load.

Performance

Was this rule helpful?

Your feedback helps improve rule quality. This stays internal for now.

Loading feedback...
0 / 385