Access-Control-Request-Headers

During a CORS preflight, the browser must declare which non-safelisted headers the subsequent request will include. The Access-Control-Request-Headers request header carries this list.

Usage

When front-end JavaScript sends a cross-origin request containing headers outside the CORS-safelisted set, the browser first issues a preflight OPTIONS request. The Access-Control-Request-Headers header in the preflight lists every non-safelisted header the actual request intends to send.

The server inspects this list and responds with Access-Control-Allow-Headers to confirm which headers are permitted. If the server omits a requested header from the allow list, the browser cancels the actual request.

CORS-safelisted request headers (Accept, Accept-Language, Content-Language, Content-Type, and Range under certain conditions) do not appear in this header because the browser permits them without preflight approval. Content-Type and Range still appear when their value falls outside the safelisted set, as happens with Content-Type: application/json.

The header value is a comma-separated list of header names, all lowercased and sorted lexicographically by the browser.

Example

A client-side application needs to send a POST with a JSON body and a custom X-Request-ID header. The browser generates a preflight listing both Content-Type (which requires preflight when the media type is application/json) and the custom header.

Request

OPTIONS /api/orders HTTP/1.1
Host: api.example.re
Origin: https://shop.example.re
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type, x-request-id

Response

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://shop.example.re
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, X-Request-ID
Access-Control-Max-Age: 3600

A preflight for a request carrying an Authorization token and a custom tracing header.

Request

OPTIONS /api/account HTTP/1.1
Host: api.example.re
Origin: https://dashboard.example.re
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization, x-trace-id

Troubleshooting preflight failures

Preflight rejections surface in the browser console as a message naming the header the server declined, along the lines of "Request header field x-request-id is not allowed by Access-Control-Allow-Headers in preflight response". The named header appears in Access-Control-Request-Headers on the preflight and is absent from the server reply.

The server reply needs every listed header echoed in Access-Control-Allow-Headers. Matching is case-insensitive, so the reply reads naturally with conventional capitalization while the browser sends lowercase.

A wildcard in Access-Control-Allow-Headers covers ordinary headers and stops short of Authorization, which requires an explicit mention by name. Requests carrying a token alongside * fail for exactly this reason, and the wildcard loses all meaning once Access-Control-Allow-Credentials is set to true.

The preflight itself travels without credentials, so authentication middleware answering 401 before reaching the CORS layer breaks the exchange ahead of the real request. Preflight OPTIONS requests belong outside the authenticated path.

Reverse proxies add another layer. nginx returns the allow headers through add_header inside a dedicated if ($request_method = OPTIONS) block, and Apache uses Header always set so the header survives on non-2xx responses. A configuration setting headers only on success drops them from the preflight reply.

See also

Last updated: August 17, 2026