← Cross-origin redirect timing opt-in
v151 · fetch · protocol element
Timing-Allow-Origin on navigation redirects
The response header a redirect server sends to opt a navigation's redirect forward into measurement by the chain's destination origin. When every redirect in the chain opts in, the destination page can see the chain's redirect timing; one silent redirect keeps the whole chain opaque.
Syntax
// On each redirect response in a navigation chain:
Timing-Allow-Origin: https://destination.example
// ...or a comma-separated list of serialized origins, or the wildcard:
Timing-Allow-Origin: https://a.example, https://b.example
Timing-Allow-Origin: *
Fetch processes the header with “getting, decoding, and splitting” — values are serialized origins or the wildcard *. The same header already exists for subresource responses; what this feature adds is its role on navigation redirect responses, where it opts in the destination origin rather than the requesting origin.
Inputs
The header's value is a list of serialized origins (for example https://destination.example) or the single wildcard *, processed by fetch's “get, decode, and split” header parsing — so a comma-separated list is normal form. The wildcard succeeds regardless of credentials (the navigation TAO check has no credentials branch, unlike CORS) and need not be the sole member — a list containing * among origins still counts. It is read from redirect responses (3xx) while fetching a navigation request — each redirect in the chain is read independently, and a redirect response with no Timing-Allow-Origin header contributes an empty value list.
Outputs
The header produces no direct output. Its effect is a permission: when the navigation completes, the destination origin runs the navigation TAO check against the collected values. If every redirect's list contains * or the destination's serialized origin, the check returns success and the destination's PerformanceNavigationTiming entry exposes redirectCount, redirectStart, and redirectEnd for the chain. Otherwise the check fails and those fields report zero.
Errors
There are no exceptions and no network errors. The failure mode is silence: a redirect that omits the header, or names neither * nor the destination origin, makes the navigation TAO check return failure, and the destination simply sees zeroed redirect fields — indistinguishable from a same-origin navigation with no redirects. Servers should treat a missing header as “no opt-in”, and origins measuring chains should treat zero values as “unknown”, never as “no redirects happened”.
Context
Where it applies: only navigation requests. Fetch collects the values via the append algorithm, which asserts the request is a navigation request; subresource fetches are unaffected and keep the existing “backward” TAO check (which opts in the requesting origin).
Who sends it: the server (or edge) issuing each 3xx response in the chain. The destination site cannot add it retroactively — it is the redirect operator's explicit choice to be measured.
Availability: Chrome 151 per the milestone listing; runtime feature NavigationTimingRedirectTimingViaTAO (status stable at trunk).
Lifecycle
Collection: as the navigation follows each redirect, fetch appends that redirect response's decoded Timing-Allow-Origin values to the request's navigation timing allow values list — one list entry per redirect, in chain order (missing header → empty entry). The append runs for every redirect-status response of a navigation request, same-origin hops included; the final response then carries a clone of the collected list.
Evaluation: once the destination origin is known, the HTML navigation steps run the navigation TAO check over the collected list. The check is all-or-nothing per chain: every entry — same-origin hops included, once any cross-origin redirect exists — must contain * or the destination origin, serialized.
Exclusions, stated exactly: if the chain has no cross-origin redirects, the real values are always exposed. Otherwise exposure additionally requires that the request's client is null or its referrer is not no-referrer — the no-referrer gate applies only when the chain has cross-origin redirects.
Examples
# The destination (https://shop.example) runs a campaign redirector.
# Chain: shop.example/out → t.co/abc → shop.example/landing
# 1) shop.example/out 302 — opts the destination in:
HTTP/1.1 302 Found
Location: https://t.co/abc
Timing-Allow-Origin: https://shop.example
# 2) t.co/abc 302 — a third party; must also opt in, or the chain stays opaque:
HTTP/1.1 302 Found
Location: https://shop.example/landing
Timing-Allow-Origin: *
# Result on shop.example/landing:
# performance.getEntriesByType("navigation")[0].redirectCount === 2
# If t.co omitted its header, redirectCount would be 0.
Source: Fetch Standard — navigation TAO check
Compatibility
| Engine / runtime | Support | Notes |
|---|---|---|
| Chrome | 151 | Milestone listing: Enabled by default; runtime feature stable at trunk |
| Edge | Not separately reported | No Edge position recorded on ChromeStatus |
| Firefox | No signal | Vendor signal recorded on the ChromeStatus entry |
| Safari | Recorded positive signal | A recorded signal, not an official WebKit standards position |
The header itself (for subresources) has older BCD data in BCD http/headers/Timing-Allow-Origin.json; the navigation redirect role is this feature and has no BCD entry yet. Vendor signals per the ChromeStatus API feature record.
Source: ChromeStatus API feature record; BCD http/headers/Timing-Allow-Origin.jsonSecurity and privacy
This header is the consent mechanism. Redirect timing can disclose a chain's structure and timing across origins, which is why cross-origin navigation redirects were opaque by default. Exposure happens only when every redirect operator explicitly opts the destination origin in — a destination cannot unilaterally observe a chain.
Referrer alignment: when the chain has cross-origin redirects, a no-referrer navigation (with a non-null client) is excluded from exposure even with the header — so the opt-in cannot be abused to measure navigations deliberately stripped of provenance. Purely same-origin chains are unaffected by that gate.
Scope: the header discloses only redirect count and redirect start/end times for the chain — not response bodies, headers, or redirect URLs beyond what the address bar already traverses.
Source: whatwg/fetch PR #1931 (opt-in alignment rationale); whatwg/html PR #12513 (exposure conditional)