Nginx CORS Headers Configuration

CORS lets a browser allow a page on one origin to call an API on another. The server decides what to allow by echoing a small set of Access-Control-* response headers; the browser enforces the decision, not the server.

The preflight request

For anything beyond a plain GET with simple headers, the browser sends an OPTIONS request first and only proceeds if the response allows the real request's method and headers.

if ($request_method = OPTIONS) {
    add_header Access-Control-Allow-Origin $cors_origin always;
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
    add_header Access-Control-Max-Age 3600 always;
    return 204;
}

Wildcard origin and credentials don't mix

A response with Access-Control-Allow-Origin: * is rejected by the browser if the request also carries credentials (cookies or an Authorization header read via credentials: "include"). List the specific origins instead, and add Vary: Origin so a shared cache cannot serve one origin's reflected headers to another.

Open the CORS headers generator

Frequently asked questions

Why does my API work with curl but not the browser?

curl does not enforce CORS — it is a browser-only protection. A missing or mismatched Access-Control-Allow-Origin header only blocks the response from reaching the page's JavaScript, not the request from reaching the server.

Do I need CORS for a same-origin request?

No. CORS only applies when the page's origin (scheme + host + port) differs from the request's target. A frontend and API on the same domain need nothing.

Guides