That CORS Error Isn’t a Bug — It’s Actually Protecting Your Web App
Source: Dev.to
If you’ve worked with APIs in a web app, you’ve probably seen this error at least once:
Access to fetch has been blocked by CORS policy
It feels annoying:
- Your API URL is correct.
- Your code looks fine.
But the browser just refuses to cooperate.
At first, it feels like a bug or mis‑configuration. The truth is:
CORS is not an error — it’s a security feature doing exactly what it’s supposed to do.
In this article, let’s understand CORS in simple words, see why it exists, what problems it solves, and why the browser behaves this way.
1. Why CORS Exists in the First Place
To understand CORS, imagine a situation without it.

Suppose you are logged into:
facebook.com- or your bank website like
hdfc.com
Your browser stores cookies or tokens so you stay logged in.
Now, in another tab, you open a random (maybe malicious) website. That site also runs JavaScript.
If there were no restrictions, that JavaScript could send a request like:
fetch("https://hdfc.com/api/balance")
Because the request originates from your browser, your bank cookies would automatically be sent along.
The bank server would think:
“This request is from a logged‑in user.”
and might return sensitive data like your balance.
This is dangerous.
To prevent this, browsers enforce the Same‑Origin Policy (SOP):
- A website can only access data from the same origin by default.
CORS (Cross‑Origin Resource Sharing) is a controlled way to relax this rule — but only when the server explicitly allows it.
2. What Exactly Is an “Origin”?
An origin consists of three parts:
| Part | Example |
|---|---|
| Scheme | http or https |
| Host | domain name (example.com) |
| Port | 80, 443, 5173, etc. |
If any one of these changes, the origin is different.
Examples
| Origin A | Origin B | Same? |
|---|---|---|
https://yuktisahu.dev | https://api.yuktisahu.dev | ❌ (different host) |
https://yuktisahu.dev | http://yuktisahu.dev | ❌ (different scheme) |
http://localhost:5173 | http://localhost:8000 | ❌ (different port) |
https://example.com/page1 | https://example.com/page2 | ✅ (same origin – path doesn’t matter) |
Browsers use this definition to decide whether a request is cross‑origin.
3. Why You Can’t Fix CORS from the Frontend
This is one of the most confusing parts for beginners.
You see the error in the browser console, so you try to fix it in your frontend code.
But CORS is not controlled by frontend code.
What actually happens
-
Your frontend sends a request to another origin.
-
The browser automatically adds an
Originheader. -
The server checks this
Origin. -
If the server trusts the origin, it includes the header in the response:
Access-Control-Allow-Origin: https://yuktisahu.dev -
If the header is missing or doesn’t match your origin, the browser blocks the response, and your JavaScript never sees it.
So even if the server responds, the browser refuses to give that response to your code.
That’s why CORS must be fixed on the server, not the frontend.
4. Why It Works in Postman but Not in the Browser
Another common confusion:
“The API works in Postman, so why does it fail in my web app?”
Because CORS is a browser security rule, not a server rule.
| Tool | How it treats CORS |
|---|---|
Postman (or curl) | Not a browser → no CORS enforcement, no cookies from other sites. |
| Browsers | Run code from many sites simultaneously, store cookies for sensitive sites, must protect users from data leaks. |
Only browsers enforce CORS. Postman and curl don’t need to.
5. Cookies Make CORS Stricter
Sometimes your frontend needs to send cookies with the request:
fetch(url, {
credentials: "include"
})
When you do this, the rules become stricter:
-
The server cannot respond with a wildcard:
Access-Control-Allow-Origin: * -
It must explicitly specify the allowed origin and also allow credentials:
Access-Control-Allow-Origin: https://yuktisahu.dev Access-Control-Allow-Credentials: true
This is intentional.
If cookies are involved, the server must clearly trust one specific origin, not everyone.
6. What Is a Preflight Request?
Some requests are “simple”, e.g.:
GET- Basic
POST(withContent-Type: application/x-www-form-urlencoded,multipart/form-data, ortext/plain)
Other requests are considered “complex”, such as:
PUT,PATCH,DELETE- Requests with custom headers
- Requests with
Content-Type: application/json
For these, the browser sends an extra request first:
OPTIONS /api
This is called a preflight request. It asks the server:
“Is it okay if I send this kind of request with these headers?”
If the server responds with the appropriate CORS headers, the browser proceeds with the actual request. If not, the browser blocks it completely.
Final Thoughts
CORS feels frustrating because it stops your code, but it exists to protect:
- Logged‑in users
- Sensitive data
- Browser security boundaries
Once you understand that:
- CORS errors make more sense.
- Debugging becomes easier.
- You know the fix is always on the server side.
So the next time you see a CORS error, instead of trying to “fix it in JavaScript”, check the server’s CORS configuration (or use a proxy during development) and you’ll be back on track.
Thinking “something is broken”, think:
“The browser is protecting users — and the server hasn’t given permission yet.”