v150 · origin trial · performance · proposal
Speculative load measurement
Speculative loads (preconnects, preloads, and speculation-rules prefetches and prerenders) only pay off when they are actually used — and today developers lack a unified view. This proposal adds performance.getSpeculations(), which records preconnect, preload, and speculative-navigation metadata, including when a preload was consumed and the same-origin navigation destination when available.
There is no published or normative API specification yet: ChromeStatus records no spec link. The proposed design is described by the WICG explainer, while Chromium's experimental implementation IDL shows the current browser binding. It is available through an origin trial on desktop in Chrome 150–155. To use it:
- Register for the
SpeculationMeasurementorigin trial at developer.chrome.com/origintrials and serve the token (third-party tokens are allowed). ChromeStatus records the trial registration (origin-trial id2748884622556266497) with the explainer as its documentation. - Or, locally: launch Chrome with
--enable-blink-features=SpeculationMeasurement(runtime-enabled featureSpeculationMeasurement, statusexperimental). - Read the data during page dismissal (for example, in the explainer's
pagehidepattern). A preload cannot be classified as unused until the browser knows it was not consumed during that page lifetime.
Naming divergence to be aware of: the ChromeStatus origin-trial metadata and the comment in Chromium's runtime_enabled_features.json5 both say performance.speculations — but the WICG explainer (the trial's own documentation) and Chromium's current experimental IDL expose a method, performance.getSpeculations(). The explainer records an earlier property-shaped design on dismissal events, but does not prove the exact lineage of the stale performance.speculations wording. This page documents the current explainer/IDL agreement and keeps the divergence visible.
at a glance
| Milestone listing | Chrome 150 — Origin trial (trial window 150–155, desktop) |
|---|---|
| Origin trial | Registerable: id 2748884622556266497, feature name SpeculationMeasurement, third-party tokens allowed, docs = WICG explainer |
| Ship estimate | None recorded — feature detail (chromestatus API, updated 2026-06-05): status text “Proposed”, no ship milestone on the active stages |
| Interface | performance.getSpeculations() returning a SpeculationData (Window only) |
| Spec status | WICG explainer (proposal) — no published spec yet |
| Runtime flag | SpeculationMeasurement in runtime_enabled_features.json5 (status experimental, origin-trial feature) |
| ChromeStatus | 5118840377835520 — Speculative load measurement |
Syntax
The proposal hangs a single method off performance, returning a SpeculationData with one array per speculation kind plus the navigation destination. IDL from Chromium's implementation of the explainer (Window-only, gated on SpeculationMeasurement):
// partial interface Performance (core/timing/performance.idl)
[Exposed=Window, RuntimeEnabled=SpeculationMeasurement,
MeasureAs=SpeculationMeasurement]
SpeculationData getSpeculations();
[RuntimeEnabled=SpeculationMeasurement, Exposed=Window]
interface SpeculationData {
readonly attribute FrozenArray<PreloadData> preloads;
readonly attribute FrozenArray<PreconnectData> preconnects;
readonly attribute FrozenArray<SpeculationNavigationData> navigations;
readonly attribute USVString? navigationDestinationURL;
};
enum CrossOriginMode { "none", "anonymous", "use-credentials" };
[RuntimeEnabled=SpeculationMeasurement, Exposed=Window]
interface PreloadData {
readonly attribute USVString url;
readonly attribute DOMString as;
readonly attribute CrossOriginMode crossorigin;
readonly attribute boolean earlyhint;
[CallWith=ScriptState] readonly attribute DOMHighResTimeStamp? used;
};
[RuntimeEnabled=SpeculationMeasurement, Exposed=Window]
interface PreconnectData {
readonly attribute USVString origin;
readonly attribute CrossOriginMode crossorigin;
readonly attribute boolean earlyhint;
};
enum SpeculationNavigationType { "prefetch", "prerender", "prerender-until-script" };
enum SpeculationEagernessValue { "conservative", "moderate", "eager", "immediate" };
[RuntimeEnabled=SpeculationMeasurement, Exposed=Window]
interface SpeculationNavigationData {
readonly attribute SpeculationNavigationType type;
readonly attribute USVString url;
readonly attribute FrozenArray<DOMString>? tags;
readonly attribute SpeculationEagernessValue? eagerness;
};
Source: Chromium performance.idl, speculation_data.idl, speculation_navigation_data.idl, preload_data.idl, preconnect_data.idl
| Member | Contract |
|---|---|
preloads[] | Each preload recorded for this page view, with its as value, crossorigin mode, whether it arrived via Early Hints (earlyhint), and used — a timestamp of when the resource was consumed from the preload map, or null if it was never used. This includes header-delivered preloads, so it is not limited to DOM <link> elements. Unused preloads are the waste signal. |
preconnects[] | Each preconnected origin, its crossorigin mode, and whether it came from a 103 Early Hints response. |
navigations[] | Each speculation-rules navigation candidate: type (prefetch, prerender, or prerender-until-script), target url, the rule's tags, and its eagerness — the metadata needed to judge which rules pay off. |
navigationDestinationURL | The explainer says this is where the user went next, exposed only for non-same-document, same-origin navigations after the same value is exposed to NavigationDestination in the navigate event. Chromium's current IDL includes the nullable member, but the explainer also retains a TODO about finalizing how to expose that URL, so treat these semantics as provisional. |
Scope notes from the explainer: only speculations made by the current document are reported (even cross-origin ones), no cross-origin data leaks; resource prefetches (as opposed to navigation prefetches) are an explicit non-goal because they may still be used by a future page; <link rel=prerender> (the legacy API) is excluded in favour of speculation-rules prerenders.
Proposal, implementation, and the stale property name
Nothing here is a shipped standard yet. The explainer records an early iteration that exposed a speculations object on dismissal events, then moved away from it because that coupled the design too tightly to dismissal-event behavior. The current explainer and Chromium's experimental IDL agree on the method form, getSpeculations(). ChromeStatus's trial description and Chromium's flag comment still say performance.speculations. That stale property wording is consistent with an earlier property-shaped design, but the available sources do not prove it came from the exact dismissal-event iteration, so this page does not claim that lineage. The explainer also discusses why PerformanceObserver and the Reporting API were not selected.
Examples
performance.getSpeculations() when available and otherwise reports that absence without fabricating data. The demo includes two real preload links so an enabled implementation has preload activity to inspect. Source: chrome-platform-showcase// The explainer's canonical pattern: report on dismissal, keep the payload small.
window.addEventListener("pagehide", () => {
const { preloads, navigations } = performance.getSpeculations();
fetch("/analytics/unused-speculations", {
method: "POST",
keepalive: true,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ preloads, navigations }),
});
});
Source: WICG explainer — example usage
Browser compatibility
There is no browser-compat-data (BCD) entry for this API yet (checked api/Performance.json directly — neither getSpeculations nor speculations is present), so the table below is an interim view built from ChromeStatus data and public signals — not from BCD.
| Browser | Status | Notes |
|---|---|---|
| Chrome | 150–155 (origin trial) | Desktop origin trial with public registration; explainer-stage proposal, ship estimate unset, status “Proposed” |
| Edge | Not separately reported | No Edge position is recorded on ChromeStatus; no public support evidence (Chromium engine equivalence is not a support commitment) |
| Firefox | No signal | Recorded on ChromeStatus |
| Safari | No signal | Recorded on ChromeStatus |
Specifications
| Specification | Status |
|---|---|
| Speculative load measurement API (WICG explainer) | Proposal / incubation — no published spec |
| HTML — Speculative loading (speculation rules) | WHATWG Living Standard — the rules being measured |
| HTML — Map of preloaded resources | WHATWG Living Standard — defines when a preload counts as used |