JavaScript Speculation Rules API Table

PieceWhat it doesField note
<script type="speculationrules">The declarationJSON rules inline or via server header - declarative prefetch/prerender, no JS required
prefetchThe cheap depthFetch the next document into cache - click still navigates, just warm; cross-origin friendly-ish
prerenderThe deep depthFull hidden render: HTML, subresources, scripts run, paint done - click becomes a process swap
eagernessThe budget dialconservative (pointerdown) / moderate (hover) / eager / immediate - moderate is the CMS default
document rulesThe auto modehref_matches + selector_matches crawl your own links - exclude logout/search/admin explicitly
document.prerenderingThe analytics guardScripts run while hidden - gate beacons, timers and autoplay on prerenderingchange or count ghost visits
activationThe instant swapClick on a prerendered page = process swap; server sees speculation requests marked in headers
support truthThe degradationChromium only; others ignore rules and navigate normally - strictly progressive, no polyfill worth it
Reference: the MDN Speculation Rules API. Declarative speculation with budgets: prefetch the plausible, prerender the likely - and the browser enforces its own memory/network caps while your rules decide where the spend goes.
Bottom line: eagerness is a budget dial - moderate (hover intent) is almost always the answer, with prerender reserved for the two or three genuinely-likely next pages. The engineering risk is not support (unsupported engines just navigate normally) but self-deception: prerendered pages run your analytics while INVISIBLE, so document.prerendering gates every beacon, timer and autoplay - ungated, you counted visits that never happened and autoplayed into the void. Measure activation rates in DevTools and server logs: a prerender nobody clicks was bandwidth donated to nobody.
Related tools: the view transitions table (the animation half of instant navigation), the service worker table (the programmatic caching sibling), the performance timing table (the numbers that prove the win), and the history table (the navigation machine the speculations feed).

The Speculation Rules API is declarative prefetching and prerendering by JSON: a <script type="speculationrules"> block (or a server header) tells the browser which links to speculate on and how eagerly - prefetch fetches the next document, prerender builds the entire hidden page (HTML, subresources, scripts executed, paint done) so the click swaps instantly. This is Chrome's successor to the old <link rel=prerender>, rebuilt with budgets and discipline.

Bottom line: eagerness is a budget dial, and the wrong setting is expensive. 'Immediate' prerenders every matching link on load - massive bandwidth and server spend; 'moderate' (hover/pointerdown) is the CMS default because hover intent is cheap and accurate; 'conservative' (pointerdown only) speculates on commitment. The pairing rule: prerender your highest-probability next pages with moderate-or-eager, prefetch broadly and cheaply - and remember every prerendered page executes your analytics and scripts while INVISIBLE, which is why document.prerendering exists.

The honest part: this is a Chromium-only accelerator - Safari and Firefox ignore speculation rules entirely, which is fine, because the API degrades to normal navigation at zero cost. The engineering risk is not support, it is self-deception: analytics that count prerendered pages as visits, side effects that should wait for activation (counters, polls, audio, auth refreshes), and server logs full of requests users never saw. The API hands you the flag (document.prerendering and the prerenderingchange event) - using it is your job.

How to use

  1. Start with the CMS default: <script type="speculationrules"> {"prefetch": [{"source": "document", "where": {"href_matches": "/*"}, "eagerness": "moderate"}]} </script> - same-site links prefetched on hover/pointerdown: cheap, safe, and the entire setup for most content sites.
  2. Prerender the certain next pages: add a prerender rule scoped tighter - the search-results-to-listing pair, the checkout's next step, the docs' next-page link - with eagerness 'moderate' or 'eager'. Reserve 'immediate' for paths you are confident enough to pay for.
  3. Scope with document rules: where accepts href_matches (with :no-prefix patterns), selector_matches (the link's CSS context - e.g. inside the pagination nav), and not_/and_ combinators - crawl-your-own-link-graph declaratively, excluding logout/search/admin URLs explicitly.
  4. Guard analytics with the prerendering flag: if (document.prerendering) wait for prerenderingchange before counting the visit, starting timers, or polling - the page's scripts run while hidden, so an ungated counter invents visits and a media element autoplays into the void.
  5. Watch it work: Chrome DevTools' Performance panel shows preloads, and the server sees the speculation requests - tune budgets by measuring which prerenders actually activate; a prerender that never gets clicked was bandwidth and CPU donated to nobody.

Frequently asked questions

What is the real difference between prefetch and prerender here?

Depth. Prefetch fetches the next document's bytes (optionally its key subresources with 'prefetch' rules listing URLs) into cache - the click still performs a normal navigation, just one that hits warm cache. Prerender builds the WHOLE page in a hidden renderer: HTML parsed, CSS applied, scripts executed, layout painted - activation is a process swap, effectively instant. The cost curve matches: prefetch is bandwidth; prerender is bandwidth plus CPU plus every script side effect running before the user arrives. Practical pairing: prefetch broadly (all same-site links, moderate), prerender narrowly (the two or three genuinely-likely next pages). Cross-origin destinations are prefetch-only territory - prerendering cross-site pages needs special server cooperation and is rarely what you want.

Which eagerness level should I ship?

Moderate, almost always. The levels trade bandwidth against latency: conservative speculates on pointerdown (last-moment, small win), moderate adds hover/pointerenter intent (the sweet spot - hovering a link is a strong signal and costs a few hundred ms of lead time), eager speculates on content visibility, immediate on page load (only for rules so confident the spend is trivial). The exception logic: static documentation or article sites can afford eager on next-page links; anything with per-request server cost needs moderate plus scope pruning. Measure, then tune: DevTools and server logs show activation rates - an eagerness level whose prerenders mostly expire unused is a dial turned past your traffic's reality.

How do I keep my analytics honest with prerendered pages?

Gate every measurement and side effect on document.prerendering. A prerendered page runs your scripts BEFORE the user clicks - so an analytics beacon that fires on load records a visit that never happened; a polling loop starts its cadence in secret; a cookie-consent or auth-refresh flow mutates state for a page the user may never see. The pattern: if (document.prerendering) { await new Promise(r => document.addEventListener('prerenderingchange', r, {once: true})); } - then initialize. Server-side, the Speculation-Rules and Sec-Purpose headers mark speculation requests so logs can exclude them. This is the API's main tax: it moves 'when does my code really start' from load to activation, and every timer, beacon and autoplay must move with it.

What happens in Safari and Firefox?

Nothing, by design - and that is the feature. Unsupported browsers ignore the speculationrules script tag entirely; links navigate the way they always did. There is no polyfill worth installing (the point of the API is the browser's internal prerender pipeline; JavaScript cannot fake a process swap), so the honest stance is strictly progressive enhancement: ship the rules, measure on Chromium, and never gate functionality on speculation happening. The one caveat is duplication: legacy <link rel=.prefetch> tags and speculation rules should not both target the same URLs (double-fetch bookkeeping), so consolidate on speculation rules where Chromium coverage is what you are optimizing and let the other engines' own prefetch heuristics do their quiet thing.

Related tools