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
- Fetch Standard: HTTP Access-Control-Request-Headers
- Access-Control-Allow-Headers
- Access-Control-Request-Method
- CORS
- HTTP headers