Speculation Rules: Prefetch and Prerender Boundaries
Compare Speculation Rules prefetch and prerender eligibility, activation, abandonment, credentials, side effects, and a safe fixture.
BotBrowser Team
Want the structured docs for Platform?
This article lives in the editorial library. For step-by-step setup, reference material, and ongoing updates, jump into the docs section.
BotBrowser can repeat an authorized browser context and record application-visible navigation outcomes, but it does not claim to enable, force, or measure Speculation Rules support in a particular browser build. The practical decision is narrower: use prefetch when an eligible future navigation may safely fetch a response, and use prerender only when the hidden document can be created, kept isolated, activated, or abandoned without unwanted work. The browser decides eligibility and lifecycle timing; an application supplies hints and a safe fallback.
TL;DR
prefetchprepares a response for a possible navigation, whileprerendercreates a hidden document that may later activate. Neither hint is a promise that the browser will fetch or render the target.- Eligibility depends on the rule source, URL, same-origin and cross-origin restrictions, policy, device conditions, and browser implementation. A matching rule is not an observation of a network request.
- Activation is a transition from a speculative document to the visible document. Abandonment can happen before activation, so initialization must tolerate a document that never becomes visible.
- Credentials, cookies, storage, analytics, media, WebSockets, and writes are side-effect boundaries. Keep speculative targets read-only and make a real activation explicit before committing state.
- A synthetic fixture can record rule input, request intent, activation, and abandonment separately without claiming that a live browser ran it.
Contents
- Prefetch and prerender are different promises
- Eligibility is a browser decision
- Activation and abandonment form a lifecycle
- Credentials, side effects, and privacy boundaries
- A copyable fixture and bounded record
- Choose a fallback from the observed boundary
- BotBrowser capability boundary
- Practical conclusion
Prefetch and prerender are different promises
The Speculation Rules API on MDN exposes a JSON rule format that lets a page describe likely navigations. The browser may use those rules to fetch a target or build a hidden target document. The page does not receive a synchronous “accepted” result from the rule parser, and the rule itself does not turn an ordinary link into a guaranteed warm navigation.
prefetch is the smaller promise. It asks the browser to retrieve a resource that could satisfy a later navigation. The response can be stored in a browser-managed cache or another internal preparation path. The target document is not exposed as the active page merely because bytes were fetched. JavaScript from that target is therefore not a reason to assume that application initialization already happened. A later navigation can still miss the speculative result because the URL, headers, policy, credentials, or browser state no longer match.
prerender goes further. The browser may create a hidden browsing context, load the target document, run its scripts under prerender restrictions, and keep it available for activation. The Chrome prerender documentation describes this as a lifecycle in which a hidden page can become the active page or be discarded. The hidden page is not a second visible tab and should not be treated as a background worker with unlimited permission to start product work.
The difference is operational. Prefetch mainly spends network and cache budget for a possible future response. Prerender can spend network, CPU, memory, storage reads, and initialization time for a possible future document. A team that cannot make the target idempotent and quiet should start with prefetch or no speculation. Faster activation is not worth sending a duplicate purchase, creating a session, opening a socket, or recording a page view before a person has navigated.
| Hint | What the browser may do | What the application may assume | Safer target shape |
|---|---|---|---|
prefetch | Fetch a candidate resource and retain it for a later navigation | Nothing until the real navigation reports its own state | Cacheable, read-only document or data |
prerender | Build a hidden document that may run eligible initialization and later activate | The target may never become visible and may be discarded | Read-only shell with deferred writes and clear activation handling |
| No hint | Perform ordinary navigation when requested | The request starts from the normal navigation lifecycle | Any flow with explicit user intent and server authorization |
These are browser behaviors, not BotBrowser controls. BotBrowser can help a team repeat a declared profile and inspect its own page's visible state, but the product cannot make a browser accept a rule, force activation, or convert a speculative fetch into a user navigation. The browser performance measurement guide is useful when a team needs to separate a timing mark from a navigation claim; a mark in a hidden page is not evidence of activation.
Eligibility is a browser decision
The WICG Speculation Rules specification defines the rule shape and the conditions a user agent considers when deciding whether to speculate. A typical document rule uses a prefetch or prerender source and a where condition, for example a same-origin URL pattern. The syntax is an input to a browser algorithm. It is not an imperative command and it does not expose every reason a candidate was skipped.
<script type="speculationrules">
{
"prefetch": [
{
"where": { "href_matches": "/docs/*" },
"eagerness": "moderate"
}
],
"prerender": [
{
"where": { "selector_matches": "a[data-prerender]" },
"eagerness": "conservative"
}
]
}
</script>
The example declares two candidate sets. It does not say that every /docs/ link will be fetched, that every marked link will be prerendered, or that the browser will preserve either result until a click. Conditions can exclude links, policy can prevent speculation, resource pressure can lower eagerness, and an implementation can support only part of the syntax. The final request may also fail for ordinary reasons such as DNS, TLS, redirects, or a changed response.
Eligibility must be recorded as a boundary, not as a boolean claim about a user. A useful review names the rule source, candidate URL class, link state, browser product and version, policy headers, connection conditions, and the expected fallback. A missing speculative request is not automatically a browser defect. It may mean that the candidate never became eligible, that the browser chose not to spend resources, or that a speculative result was invalidated before inspection.
Cross-origin candidates deserve an explicit check. A rule can name a URL that is syntactically valid while the browser or server still refuses the speculation because of origin, credentials, response policy, or privacy protections. Do not infer that a cross-origin response was fetched merely because a link appears in the DOM. Keep the fixture on origins you own and use synthetic paths so the receiver can distinguish a speculative request from a real navigation.
The Navigation API and history guide supplies a related caution: URL visibility and a state transition do not prove that a person visited a destination. The secure-contexts guide adds the prerequisite check before a page requests a privileged browser feature. Speculation adds another path that can make a URL observable without activation. Analytics should use an activation-scoped signal, not a request alone, and a server should not treat a prefetch or prerender request as proof of intent to complete an action.
Activation and abandonment form a lifecycle
Think in four states: declared, eligible, activated, and abandoned. “Declared” means the page supplied a rule. “Eligible” means the browser accepted the candidate for consideration; it is still not a guarantee of a request. “Activated” means the hidden or prepared result became the visible navigation. “Abandoned” means the candidate was discarded, expired, superseded, or otherwise never activated. The state names belong in a record even when the browser exposes only partial signals.
Activation changes what the target is allowed to do. A prerendered document can be loaded before a person selects it, but the application should defer irreversible work until it knows the document is visible or receives an equivalent activation signal. Use activation-aware code paths for analytics, personalization writes, reservation creation, mutation requests, and third-party embeds. A target that cannot distinguish hidden initialization from real arrival is a poor prerender candidate.
Abandonment is normal. A person can choose a different link, close the page, lose connectivity, or trigger a new rule set before the candidate activates. The browser can also discard a candidate under memory pressure or because a policy, response, or lifecycle condition changed. Cleanup must therefore be idempotent and bounded: cancel timers, release in-memory handles, and avoid treating abandonment as an error that needs a user-visible retry.
| Lifecycle state | Evidence a fixture can keep | Unsafe interpretation |
|---|---|---|
| Declared | Rule JSON fingerprint and candidate URL class | The browser accepted the rule |
| Eligible | Browser-specific diagnostic or controlled request marker, if available | A request definitely occurred |
| Activated | Visible navigation or activation-scoped application event | Every initialization ran only once |
| Abandoned | Candidate was dropped or never activated before timeout | The user rejected the destination |
The state machine should tolerate reordering. An activation event can race with cleanup, a server can receive a speculative request before the UI knows whether activation happened, and a navigation can be restored from a cache. Use a stable fixture identifier and a short-lived correlation value, but do not put account IDs, cookies, or raw URLs with secrets into a public record. The record answers “which bounded case changed state?” rather than “which person caused this request?”
When a target uses service workers, workers, or page lifecycle APIs, test the hidden phase separately from the visible phase. A worker may receive work for a page that never activates. A page visibility event may arrive at a different time than an application router event. These details are implementation-specific, so a portable article should describe the decision boundary and the fallback, not promise one universal event order. Keep the required content usable if no activation signal is available.
Credentials, side effects, and privacy boundaries
Speculation can carry browser state that makes a request look like a normal visit. Cookies, cache entries, authorization headers, client hints, referrer policy, and service-worker behavior can all affect what the target receives. The exact credential behavior is governed by the browser, request mode, origin, response policy, and implementation. Never design a fixture that depends on a real account cookie or a production authorization token.
Separate read and write routes. A GET that returns a public, cacheable shell is easier to speculate safely than a URL whose server handler mutates a cart, starts a job, sends an email, or consumes a one-time token. HTTP method alone is not a complete safety guarantee: a GET endpoint can still have side effects. The server must make idempotency and authorization decisions independently of any speculation hint.
Analytics is another side-effect boundary. A prerendered document can execute code before the person sees it, so a page-view beacon in module initialization can overcount visits. Gate measurement on a visible activation signal or a server-side event that the product defines as a real navigation. If the signal is unavailable, count the page only after the user-visible route commits. Keep speculative diagnostics in a separate short-retention stream and label them as candidate activity.
Privacy review should ask what a third party can learn from a speculative request. The destination may learn that a browser considered a link, even when no activation followed. A cache may retain a response, and a service worker may record an access. The DNS leak prevention guide explains why auxiliary lookups need their own route review; prefetch and prerender should likewise be included in a declared proxy and DNS policy rather than assumed to follow the explicit navigation path.
Use synthetic identities and endpoints in a fixture. Replace a production account with test-user-17, a real order with order-synthetic-42, and a real analytics destination with an owned receiver. Do not echo request headers, cookies, full referrers, or query strings into a public log. Redact values at collection time, set a short retention window, and document who can delete the record. A fixture that leaks credentials in order to prove a privacy property has failed its own boundary.
A copyable fixture and bounded record
The following fixture is intentionally declarative. It supplies a rule, two owned links, and a page-side record shape. It does not claim that a browser fetched either target, accepted the rule, activated a prerender, or produced the shown result. Replace the example receiver with an owned test service only in an authorized environment.
<script type="speculationrules">
{
"prefetch": [
{
"urls": ["/fixture/read-only-shell.html"],
"eagerness": "immediate"
}
],
"prerender": [
{
"urls": ["/fixture/activation-shell.html"],
"eagerness": "conservative"
}
]
}
</script>
<a href="/fixture/read-only-shell.html" data-case="prefetch">Read-only shell</a>
<a href="/fixture/activation-shell.html" data-case="prerender">Activation shell</a>
<output id="speculation-status">not observed</output>
Record the declared input separately from the outcome. The observed field must stay empty until a real fixture run supplies evidence; the article does not fill it with a guessed value. A durable record can use this shape:
{
"fixture": "speculation-boundary-v1",
"candidate": "/fixture/activation-shell.html",
"hint": "prerender",
"browser": "declared product, version, channel, and OS",
"policy": "response and permissions policy revision",
"credentials": "synthetic, no account cookie",
"declared": true,
"eligible": "unknown until a run records it",
"activated": "unknown until a visible navigation records it",
"abandoned": "unknown until the lifecycle ends",
"observed": null,
"fallback": "ordinary navigation remains available",
"dataClass": "synthetic"
}
Use two cases to expose the boundary. The first links a read-only target that can tolerate a cache hit and an ordinary navigation. The second links a target that records a visible activation marker but performs no write. A third negative case can point to an intentionally omitted URL and verify that the application stays usable; it must not claim that a missing request proves a browser block. Keep the receiver and the page's expected state under the same test owner.
The fixture's minimum assertions are: the rule parses as the intended JSON, the links remain usable without speculation, the target has no irreversible initialization before activation, and any received request is classified as candidate activity. If a test later runs, add the exact browser version, channel, OS, policy response, request result, activation signal, and abandonment reason. A run record belongs in private evidence or a controlled test log, not as an invented observation in this guide.
Choose a fallback from the observed boundary
| Situation | Decision | Why |
|---|---|---|
| Target is read-only and cacheable, but activation is uncertain | Prefer prefetch or ordinary navigation | The cost and side-effect surface stay smaller |
| Target has a visible shell and deferred writes | Consider prerender with a conservative rule | Hidden initialization can remain reversible |
| Target mutates state during load | Do not prerender it | A discarded candidate can still trigger an unwanted action |
| Credentials or sensitive data are required before activation | Require explicit navigation and authorization | A speculative request may disclose more than the user intended |
| Browser support or policy outcome is unknown | Keep the ordinary link and label the result unverified | A hint is not a compatibility guarantee |
If a candidate is not eligible, retain the link. If a candidate is eligible but abandoned, treat that as expected lifecycle behavior rather than a conversion failure. If a request arrives before activation, classify it as speculative and prevent it from changing account or order state. If activation occurs, re-check authorization and current application state before committing a write. These rules make the same fallback useful across browsers that implement different parts of the API.
Do not hide a mismatch by deleting the rule or widening the candidate set. First compare the declared rule, final response headers, URL, origin, credentials mode, browser version, and policy. Then decide whether the target belongs in prefetch, prerender, or no speculation. The MDN Speculation Rules API reference is the right place to check syntax; the WICG specification is the right place to read the algorithm and its limits; the Chrome prerender guide describes Chrome's documented lifecycle. None of these sources turns a fixture plan into measured support for an arbitrary build.
BotBrowser capability boundary
BotBrowser can load an authorized profile, keep a declared browser context reproducible, and expose browser-visible results from an owned fixture when a team chooses to run that workflow. It cannot force a browser to fetch a speculative candidate, make a prerender activate, inspect an implementation's private eligibility decision, or guarantee that a third-party endpoint received no request. The fixture above is a review shape, not a BotBrowser command or a measured result.
The matching BotBrowser advanced-features documentation describes product-level browser controls and profile workflows, not a shipped Speculation Rules implementation. This page adds the prefetch-versus-prerender choice, activation and abandonment states, credential and side-effect review, and a copyable bounded record that the docs page does not map. A team can use BotBrowser later to repeat its own authorized fixture, but it must publish the exact build and outcome rather than infer support from a profile or from a rule in page source.
Keep any BotBrowser result scoped to the named profile, browser version, OS, policy response, and fixture revision. Do not turn a successful page load into a claim that all candidates were eligible, that prerender activated, or that a service received no speculative request. Do not use speculation to defeat authorization, consent, privacy controls, or a provider's rate limits.
FAQ
Does a prefetch mean the user visited the target?
No. A prefetch can retrieve a response without a visible navigation, and the candidate can be discarded before a click. Count a visit only from an activation-scoped event or another product-defined navigation signal.
Is prerender always faster than prefetch?
No. Prerender can reduce activation work when it is eligible and retained, but it also consumes more CPU, memory, storage reads, and initialization budget. Resource pressure or a policy decision can prevent it, and a discarded candidate provides no user-visible benefit.
Can a speculative request use credentials?
It can be affected by the browser's credential, origin, policy, cache, and service-worker rules. That is why a fixture must use synthetic credentials or none at all. Never assume that a speculative request is anonymous or that a response is safe to expose.
Should a page write analytics during hidden initialization?
Usually no. Hidden initialization can happen without activation and can overcount visits or reveal a link choice. Defer irreversible analytics and business writes until the visible navigation commits, then record the event with an activation-scoped identifier.
What should happen when eligibility is unknown?
Keep the ordinary link and treat the speculative result as unverified. The fallback should preserve the required content and authorization path without depending on a request that the browser may skip.
Sources
- WICG Speculation Rules specification
- MDN: Speculation Rules API
- Chrome for Developers: Prerender pages
- BotBrowser: Advanced features
Practical conclusion
Choose prefetch for a read-only response that can tolerate a cache hit; choose prerender only for a hidden document that can initialize without irreversible work and can cleanly activate or be abandoned. Treat eligibility as browser-owned, activation as the point where visible intent is established, and speculative requests as candidate activity rather than proof of a visit. Keep credentials, analytics, storage, and writes behind explicit authorization and activation boundaries.
The next safe action is to put the declarative fixture on an owned test origin, keep the normal links working, and record declared, eligible, activated, and abandoned as separate fields. A future run may establish what one named browser build did for that fixture. It will not establish universal support, eliminate privacy review, or turn BotBrowser into a Speculation Rules implementation.
This article is part of the guide: Web Platform Surfaces: A Consistency Review Map
Related Articles
Navigation API history and privacy boundaries
PlatformSecure Contexts: Why Advanced Browser APIs Need HTTPS
PlatformCORS Browser Boundaries: Headers, Preflights, Credentials, and Cache
PlatformBack-Forward Cache: Lifecycle, Privacy, and State Consistency
PlatformDocument Picture-in-Picture: Permission and Window Boundaries
PlatformSame-Origin Policy and Site Isolation Explained
Take BotBrowser from research to production
The guides cover the model first, then move into cross-platform validation, isolated contexts, and scale-ready browser deployment.