Cross-Origin Resource Sharing CORS
Cross-Origin Resource Sharing, also called CORS, is a browser security mechanism that controls whether one origin can access resources from another origin.
It is mainly used when frontend code running on one domain tries to call an API from another domain.
Example:
def.com wants to access data from api.abc.com
Even if api.abc.com exposes a public API, the browser still checks whether api.abc.com has allowed def.com to access the resource.
One-line idea: CORS lets the server tell the browser which origins are allowed to access its resources.
Core Concepts
What It Is
CORS is a browser-level security rule that checks whether a cross-origin request is allowed by the target server.
Simple meaning:
Frontend wants data from another origin
↓
Browser checks if cross-origin access is allowed
↓
Server sends CORS headers
↓
Browser allows or blocks the response
Important point:
CORS is enforced by the browser.
The server decides who is allowed.
Why It Matters
Browsers protect users by preventing random websites from reading data from other domains.
Without CORS, any website could try to call APIs from another domain and read responses.
Example:
malicious-site.com
↓
tries to access
bank-api.com/user-data
CORS helps by making the browser ask:
Has bank-api.com allowed this origin?
If not, the browser blocks the response.
Same-Origin Policy
By default, browsers follow Same-Origin Policy.
Same-Origin Policy means:
A page can access resources from the same origin.
A page cannot freely access resources from a different origin.
An origin is mainly decided by:
protocol + domain + port
Example origin:
http://example.com:8080
Breakdown:
| Part | Value |
|---|---|
| Protocol | http |
| Domain | example.com |
| Port | 8080 |
Cross-Origin Request
A request becomes cross-origin when protocol, domain, port, or subdomain is different.
| Difference | Example |
|---|---|
| Different protocol | http://a.com → https://a.com |
| Different port | localhost:4000 → localhost:4001 |
| Different domain | a.com → b.com |
| Different subdomain | a.com → subdomain.a.com |
Simple mental model:
Same protocol + same domain + same port = same origin
Anything different = cross-origin
Core Flow
The CORS flow looks like this:
Client JavaScript sends request
↓
Browser checks if request is cross-origin
↓
Browser may send preflight OPTIONS request
↓
Server responds with CORS headers
↓
Browser decides whether original request is allowed
↓
If allowed, browser sends original request
↓
Server sends actual response
If the server does not allow the origin:
Browser blocks the request/response
↓
CORS error appears in console
Main CORS Headers
The PDF lists these important CORS headers:
| Header | Purpose |
|---|---|
Access-Control-Allow-Origin | Defines which origin is allowed |
Access-Control-Allow-Methods | Defines which HTTP methods are allowed |
Access-Control-Allow-Headers | Defines which request headers are allowed |
Access-Control-Allow-Credentials | Defines whether credentials are allowed |
Access-Control-Expose-Headers | Defines which response headers frontend JS can read |
Practical Examples
Access-Control-Allow-Origin
This header tells the browser which origin can access the response.
Example:
Access-Control-Allow-Origin: http://127.0.0.1:5500
Meaning:
Only http://127.0.0.1:5500 is allowed to access this response.
If the origin does not match, the browser blocks access.
Access-Control-Allow-Methods
This header tells the browser which HTTP methods are allowed.
Example:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Meaning:
The server allows these methods for cross-origin requests.
Access-Control-Allow-Headers
This header tells the browser which custom request headers are allowed.
Example:
Access-Control-Allow-Headers: Content-Type, Authorization
This is useful when the client sends custom headers like tokens or content type.
Access-Control-Allow-Credentials
This header is related to cookies or credentials.
Example:
Access-Control-Allow-Credentials: true
Meaning:
Browser may allow credentials like cookies when configured properly.
Access-Control-Expose-Headers
By default, frontend JavaScript cannot read every response header.
This header tells the browser which response headers should be exposed to JavaScript.
Example:
Access-Control-Expose-Headers: X-Total-Count
Meaning:
Frontend code can read X-Total-Count from the response.
Preflight Request
For some cross-origin requests, the browser first sends a preflight request.
A preflight request is sent using the OPTIONS method.
Simple flow:
Client wants to send cross-origin request
↓
Browser sends OPTIONS request first
↓
Server responds with allowed origins/methods/headers
↓
Browser checks the response
↓
If allowed, original request is sent
↓
If not allowed, request is stopped
Important point:
If preflight fails, the browser will not send the original request.
Preflight Example Flow
Client JavaScript
↓
Browser detects cross-domain API call
↓
Browser sends OPTIONS preflight request
↓
Server sends preflight response with CORS headers
↓
Browser validates the headers
↓
Browser sends actual request
↓
Server sends actual response
↓
Client receives data
If not allowed:
Browser sends OPTIONS request
↓
Server does not allow origin/method/header
↓
Browser terminates the request
↓
Original request is not sent
Example 1: Calling Google Search API
The PDF shows an example where a local HTML page tries to fetch a Google search URL.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fetch with CORS Example</title>
</head>
<body>
<h1>Fetch with CORS Example</h1>
<button onclick="fetchData()">Fetch Data</button>
<div id="result"></div>
<script>
function fetchData() {
fetch("https://www.google.com/search?q=sharvil+ajmani", {
method: "GET",
})
.then((response) => response.json())
.then((data) => {
document.getElementById("result").innerText = JSON.stringify(
data,
null,
2,
);
})
.catch((error) => {
console.error("Error:", error);
});
}
</script>
</body>
</html>
When the button is clicked:
Local page tries to access Google
↓
Browser sees cross-origin request
↓
Google does not allow this origin for this fetch
↓
Browser shows CORS error
Example 2: Local Client and Server
The PDF also shows a local setup with:
client/index.html
server/index.js
The client runs on one port and the server runs on another port.
Client code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fetch with CORS Example</title>
</head>
<body>
<h1>Fetch with CORS Example</h1>
<button onclick="fetchData()">Fetch Data</button>
<div id="result"></div>
<script>
function fetchData() {
fetch("http://localhost:5010/list", {
method: "GET",
})
.then((response) => response.json())
.then((data) => {
document.getElementById("result").innerText = JSON.stringify(
data,
null,
2,
);
})
.catch((error) => {
console.error("Error:", error);
});
}
</script>
</body>
</html>
Server code:
const express = require("express");
const app = express();
app.get("/list", (req, res) => {
res.send([
{
id: 1,
title: "Namaste Frontend System Design",
},
]);
});
const port = process.env.PORT || 5010;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
If the client is running on another port, the browser treats it as cross-origin.
Example:
Client: http://127.0.0.1:5500
Server: http://localhost:5010
Since the port/origin is different, the browser blocks the request unless the server allows it.
Fixing CORS Using cors Package
The PDF shows using the cors package in Express.
Install/use:
cors package
NPM package:
https://www.npmjs.com/package/cors
Server code with allowed origin:
const express = require("express");
const app = express();
const cors = require("cors");
var allowedOrigin = ["http://127.0.0.1:5500"];
const corsOptions = {
origin: function (origin, callback) {
if (allowedOrigin.indexOf(origin) !== -1 || !origin) {
callback(null, true);
} else {
callback(new Error("CORS error"));
}
},
};
app.use(cors(corsOptions));
app.get("/list", (req, res) => {
res.send([
{
id: 1,
title: "Namaste Frontend System Design",
},
]);
});
const port = process.env.PORT || 5010;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Here, only this origin is allowed:
http://127.0.0.1:5500
Flow:
Client origin is 127.0.0.1:5500
↓
Server checks allowedOrigin list
↓
Origin exists in whitelist
↓
CORS headers are returned
↓
Browser allows response
What Happens If Wrong Origin Is Allowed
The PDF also shows changing the allowed origin to a different port:
var allowedOrigin = ["http://127.0.0.1:5501"];
But the client is running on:
http://127.0.0.1:5500
Now the flow becomes:
Client origin is 127.0.0.1:5500
↓
Server allowed list has 127.0.0.1:5501
↓
Origin does not match
↓
Server throws CORS error
↓
Browser shows CORS error
This proves that CORS should be configured with the correct allowed origins.
CORS and Browser Extensions
The PDF mentions that some developers install browser CORS extensions and are able to access APIs from cross-domain.
But this should not be treated as a real fix.
Important mental model:
Browser extension may bypass local browser restriction
↓
But real users will still face CORS issues
↓
Proper CORS headers must be set on the server
Correct fix:
Configure server CORS policy properly.
Do not depend on browser extensions.
CORS Whitelisting
Whitelisting means allowing only selected origins.
Good approach:
Allow only trusted origins
Reject all others
Example:
const allowedOrigin = ["http://127.0.0.1:5500"];
This is safer than allowing every origin.
Mental model:
Do not allow everyone.
Allow only known frontend domains.
Common CORS Error Reason
CORS errors usually happen because:
| Reason | Explanation |
|---|---|
| Server did not send CORS headers | Browser blocks response |
| Origin is not allowed | Access-Control-Allow-Origin does not match |
| Method is not allowed | Request method is missing in allowed methods |
| Header is not allowed | Custom request header is not allowed |
| Credentials are not configured properly | Cookies/auth credentials need proper config |
| Wrong port/domain/protocol | Browser treats it as cross-origin |
Interview Revision
Quick Revision Checklist
- Check the frontend origin.
- Check the backend/API origin.
- Compare protocol, domain, and port.
- Confirm whether the request is cross-origin.
- Check browser console CORS error message.
- Check Network tab for preflight OPTIONS request.
- Make sure server sends Access-Control-Allow-Origin.
- Make sure server allows required methods.
- Make sure server allows required headers.
- Add credentials config only if needed.
- Use whitelisting for allowed origins.
- Do not rely on CORS browser extensions.
- Configure CORS on the server, not only on the client.
Frequently Asked Interview Questions
1. What is Cross-Origin Resource Sharing CORS?
Cross-Origin Resource Sharing, also called CORS, is a browser security mechanism that controls whether one origin can access resources from another origin.
2. Why is Cross-Origin Resource Sharing CORS important?
Browsers protect users by preventing random websites from reading data from other domains.
3. What practical rule should you remember?
Check the frontend origin. Check the backend/API origin.
Memory Trick
What It Is → Why It Matters → Same-Origin Policy
One-Line Summary
CORS lets the server tell the browser which origins are allowed to access its resources.
Final Mental Model
Different origin request
↓
Browser asks server: Is this origin allowed?
↓
Server responds with CORS headers
↓
Browser allows or blocks
Remember it like this:
Same origin -> allowed by default
Cross origin -> needs server permission
Preflight -> browser asks before real request
CORS headers -> server's permission rules
Or:
CORS is not an API problem only.
It is the browser enforcing server-defined access rules.