On this page
Speculation Rules API: Zero-Latency Navigation Without an SPA Router
The Speculation Rules API lets an MPA prerender the next page before the click, without the bundle cost or hydration overhead of a client-side router.
Summary: The Speculation Rules API allows the browser to prefetch or prerender future page navigations based on declarative rules, such as hovering over a link or scrolling it into the viewport. This provides the instant-loading, zero-latency feel of a Single Page Application (SPA) on a genuine Multi-Page Application (MPA) architecture, without the heavy client-side JavaScript bundle costs.
At a glance
| Property | Answer |
|---|---|
| API | Speculation Rules API |
| Spec | WICG Speculation Rules |
| Availability | Limited / not Baseline |
| Desktop support | Chrome, Edge |
| Safari | Disabled behind flag |
| Firefox | Positive standards position, not shipped |
| Secure context | Required |
| Main use | Zero-latency MPA navigation |
Disclosure: We implement these architectures for clients and use them on our own infrastructure.
The SPA-router argument for client-side routing has always been the same: full page navigations feel slow, so eliminate them. Ship one JavaScript bundle, keep the app running, and swap DOM subtrees on navigation. The perceived-speed win was real, but it justified a real cost. That cost included massive bundle sizes, heavy hydration passes, and complex state management.
The Speculation Rules API removes the justification. It lets the browser prerender the next real page—same origin, real HTML document, real navigation—before the user clicks. When the user eventually clicks the link, the navigation is already sitting in memory. You get the SPA’s perceived speed on an actual multi-page architecture, with none of the client-side routing weight.
What it replaces, and what it doesn’t
<link rel="prefetch"> has existed for years. It downloads a document’s bytes into the HTTP cache and does nothing else. It performs no rendering and initiates no subresource loading. <link rel="prerender"> was a Chrome-only predecessor that did a full invisible render, but it was expensive, prone to side effects, and never shipped anywhere else. Chrome eventually deprecated it.
Speculation Rules replaces both with a single declarative API and two distinct actions:
| Action | What happens | Cost | Use for |
|---|---|---|---|
prefetch | Downloads the HTML document body only. No subresources, no JS execution. | Low | Broad application - most links on your site |
prerender | Fetches the document, loads subresources, executes JavaScript, renders into an invisible tab. | High | Sparingly - high-confidence next pages only |
That cost asymmetry should drive your rule design. MDN’s own guidance is blunt about it: adopt prefetch broadly, but adopt prerender narrowly.
Declarative rules, not URL hardcoding
Rather than manually injecting <link> tags into the DOM, you supply the browser with a JSON-based rule set.
<script type="speculationrules">
{
"prefetch": [{
"source": "document",
"where": { "href_matches": "/specs/*" },
"eagerness": "moderate"
}],
"prerender": [{
"source": "document",
"where": { "href_matches": "/pricing" },
"eagerness": "eager"
}]
}
</script>
source: "document" means the rule applies to links present in the current document, matched by pattern. You are not hardcoding a URL list that goes stale as pages are added or removed. where.href_matches scopes the rule to a section of the site. Finally, eagerness controls the trigger condition.
| Eagerness | Desktop trigger | Mobile trigger (from Jan 2026) |
|---|---|---|
immediate | On page load | On page load |
eager | 10ms hover | 50ms after link enters viewport |
moderate | 200ms hover, or pointerdown | pointerdown (no hover event) |
conservative | pointerdown only | pointerdown only |
The eager setting on mobile is new as of January 2026, and it is the setting most likely to surprise you. It fires from viewport intersection alone, with no interaction required. That is appropriate for a small number of high-confidence destinations (like a primary CTA), but inappropriate applied broadly, because it starts speculating on links the user is merely scrolling past.
The resource ceiling
Chrome enforces hard limits so a careless rule set cannot consume unbounded resources:
immediate/eager: up to 50 concurrent prefetches, 10 concurrent prerendersmoderate/conservative: up to 2 concurrent prefetches, 2 concurrent prerenders (FIFO - new speculations evict the oldest)
Chrome also disables speculation entirely under three conditions: Save-Data mode enabled, Battery Saver with low charge, or if the user has turned off the browser’s “Preload pages” setting. These are conditions you cannot override from your rule set. The API is built so that aggressive speculation degrades safely on constrained devices rather than destroying a user’s battery or data plan.
Yielding the main thread during prerender
A prerendered page executes its full JavaScript in the background, inside an invisible tab. If that JavaScript does anything expensive on load—such as a large synchronous initialization routine or a big client-side data transform—it competes for the same main-thread budget as your currently visible tab.
You must break long synchronous work into yielding chunks so a prerender in progress does not starve the foreground page.
// Anything that runs on page load and could be expensive
// should yield periodically, prerendering or not.
async function processInBackground(items) {
for (let i = 0; i < items.length; i++) {
processItem(items[i]);
// Yield every 50 items so a prerendering tab doesn't
// monopolize the main thread the foreground tab shares.
if (i % 50 === 0) {
await new Promise(resolve =>
'scheduler' in window
? scheduler.yield()
: setTimeout(resolve, 0)
);
}
}
}
scheduler.yield() is the purpose-built API for this. setTimeout(resolve, 0) is the fallback where it is unavailable. Either way, the discipline is the same one that matters for long tasks generally. This is not a Speculation Rules–specific concern, but prerendering makes it a background issue you can easily forget about until it shows up as jank on the foreground page.
prerender_until_script: real, but very new
A third action landed in Chrome 144 (January 2026): prerender_until_script. It fetches the document, renders it, and loads CSS, images, and fonts. However, it explicitly pauses JavaScript execution at the first blocking <script> tag.
The design goal is specific: avoid the side effects of full prerendering (like an analytics pageview firing on a page the user never actually visits) while still paying the render and asset cost up front. As of this writing, it is a very recent Chrome release that is still working through W3C TAG review. It is usable in Chrome 144+ today, but it is not yet a cross-browser guarantee.
<script type="speculationrules">
{
"prerender": [{
"source": "document",
"where": { "href_matches": "/blog/*" },
"eagerness": "moderate"
}]
}
</script>
Chrome 144+ users get prerender_until_script semantics automatically where applicable. There is no separate opt-in syntax to write today beyond the standard prerender rule. Verify its interaction with your third-party scripts directly before relying on it, as a script positioned differently than you expect changes exactly where execution pauses.
Browser support and rollout strategy
Speculation Rules are currently limited to Chromium-based browsers, though other vendors have signaled support for portions of the spec.
| Browser | Support |
|---|---|
| Chrome | prerender key from Chrome 105, prefetch from 110. |
| Edge | Same as Chrome. |
| Safari | Implemented in Safari 26.2. Disabled by default. |
| Firefox | Has declared a positive standards position on prefetch. Not shipped. |
The API is explicitly designed to degrade safely. Unsupported browsers ignore the <script type="speculationrules"> block entirely, with no error thrown and no fallback code required. That makes it a genuine progressive enhancement.
If your audience skews toward Safari—common for premium consumer products—the measured win on your actual traffic will be smaller than a Chrome-only benchmark suggests. Always measure on your own analytics-segmented traffic, not on a global browser-share estimate.
What actually needs auditing before you ship
Unsafe speculation conditions. The spec defines cases where prerendering a URL is unsafe by default, such as pages with side effects on load or pages behind authentication. A page that fires a purchase-confirmation event or logs an analytics pageview on load should not be a prerender target. Prerendering executes that code whether or not the user ever arrives.
Cross-site limits. prefetch works across origins with strict restrictions. prerender largely does not work cross-origin at all. Design your rules entirely around same-origin navigation.
CSP. Speculation rules use a <script> element. A site with a strict Content-Security-Policy needs inline-speculation-rules added to the script-src directive, via a hash or nonce source. Otherwise, the rules are silently ignored by the browser.
Combining with the rest of your architecture
The highest-leverage pairing on this site is Speculation Rules plus the View Transitions API on cross-document navigation.
A prerendered page that cross-fades in via a native view transition eliminates both problems SPA routing existed to solve: navigation latency, and the jarring hard cut of a full page load. You achieve this on a genuine MPA, with two declarative browser features, and zero client-side routing code.
Frequently asked questions
Does the Speculation Rules API work in Safari and Firefox?
Safari 26.2 has an implementation disabled by default. Firefox has declared a positive standards position on prefetch but has not shipped it. The API degrades safely in unsupported browsers—no fallback code is required.
What is the difference between prefetch and prerender?
prefetch downloads the HTML document only, with no rendering or JavaScript execution, making it a low-cost action safe to apply broadly. prerender does a full invisible render including asset loading and JavaScript execution, at a cost roughly comparable to rendering an <iframe>. Reserve it for high-confidence destinations.
Is prerender_until_script shipped and stable?
It shipped in Chrome 144 (January 2026) and is usable today, but it is recent and still moving through standards review. Treat it as current-but-young rather than settled, and verify its interaction with your third-party scripts directly.
Will Speculation Rules replace my SPA router?
For content sites, marketing pages, documentation, and blogs, yes—especially in combination with an MPA architecture and View Transitions. For a genuine web application with persistent client state, it solves navigation latency but doesn’t address the reasons you manage client state in the first place.
Does prerendering execute JavaScript on the target page?
Yes, unless you are relying on prerender_until_script, which explicitly pauses at the first blocking script. Standard prerender executes fully. This is exactly why unsafe-to-prerender pages (anything with load-time side effects) must be excluded from your rules.
How do Speculation Rules interact with the HTTP cache?
Documents fetched via a prefetch rule are placed directly into the standard HTTP cache, making them instantly available for the next navigation. Pages loaded via a prerender rule are held in a special, hidden in-memory prerender map until the user navigates, at which point the invisible tab is swapped to the foreground.
Can I use Speculation Rules to prefetch cross-origin pages?
Yes, but with strict limitations. Cross-origin prefetches are permitted, but they require the target origin to explicitly opt-in by responding with specific CORS headers and the No-Vary-Search header to prevent cache partitioning issues. Cross-origin prerender is heavily restricted and generally unsupported to prevent cross-site tracking and side-channel attacks.
What happens if the user navigates before the prerender completes?
If the user clicks a link while the prerender is still executing in the background, the browser smoothly swaps the prerendering tab to the foreground. It simply completes the remaining load and render tasks as the active, visible tab, resulting in a significantly faster load than starting from scratch.
Sources
- MDN: Speculation Rules API
- MDN:
<script type="speculationrules"> - W3C TAG design review:
prerender_until_script
From the team at
We build digital products and explore the modern web standards behind them.