3 Common CORS Errors Every Frontend Developer Faces

Posted by

If you’ve ever seen “blocked by CORS policy” in your console, this post is for you. Let’s decode the 3 most common CORS errors and how to fix each one the right way.

If you’ve ever seen “blocked by CORS policy” in your console, this post is for you. Let’s decode the 3 most common CORS errors and how to fix each one the right way.

Introduction

CORS errors are the frontend developer’s rite of passage.

You fetch data from an API, and your console explodes:

Access to fetch at 'https://api.example.com' from origin 'http://localhost:3000' 
has been blocked by CORS policy.

You try headers, proxies, Chrome extensions, even prayers, but nothing works.

The problem isn’t your JavaScript it’s the browser enforcing the Same-Origin Policy.

Let’s break down the 3 most common CORS errors, what they actually mean, and how to fix them properly from both the frontend and backend sides.


Error #1: “No ‘Access-Control-Allow-Origin’ Header Present”

What It Means

Your frontend requested another origin (like an API domain), but the server didn’t explicitly say,

“Yes, this origin is allowed.”

The browser sees that as unsafe and blocks the response.

Example

fetch("https://api.example.com/users");

Browser sends:

Origin: http://localhost:3000

Server responds without:

Access-Control-Allow-Origin: http://localhost:3000

→ ❌ Browser blocks the response before your JavaScript can access it.

✅ Fix

On your backend, add this header:

Access-Control-Allow-Origin: http://localhost:3000

For development only (not production):

Access-Control-Allow-Origin: *

Express Example

import cors from "cors";
app.use(cors({ origin: "http://localhost:3000" }));

💡 Rule: Always fix CORS on the server, never the client.


Error #2: “Preflight Request Doesn’t Pass Access Control Check”

What It Means

Your request isn’t a “simple” one; maybe you used a custom header, or the PUT / DELETE Method.
 Before sending it, the browser performs a preflight OPTIONS request to check if it’s allowed.

If your server doesn’t respond correctly → the real request never happens.

Example

fetch("https://api.example.com/update", {
method: "PUT",
headers: { "Content-Type": "application/json", Authorization: "Bearer token" },
body: JSON.stringify({ name: "Rahmat" }),
});

The browser automatically sends:

OPTIONS /update
Origin: http://localhost:3000
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization

If your server doesn’t reply with:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET,POST,PUT,DELETE
Access-Control-Allow-Headers: Content-Type,Authorization

→ ❌ The preflight fails silently.

✅ Fix

Make sure your backend handles OPTIONS requests and responds with all three headers above.

Express Example

app.options("*", cors()); // enable preflight for all routes

💡 Rule: The preflight must succeed before the real request is sent.


Error #3: “Credentialed Requests Can’t Use Wildcard (*) Origin”

What It Means

You’re sending cookies or tokens using:

fetch("https://api.example.com/session", {
credentials: "include",
});

…but your backend has:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

That combination is invalid.
 When credentials are included, browsers require a specific origin, not. *.

✅ Fix

Specify your exact frontend origin:

Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Credentials: true

And keep credentials: "include" on the frontend.

Express Example

app.use(
cors({
origin: "http://localhost:3000",
credentials: true,
})
);

💡 Rule: * And credentials are never allowed together.


Bonus: Why Postman Works but Browser Doesn’t

Because Postman is not a browser.
It doesn’t enforce CORS or Same-Origin Policy.

So when something works in Postman but fails in Chrome →
It’s almost always missing headers on your backend.


3 Debugging CORS Like a Pro

✅ Open Network → OPTIONS request in DevTools
 → check what headers are missing.

✅ Inspect the Origin header in your request
 → make sure your backend returns the same one in Access-Control-Allow-Origin.

✅ Avoid “quick fixes” like mode: "no-cors" Chrome extensions just hide the problem, not solve it.


Why These Errors Exist

CORS isn’t here to annoy you; it’s here to protect users.
Without it, any site could send hidden requests using your credentials to another service.

Once you understand the pattern browser asks for permission, the server grants it via headers, and it all starts making sense.


Conclusion

CORS in 3 lines:

  1. The browser sends a Origin header.
  2. Server responds with Access-Control-Allow-Origin friends.
  3. The browser decides if it’s safe.

When it fails, it’s almost always one of these:

  1. Missing Access-Control-Allow-Origin
  2. Preflight (OPTIONS) misconfigured
  3. Credentials with wildcard origin

Fix those three, and 95% of CORS errors disappear forever.


Call to Action

Have you run into a CORS error that wasn’t fixed by these?
Drop your setup (frontend + backend) in the comments 👇 I’ll help you debug it.

And if your teammate still says “CORS is a frontend problem”, send them this post before they add mode: "no-cors" again 😅.

Leave a Reply

Your email address will not be published. Required fields are marked *