How does the 'Access-Control-Allow-Origin' header work?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Access-Control-Allow-Origin is a CORS response header that tells browsers which origins are allowed to read a cross-origin response. It is not an authentication mechanism, and it does not control whether the HTTP request reaches the server at all.
That distinction matters. The server may receive and process a request, yet the browser can still block JavaScript from reading the response because the CORS policy did not allow that origin.
Same-Origin Policy and What CORS Changes
Browsers enforce the same-origin policy for scripts. Under that policy, a page loaded from one origin cannot freely read responses from another origin unless the target server opts in.
An origin is the combination of:
- scheme
- host
- port
If any of those differ, the request is cross-origin from the browser’s point of view.
Access-Control-Allow-Origin is one of the headers the server uses to opt in to that cross-origin read access.
The Simple Case
For a simple cross-origin request, the browser sends the request with an Origin header. The server then returns a matching CORS response header.
If the browser sees an allowed origin, JavaScript may read the response. If the header is missing or mismatched, the browser blocks script access even though the network request itself succeeded.
That is why CORS errors can be confusing: the server logs may show a successful request while the frontend still reports a blocked response.
Preflight Requests
If the request is not “simple” enough, the browser sends a preflight OPTIONS request first. This asks the server whether the real request method and headers are allowed.
A typical preflight response looks like this:
If the preflight response is not acceptable, the browser does not send the actual application request.
Credentials Change the Rules
If the browser sends credentials such as cookies or HTTP authentication, you cannot use Access-Control-Allow-Origin: *.
Instead, the server must return the exact trusted origin and also include:
The client side must also opt in, for example with fetch(..., { credentials: "include" }).
This is one of the most common CORS mistakes: combining credentials with a wildcard origin and expecting browsers to allow it.
A Safe Server Pattern
A typical safe pattern is to maintain an allowlist and echo back only trusted origins.
The Vary: Origin header is important when caches are involved, because the response can change depending on the request origin.
Common Pitfalls
A common mistake is treating CORS as if it were API authentication. It is not. It is a browser-enforced read policy.
Another issue is returning * while also expecting browsers to send cookies. Credentialed requests require an explicit origin, not a wildcard.
Developers also often configure the main request headers but forget the OPTIONS preflight path, which breaks anything beyond the simplest request types.
Finally, reflecting arbitrary origins without an allowlist creates a weak and often accidental policy. Dynamic reflection should still be constrained.
Summary
- '
Access-Control-Allow-Origintells browsers which origins may read a cross-origin response.' - It does not replace authentication and does not stop the server from receiving the request.
- Non-simple requests may require a preflight
OPTIONSexchange. - Credentialed requests require an explicit origin, not
*. - Safe CORS setups usually use an allowlist and include
Vary: Originwhen the value is dynamic.

