Skip to content
Back to the Lab

The Speculation Rules API Explained

A deep technical guide to the Speculation Rules API, covering prefetch and prerender rules, eagerness levels, document rules with URL and selector matching, what changes for a prerendered page, safety restrictions, and current browser support.

A dark Egnworks banner representing a browser silently prerendering the next page before a click.

Every ordinary navigation starts from zero the moment a visitor clicks a link. The browser resolves DNS, opens a connection, sends the request, waits for a response, then parses and renders whatever comes back, all after the click has already happened. The Speculation Rules API lets a page tell the browser to do some or all of that work in advance, for a link the visitor has not clicked yet, so the navigation that eventually happens has less left to do or nothing left to do at all.

Why a Click Has Always Started From Zero#

A <link rel="prefetch"> hint has existed for years and tells the browser to download a resource ahead of time, but for a full page navigation this only saves the network round trip. The browser still has to parse the HTML, discover and fetch subresources, run scripts, and lay out the page after the click, which is most of the actual work involved in a slow feeling navigation.

A separate, nonstandard <link rel="prerender"> existed in Chrome for a period and went further, but it offered no way to control when prerendering happened, which links qualified, or how many speculative loads ran at once, and different browsers implemented it inconsistently or not at all. The Speculation Rules API replaces both with a single, structured mechanism that covers prefetching, full prerendering, and the safety and control primitives that a heuristic like this needs.

Prefetch and Prerender Are Not the Same Thing#

Rules are declared as JSON inside a <script type="speculationrules"> element, under two possible top level keys.

<script type="speculationrules">
{
  "prefetch": [{ "urls": ["/pricing"] }],
  "prerender": [{ "urls": ["/docs"] }]
}
</script>

A prefetch rule downloads the response body ahead of time, so the network request is already finished by the time the visitor clicks, but the browser still parses, runs scripts, and renders after the click. A prerender rule goes further, loading the destination into a hidden, fully rendered background tab, including running its JavaScript, so that clicking the link only has to swap that already rendered tab into view. Prerendering costs more, both in bandwidth and in the resources spent rendering a page that might never be viewed, which is why it needs more deliberate targeting than prefetching does.

Writing Rules by URL List#

The simplest rule form lists exact URLs to prefetch or prerender.

<script type="speculationrules">
{
  "prerender": [
    { "urls": ["/product/hats", "/product/shoes"] }
  ]
}
</script>

This works well for a small, known set of likely next pages, such as the next page of a paginated list, but it does not scale to a page with dozens or hundreds of links where the destination is not known ahead of time.

Writing Rules by Document Pattern#

A document rule matches links already present on the page instead of listing URLs by hand, using a where clause built from href_matches, selector_matches, and the logical operators and, or, and not.

<script type="speculationrules">
{
  "prerender": [
    {
      "where": {
        "and": [
          { "href_matches": "/product/*" },
          { "not": { "selector_matches": ".no-prerender" } }
        ]
      }
    }
  ]
}
</script>

This rule prerenders every link whose URL matches the /product/* pattern, excluding any link carrying a no-prerender class, without the page needing to know those URLs in advance. A single document rule like this can cover an entire category of links across a site that changes its content constantly, such as a product catalog or a blog index.

Controlling When Speculation Starts With Eagerness#

Prerendering every matching link the instant the rule is parsed would waste bandwidth on links the visitor never intends to follow. The eagerness field controls how confident the browser needs to be before it starts.

EagernessWhen speculation starts
immediateAs soon as the rule is evaluated, the default for URL list rules
eagerAfter roughly 10 milliseconds of pointer hover on desktop, or shortly after a link becomes visible on mobile
moderateAfter roughly 200 milliseconds of hover or on pointer down on desktop, or after scrolling settles near the link on mobile
conservativeOnly once the visitor has actually pressed down on the link, the default for document rules
<script type="speculationrules">
{
  "prerender": [
    {
      "where": { "href_matches": "/product/*" },
      "eagerness": "moderate"
    }
  ]
}
</script>

moderate is a reasonable default for document rules covering many links, since it only spends resources on links a visitor has shown some intent toward, while conservative is closer to guaranteed intent at the cost of less time to actually finish prerendering before the click lands.

What Changes for a Prerendered Page#

A page loading inside a prerendered tab is not actually visible yet, so a number of platform features that assume an active, foreground page are deferred until the tab is activated. Geolocation, camera and microphone access, notifications, storage persistence prompts, and service worker registration all wait for activation rather than running during prerendering. window.alert, confirm, and prompt return immediately without blocking, and cross-site navigation and cross-origin iframe loading are restricted while the page is still hidden.

None of this requires special handling for a typical content page, but a page that fires an analytics event or starts a session timer as soon as it loads needs to account for the possibility that this happens during prerendering, before the visitor has actually seen anything.

Detecting a Prerendered Page in Code#

document.prerendering reports whether the current page is currently in the prerendered, not yet activated state, and the prerenderingchange event fires the moment it becomes the active page.

if (document.prerendering) {
  // defer analytics until the page is actually seen
} else {
  sendPageViewEvent();
}

document.addEventListener("prerenderingchange", () => {
  sendPageViewEvent();
});

A server can perform the equivalent check by watching for the Sec-Purpose request header, which carries prefetch or prefetch;prerender on a speculative request, useful for a backend that wants to avoid counting a prerender as a real page view before the client side check above even runs.

Rules That Should Never Be Prefetched or Prerendered#

Speculatively loading a URL runs whatever that page does on load, which is unsafe for a URL whose mere loading has a side effect.

URL typeWhy it is unsafe to speculate
Sign-out linksLoading the page logs the visitor out before they clicked anything
Add-to-cart or checkout actionsLoading the page can add an item or charge a payment method
Links that consume a limited allowance, such as a one-time downloadLoading the page burns the allowance without an actual visit
Ad click and conversion tracking linksLoading the page fires a tracked click that never really happened

A where clause that excludes these URLs by pattern or by a marker class, the same way the earlier not: { selector_matches } example excluded .no-prerender, keeps a broad document rule from accidentally covering something like this.

Browser Support Today#

Speculation rules currently run in Chromium based browsers, including Chrome, Edge, and Opera. Firefox has no support, and Safari does not support it either as of this writing. Because the feature is declared as inert JSON inside a script tag, a browser without support simply ignores it entirely rather than erroring, which makes it safe to ship as a progressive enhancement without a feature detection branch, though HTMLScriptElement.supports("speculationrules") is available for code that wants to confirm support before relying on the behavior it produces.

Conclusion#

The Speculation Rules API turns “load the next page before the click” from a browser specific hack into a declarative, JSON based mechanism with real controls over scope, timing, and safety. Prefetch and prerender cover different amounts of the work a navigation eventually needs, document rules let a single declaration cover links a page did not know about in advance, and eagerness levels tune how much confidence the browser needs before it spends the bandwidth. With support currently limited to Chromium based browsers, it is a genuine progressive enhancement today, one that makes navigation feel instant for the visitors whose browser supports it, without changing anything for the ones whose browser does not.

References#

MDN: Speculation Rules API

MDN: script type=“speculationrules”

Chrome for Developers: Prerender Pages in Chrome

Can I Use: Speculation Rules