Access-Control-Allow-Headers: permitted request headers
Access-Control-Allow-Headers lists the request headers a cross-origin client may send. Anything not safelisted and not on this list causes the preflight to fail.
At a glance
- Direction
- Response, on the preflight only.
- Defined in
- The Fetch standard (WHATWG)
- When absent
- Only the safelisted request headers are permitted, so any custom header fails the preflight.
- Safelisted already
- Accept, Accept-Language, Content-Language, and Content-Type with a restricted set of values
- Wildcard
- Allowed for non-credentialed requests, and it never covers Authorization.
- Case
- Header names are case insensitive, unlike the method list.
- Answers
- Access-Control-Request-Headers, which the browser sends on the preflight
In detail
A small set of request headers are safelisted and never trigger a preflight, but the safelisting of Content-Type is narrow: only the three form and text types qualify, so sending application/json is enough on its own to require a preflight. That surprises people who assumed the custom header they added was the cause.
The answer must cover every header the browser named in Access-Control-Request-Headers. Missing one fails the whole preflight, and the browser's console message names the offending header, which makes this one of the few CORS errors that tells you exactly what to fix.
The wildcard works for requests without credentials, with one carve out that catches people repeatedly: it does not cover Authorization. That header always has to be listed by name, so an API using bearer tokens cannot rely on the wildcard, whatever else its policy says.
Keep the list to headers you actually read. A generous list that names a dozen headers nobody sends is not more permissive in a useful way, it just makes the preflight response larger and hides which headers the endpoint genuinely expects from the next person who has to change it.
One more asymmetry catches people moving between the two allow lists: this one is compared case insensitively, while the method list is not. So Content-Type in your answer satisfies a request for content-type, but PATCH in lower case does not satisfy a request for PATCH. Writing both lists in their conventional casing avoids having to remember which rule applies where.
Examples
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Headers: Authorization, Content-Type, X-Request-Id
Access-Control-Allow-Credentials: trueAuthorization has to be named explicitly. A wildcard would not cover it even without credentials.
Access-Control-Request-Headers: authorization,content-type,x-request-idThe browser lowercases and sorts the names. Your answer does not have to match that formatting.
Things that catch people out
- The wildcard never covers Authorization, so a token based API that relies on it sees preflights fail while everything else appears configured correctly.
- Sending application/json is enough to trigger a preflight on its own, even with no custom headers at all.
- Omitting a single requested header fails the entire preflight, not just that header, and the real request is never sent.
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-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.
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.
Authorization: credentials on a request
How the Authorization header is structured, how Basic and Bearer differ, why it is dropped across a cross-host redirect, and how it interacts with caching.
Content-Type: media type, charset and boundary
How Content-Type is structured, why the charset parameter still matters, what boundary does on a multipart upload, and how a wrong type breaks a page.
Access-Control-Allow-Credentials: cookies across origins
What credentials mode means, the three wildcards it disables, what the client must also do, and why this header needs an exact origin in the response.
Access-Control-Expose-Headers: reading response headers
Which response headers page code can read cross-origin by default, how to expose more, and why a pagination or request id header appears empty without it.
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