
How the Access-Control-Allow-Origin Header Works: A Complete Guide
Last updated 2 weeks, 4 days ago | 44 views 75 5

Certainly! Here's a detailed article on the Access-Control-Allow-Origin
header, covering how it works, step-by-step explanations, code examples, and common pitfalls.
How the Access-Control-Allow-Origin
Header Works: A Complete Guide
When building modern web applications, you may encounter the dreaded CORS error. One of the most important headers that governs this behavior is the Access-Control-Allow-Origin
header.
This article will guide you through:
-
What this header does
-
How it affects cross-origin requests
-
Real-world examples with code
-
A complete server-side configuration
-
Tips and common pitfalls to avoid
What Is Access-Control-Allow-Origin
?
The Access-Control-Allow-Origin
header is part of the Cross-Origin Resource Sharing (CORS) specification. It tells the browser which origins are allowed to access resources on the server.
Understanding Origins
An origin consists of:
-
Protocol (http / https)
-
Domain (example.com)
-
Port (optional)
Example:
Origin A: https://example.com
Origin B: http://api.example.com
These are different origins!
So, if your frontend at https://frontend.com
tries to fetch data from https://api.backend.com
, it’s a cross-origin request.
⚙️ How the Header Works (Step-by-Step)
1. Browser Sends Request
When the frontend JavaScript (e.g., with fetch()
or XMLHttpRequest
) tries to access a different origin, the browser sends a request like:
Origin: https://frontend.com
2. Server Responds with Header
The server must explicitly allow access by responding with:
Access-Control-Allow-Origin: https://frontend.com
Or, to allow all:
Access-Control-Allow-Origin: *
If the header is missing or incorrect, the browser blocks the response.
✅ Simple Example (Server and Client)
Server (Node.js / Express Example)
const express = require("express");
const app = express();
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "https://frontend.com");
next();
});
app.get("/data", (req, res) => {
res.json({ message: "Data from server" });
});
app.listen(3000, () => console.log("API running on port 3000"));
Replace
https://frontend.com
with the actual domain of your frontend.
Client (JavaScript)
fetch("https://api.yourdomain.com/data")
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error("CORS error:", err));
Example with Wildcard (Allowing All Origins)
Access-Control-Allow-Origin: *
⚠️ Important: If you use *
, you cannot send credentials (cookies, HTTP auth).
Credentials Use Case
If you need to allow cookies/auth headers:
Access-Control-Allow-Origin: https://frontend.com
Access-Control-Allow-Credentials: true
And in your fetch()
:
fetch("https://api.yourdomain.com/data", {
credentials: "include",
});
✅ You must not use *
with Access-Control-Allow-Credentials
.
Complete Example (PHP)
<?php
// allow from specific origin
header("Access-Control-Allow-Origin: https://frontend.com");
// optional headers
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
echo json_encode(["status" => "success", "message" => "Hello from PHP!"]);
?>
✅ Tips
-
Dynamically match
Origin
header if you serve multiple frontends. -
Always restrict origins in production — don’t leave
*
open unless absolutely necessary. -
Use CORS middleware (e.g.,
cors
in Express ordjango-cors-headers
) for simpler setup.
⚠️ Common Pitfalls
Mistake | Explanation |
---|---|
Using * with credentials: true |
This violates the CORS spec and won’t work |
Not responding to OPTIONS request |
Preflight checks require a valid response |
Setting wrong domain in Access-Control-Allow-Origin |
Must exactly match the Origin header |
Forgetting CORS on non-GET methods | PUT/POST often require preflight permission |
Client errors hard to debug | CORS errors are silently blocked by browsers, making debugging tricky |
Bonus: Express with Dynamic Origin Handling
const cors = require("cors");
const whitelist = ["https://frontend.com", "https://admin.frontend.com"];
const corsOptions = {
origin: function (origin, callback) {
if (whitelist.includes(origin)) {
callback(null, true);
} else {
callback(new Error("Not allowed by CORS"));
}
},
credentials: true,
};
app.use(cors(corsOptions));
Conclusion
The Access-Control-Allow-Origin
header is your key to unlocking safe and secure cross-origin requests. With careful configuration, you can allow your frontend apps to communicate with your APIs while maintaining security.