Access-Control-Max-Age: caching the preflight result
Access-Control-Max-Age says how many seconds a browser may reuse this preflight result instead of sending another OPTIONS request before every call.
At a glance
- Direction
- Response, on the preflight only.
- Defined in
- The Fetch standard (WHATWG)
- When absent
- Browsers use a short default, in the region of five seconds, so most requests are preflighted again.
- Unit
- Seconds, as an integer
- Chrome cap
- Around two hours. Larger values are clamped rather than rejected.
- Firefox cap
- Around twenty four hours
- Value -1
- Disables caching, so every request is preflighted
In detail
Without preflight caching, a cross-origin application makes two round trips for every write: an OPTIONS request and then the real one. On a high latency connection that doubling is the single largest cost of using CORS at all, and it is entirely avoidable for endpoints whose policy does not change from minute to minute.
Browsers cap the value regardless of what you send. Chrome clamps to roughly two hours and Firefox to roughly a day, and a much larger number is silently reduced rather than refused, so an enormous value neither helps nor causes an error. Something in the range of a few hours captures nearly all of the benefit.
The cached entry is keyed by origin, URL and the specific method and headers that were requested. Changing your policy therefore leaves clients with a stale permission for as long as their entry lives, which is the reason to keep the value moderate on any endpoint whose CORS rules you might tighten.
The value minus one turns caching off explicitly. That is occasionally useful while debugging, because otherwise a corrected preflight response is not consulted until the old entry expires, and it is easy to conclude a fix did not work when the browser simply has not asked again. A private window achieves the same thing without a deploy, since its preflight cache starts empty.
Examples
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PATCH
Access-Control-Allow-Headers: content-type, authorization
Access-Control-Max-Age: 600Access-Control-Max-Age: -1Things that catch people out
- A large value does not survive the browser caps, so sending a week is functionally the same as sending a few hours.
- A cached preflight hides policy changes. After tightening CORS rules, existing clients keep the old permission until their entry expires.
- The cache key includes the requested headers, so adding one custom header to a call forces a new preflight even though the endpoint has not changed.
Try it: HTTP Headers Checker
Check a live URL or paste headers you already have. It grades six security headers from A+ to F and lists every other header the response returned.
HTTP Headers Checker
LOCAL · Browser-OnlyView HTTP response headers for any URL
Enter any website URL to fetch and analyze its HTTP response headers. We'll automatically add https:// if needed.
Why Check Security Headers?
Security headers protect your website against common attacks like XSS, clickjacking, and MIME sniffing. They're set by your web server and cost nothing to implement. Missing security headers are one of the most common findings in security audits.
Related HTTP headers
All http headers →Access-Control-Allow-Methods: permitted methods on preflight
Where the allow methods header belongs, why it appears only on the preflight response, which methods never need it, and how it interacts with caching.
Access-Control-Request-Method: the preflight question
What the browser sends on a preflight, which methods trigger one, why the server must answer with an exact match, and how to reproduce a preflight by hand.
Access-Control-Allow-Headers: permitted request headers
Which request headers trigger a preflight, how to answer with the right allow list, and the one header a wildcard never covers.
Cache-Control: directives for browsers and shared caches
Every Cache-Control directive that matters, the difference between no-cache and no-store, and how to cache immutable assets forever without breaking deploys.
Origin: where a request was initiated from
When browsers send Origin, why it is only scheme, host and port, when the value is null, and how to use it for cross-site request forgery defence.
Access-Control-Request-Headers: declaring custom headers
What the browser declares on a preflight, why the names arrive lowercase and sorted, which headers are omitted, and how to answer without guessing.
Tools for this
- HTTP Request Builder Free online HTTP request builder - build and test HTTP requests with custom headers and body
- HTTP Headers Checker Free online HTTP headers checker - view HTTP response headers for any URL