Timing-Allow-Origin
Browsers zero out timing attributes for cross-origin resources to prevent information leakage. The Timing-Allow-Origin response header lifts this restriction, granting specified Origins access to detailed Resource Timing API data.
Usage
Browsers expose detailed performance timing for
same-origin resources through the
PerformanceResourceTiming interface. For
cross-origin resources, the same-origin policy
restricts access by zeroing out most timing
attributes. DNS lookup time, TCP connect duration,
TLS handshake time, request start,
response start,
and transfer size all return 0 for cross-origin
requests by default.
The Timing-Allow-Origin header lifts this restriction. When a server includes the header with a matching origin value or wildcard, the browser exposes the full set of timing attributes to JavaScript running on the allowed origin. This gives Real User Monitoring (RUM) tools and performance scripts visibility into the loading behavior of third-party resources like CDN assets, fonts, and analytics scripts.
Without the header, the following
PerformanceResourceTiming attributes are zeroed
for cross-origin resources: redirectStart,
redirectEnd, workerStart, domainLookupStart,
domainLookupEnd, connectStart, connectEnd,
requestStart, responseStart,
secureConnectionStart,
firstInterimResponseStart, and
finalResponseHeadersStart. The nextHopProtocol
attribute returns an empty string. The
encodedBodySize, decodedBodySize, and
contentType attributes follow the CORS
status of the response rather than this header, and
transferSize requires both checks to pass.
The firstInterimResponseStart attribute is
particularly relevant for measuring 103 Early
Hints performance. This timestamp records when the
browser received the first byte of an interim 1xx
response. For cross-origin resources, the value
returns 0 unless the server sends
Timing-Allow-Origin. Measuring the gap between
requestStart and firstInterimResponseStart
reveals how quickly the server delivered Early Hints
before the final response arrived.
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
const earlyHints = entry.firstInterimResponseStart - entry.requestStart;
if (earlyHints > 0) {
console.log(
`${entry.name}: Early Hints in ${earlyHints}ms`
);
}
});
});
observer.observe({ type: "resource", buffered: true });
The header also unlocks the
Server-Timing serverTiming
property on cross-origin resources. Without
Timing-Allow-Origin, server timing entries are
not exposed to the requesting origin.
Multiple origins are specified as comma-separated
values. The wildcard * grants access to all
origins. The header is processed during fetch and
applies to both fresh and cached responses. When a
cached response is revalidated, the header value
from the revalidation response takes precedence.
Navigations receive the same treatment across Redirects. The browser records the Timing-Allow-Origin values of every redirect response in a navigation's redirect chain, and full navigation timing is exposed only when each response in the chain allows the destination origin.
Values
Origin
One or more specific Origins allowed to access timing data. Multiple origins are comma-separated.
* (wildcard)
The wildcard grants timing data access to all origins. Common on public CDN resources and static asset hosts where timing visibility has no privacy implications.
Example
Granting timing access to a specific analytics
origin. Only scripts running on
https://analytics.example.re see full timing
data for this resource.
Timing-Allow-Origin: https://analytics.example.re
Granting timing access to multiple origins. Both the main site and the monitoring service see timing attributes.
Timing-Allow-Origin: https://www.example.re, https://monitoring.example.re
A CDN serving public static assets grants timing access to all origins. Any page loading resources from this CDN sees full timing data, enabling RUM tools to measure DNS, TLS, and response times for third-party assets.
Timing-Allow-Origin: *
Pairing Timing-Allow-Origin with
Server-Timing exposes both
network-level and server-level performance data to
cross-origin consumers. The timing header unlocks
the serverTiming property containing the custom
metrics.
Timing-Allow-Origin: *
Server-Timing: cdn-cache;desc="HIT", edge;dur=2
What fails, and what survives anyway
A failed check zeroes the phase breakdown of Resource Timing: DNS, connection, TLS, request, and response milestones, redirect timings, and the next-hop protocol. Total duration survives, along with start and end times, so cross-origin resources stay measurable as a whole while their anatomy disappears. Body sizes follow CORS status rather than this header, and browsers reserve the right to zero transfer sizes regardless.
Two behaviors separate Timing-Allow-Origin from
its CORS lookalikes. The wildcard works with
credentials: a * passes the check on cookie-bearing
requests, where
Access-Control-Allow-Origin
rejects the same combination. And redirects poison
permanently: one hop in a chain missing the header
sets a failure flag no later response clears, so a
final response carrying * cannot rescue timing
lost at an intermediate redirect. Analytics and
shortener hops each need the header or the whole
chain reports opaque.
Deployment leans overwhelmingly on the wildcard,
with Web Almanac measurements putting * at roughly
85% of the header's use, and listing
specific origins carries the same shared-cache
discipline as
Access-Control-Allow-Origin:
an origin-specific value served from a cache without
Vary: Origin reaches the wrong requester.
See also
- Resource Timing (W3C)
- PerformanceResourceTiming: firstInterimResponseStart (MDN)
- Server-Timing
- 103
- Cors
- HTTP headers