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.com | exactly this origin (scheme, host and port) |
| null | the 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
Originagainst an allowlist and echo the match back. - When the value depends on the request's
Origin, also sendVary: Originso caches don't serve one site's answer to another. *doesn't work for requests with cookies orAuthorization: send the exact origin plusAccess-Control-Allow-Credentials: true.- Never echo back any
Originwithout checking it — that switches CORS protection off for every site.
Further reading: CORS errors explained
How to set Access-Control-Allow-Origin
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.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" },
],
},
];
},
};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.