GuidesHEADERS

The complete list of CORS headers

CORS runs on a fixed set of HTTP headers: the browser sets a few request headers, and the server answers with response headers that grant or withhold access. This list of CORS headers covers both sides, the fetch metadata headers that ride along, and which header resolves which console error.

Request headers the browser sets

The browser generates these headers automatically when a page issues a cross-origin fetch or XMLHttpRequest. Servers read them to decide whether to permit the request.

CORS and fetch-metadata request headers
HeaderSent onPurpose
OriginCORS requests and preflightsThe requesting origin: scheme, host, and port, or null
Access-Control-Request-MethodPreflight requestsThe HTTP method the actual request will use
Access-Control-Request-HeadersPreflight requestsSorted, lowercase list of the non-safelisted headers the actual request will send
Sec-Fetch-ModeMost requestsThe request mode: cors, no-cors, navigate, same-origin, or websocket
Sec-Fetch-SiteMost requestsHow initiator and target relate: cross-site, same-site, same-origin, or none
Sec-Fetch-DestMost requestsWhere the response will be used; fetch and XHR send the empty value
Sec-Fetch-UserUser-initiated navigationsAlways ?1; omitted when there was no user activation

Origin, Access-Control-Request-Method, Access-Control-Request-Headers, and the Sec-Fetch-* headers are forbidden request headers: the browser sets them and JavaScript cannot override them.

Response headers the server answers with

The server communicates permission by adding these headers to its responses. They decide whether the browser exposes the response body, and whether an actual request may follow a preflight.

CORS response headers
HeaderAppears onPurpose
Access-Control-Allow-OriginPreflight and actual responsesThe one origin allowed to read the response, or * without credentials
Access-Control-Allow-CredentialsPreflight and actual responsesOnly valid value is true; permits credentialed requests when the client opts in
Access-Control-Allow-MethodsPreflight responsesMethods allowed for the actual request; GET, HEAD, POST always allowed
Access-Control-Allow-HeadersPreflight responsesRequest headers allowed in the actual request; matching is case-insensitive
Access-Control-Max-AgePreflight responsesSeconds the browser may cache the preflight; default 5, capped at 7200 in Chromium and 86400 in Firefox
Access-Control-Expose-HeadersActual responsesExtra response headers scripts may read beyond the safelisted set
Timing-Allow-OriginActual responses (adjacent standard)Origins allowed to see detailed Resource Timing data; takes a list or *

The full exchange in one view

A cross-origin request with non-safelisted methods or headers runs in two phases: an OPTIONS preflight, then the actual request. Each header above appears at a fixed position in that exchange.

Preflight, then the actual request
> OPTIONS /reports HTTP/2
> origin: https://app.example.com
> access-control-request-method: PUT
> access-control-request-headers: content-type, x-api-key
> sec-fetch-mode: cors
> sec-fetch-site: cross-site

< HTTP/2 204
< access-control-allow-origin: https://app.example.com
< access-control-allow-methods: PUT
< access-control-allow-headers: Content-Type, X-Api-Key
< access-control-max-age: 7200
< vary: Origin

> PUT /reports HTTP/2
> origin: https://app.example.com
> content-type: application/json
> x-api-key: demo-key

< HTTP/2 200
< access-control-allow-origin: https://app.example.com
< access-control-expose-headers: X-Request-Id
< vary: Origin

Which header fixes which error

Browser consoles name the failing header directly. Match the error to the header, then check the response it belongs on.

Console errors and the header that resolves them
Console errorHeader to fix
No 'Access-Control-Allow-Origin' header is present on the requested resourceAccess-Control-Allow-Origin on the actual response
Response to preflight request doesn't pass access control checkAllow-Origin, Allow-Methods, or Allow-Headers on the preflight response
Method PUT is not allowed by Access-Control-Allow-Methods in preflight responseAccess-Control-Allow-Methods
Request header field X-Api-Key is not allowed by Access-Control-Allow-HeadersAccess-Control-Allow-Headers
The value of the 'Access-Control-Allow-Origin' header must not be the wildcard '*'Echo the explicit origin and add Access-Control-Allow-Credentials: true

Defaults and safelists worth memorizing

The browser defaults explain why some requests skip the preflight entirely and why some responses are readable without any extra headers.

  • CORS-safelisted methods are GET, HEAD, and POST, always allowed without preflight negotiation.
  • CORS-safelisted request headers are Accept, Accept-Language, Content-Language, Content-Type limited to application/x-www-form-urlencoded, multipart/form-data, and text/plain, and Range with a single range value.
  • CORS-safelisted response headers exposed to scripts by default are Cache-Control, Content-Language, Content-Length, Content-Type, Expires, Last-Modified, and Pragma.
  • The default preflight cache is 5 seconds; browsers cap Access-Control-Max-Age at 7200 seconds in Chromium and 86400 seconds in Firefox.

Good questions.

Can JavaScript set or change the Origin header?

No. Origin is a forbidden request header controlled by the browser; fetch and XMLHttpRequest cannot set or override it.

Which CORS headers come from the browser and which from the server?

The browser sets Origin, Access-Control-Request-Method, Access-Control-Request-Headers, and the Sec-Fetch-* headers on requests. The server returns the Access-Control-Allow-* family, Access-Control-Max-Age, and Access-Control-Expose-Headers on responses.

What are the limits on preflight caching?

The default is 5 seconds when Access-Control-Max-Age is omitted. Chromium caps the value at 7200 seconds (2 hours) and Firefox at 86400 seconds (24 hours).

How do I check which headers an endpoint returns?

Run the URL through the CORS header checker and inspect the preflight and actual response headers directly.