devkult_
tools29converters34
home/headers/access-control-allow-origin

Access-Control-Allow-Origin

response headercors

Tells the browser which origin may read this response from JavaScript running on another site.

Browsers block JavaScript from reading responses from another origin unless the server opts in. This header is that opt-in: it names the one origin allowed to read the response, or * for any. It must be on the actual response — and, for preflighted requests, on the OPTIONS response too.

The server always receives and processes the request; CORS only controls whether the calling page can see the answer.

Syntax

Access-Control-Allow-Origin: * | <origin> | null

Defined in Fetch Standard — CORS protocol.

Values

*any origin may read it — not allowed together with credentials
https://app.example.comexactly this origin (scheme, host and port)
nullthe opaque 'null' origin — avoid, since sandboxed iframes and file:// pages send it

Examples

Access-Control-Allow-Origin: https://app.example.com

one trusted front end

Access-Control-Allow-Origin: *

a public API with no cookies or auth headers

Good to know

  • It takes one origin, not a list. To allow several, check the request's Origin against an allowlist and echo the match back.
  • When the value depends on the request's Origin, also send Vary: Origin so caches don't serve one site's answer to another.
  • * doesn't work for requests with cookies or Authorization: send the exact origin plus Access-Control-Allow-Credentials: true.
  • Never echo back any Origin without checking it — that switches CORS protection off for every site.

Further reading: CORS errors explained

How to set Access-Control-Allow-Origin

Express (cors package)
import cors from "cors";

app.use(cors({
  origin: ["https://app.example.com", "https://admin.example.com"],
  credentials: true, // only if the browser sends cookies
}));
// Echoes the matching origin, adds Vary: Origin and answers preflights.
Next.js (next.config.js)
module.exports = {
  async headers() {
    return [
      {
        source: "/api/:path*",
        headers: [
          { key: "Access-Control-Allow-Origin", value: "https://app.example.com" },
          { key: "Access-Control-Allow-Methods", value: "GET, POST, PUT, DELETE" },
          { key: "Access-Control-Allow-Headers", value: "Content-Type, Authorization" },
        ],
      },
    ];
  },
};
nginx (allowlist)
map $http_origin $cors_origin {
  default "";
  "https://app.example.com" $http_origin;
}

server {
  location /api/ {
    add_header Access-Control-Allow-Origin $cors_origin always;
    add_header Vary Origin always;
    # ...
  }
}

Check it

Fetch only the response headers and filter for Access-Control-Allow-Origin. In the browser, it's under Response Headers in DevTools → Network.

curl -sI https://example.com/ | grep -i '^access-control-allow-origin:'

To compare response headers across many URLs at once, use the HTTP Status Checker.

Frequently asked questions

Can I list multiple origins in Access-Control-Allow-Origin?

No. The header accepts a single origin or *. Compare the request's Origin header to your allowlist and return the one that matched, with Vary: Origin.

Why does the request reach my server but the browser still reports a CORS error?

CORS is enforced by the browser when it reads the response. The server ran the request; the browser hid the result because this header was missing or didn't match.

Related headers