If you’ve ever screamed at your monitor because of a mysterious CORS error…
Congratulations — you are officially a web developer. 🎉
CORS is like that strict bouncer outside the club who won’t let you in even though you swear you're on the list.
This blog will finally explain the difference between Client-Side CORS and Server-Side CORS, without making your brain melt like a broken build.
🧐 What Is CORS, Really?
CORS stands for Cross-Origin Resource Sharing — which sounds fancy, but really means:
“Hey browser, can this website talk to that other website? Or is it a stranger danger situation?”
The browser is extremely paranoid.
If domain A calls domain B, the browser goes:
“Hold up. Who sent you? Show me your passport, Aadhar card, PAN card, and two 2x2 photos.”
🤓 Client-Side vs Server-Side CORS: The Plot Twist
People keep saying “client-side CORS” and “server-side CORS,” but here’s the truth:
Only the server decides CORS. The client is just a confused teenager asking for permission.
Still, both sides play a role — so let’s decode them.
🔵 Client-Side CORS (AKA: The Illusion of Control)
Developers be like:
fetch("/api", { mode: "cors" })
And expect the browser to go:
“Yes sir! CORS enabled! You’re a genius!”
But no.
The browser basically says:
“Cute. But I enforce the rules. Sit down.”
Client-side "CORS" is really about how you send the request:
-
mode: "cors"→ “Please let me in!” -
mode: "no-cors"→ “Fine, I’ll leave. I didn’t want to see the response anyway.” -
credentials: "include"→ “Here are my cookies, please don’t judge.”
⚠️ But the client CANNOT actually enable CORS.
It’s like trying to unlock a door by telling the door politely.
The server still holds the key.
🟣 Server-Side CORS (The Real Boss Here)
This is where the actual magic happens.
If the server doesn’t approve your origin…
The browser will block you faster than a bad ex.
Servers respond with headers like:
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Only then does the browser say:
“Okay, fine. I guess you're allowed in.”
Example (Express.js)
app.use(cors({
origin: "https://myapp.com",
credentials: true
}));
Example (Next.js API Route)
res.setHeader("Access-Control-Allow-Origin", "https://myapp.com");
res.setHeader("Access-Control-Allow-Credentials", "true");
If you forget even one header?
Boom.
CORS error.
Your day is ruined. Your coffee goes cold. Your teammates hear a scream.
🧪 Simple vs Preflight Requests (AKA: Browser Drama)
The browser sends:
👉 Simple requests
These are chill. The browser is like:
“GET or POST with simple headers? Fine, go ahead.”
👉 Preflight requests
These are drama.
If you use:
-
PUT,PATCH,DELETE - Custom headers
- JSON body
The browser becomes your mom:
“Wait. Before you go, WHERE are you going? Who’s going with you? When will you come back???”
It sends an OPTIONS request first.
If the server doesn’t respond correctly?
Blocked. Again.
🧠 Summary Table for Geniuses Who Scrolled Too Fast
| Thing | Client Side | Server Side |
|---|---|---|
| Who’s in control? | Lol. Not you. | The real boss. |
| Can it allow a request? | ❌ Nope | ✅ Absolutely |
| Can it trigger preflight? | ✅ Yes | ⚠️ Must respond properly |
| Is it real CORS? | ❌ No | ✅ Yes, 100% legit |
Final Thoughts
CORS errors might feel like a personal attack from the universe, but the rule is simple:
Client requests. Server approves. Browser judges.
Just like real life.
If everyone plays their part correctly, CORS becomes easy.
If not… well, enjoy the next 3 hours of debugging. 😅
Top comments (0)