In short
Your frontend on localhost:5173 calls your API on localhost:3000, and the console shouts 'blocked by CORS policy'. Every backend developer meets this error. Here's what it really means.
Cross-Origin Resource Sharing — a browser security mechanism that blocks a frontend on one origin from calling an API on another origin unless the server explicitly allows it.

Think of it like this
The society gate list
Any visitor can walk up to the gate, but the guard checks the resident's approved list before letting them in. The resident writes the list, the guard enforces it. With CORS, your server writes the list of allowed websites, and the browser is the guard.
Watch it happen
A preflight from app.example.com
fetch POST /orders
1/7Code on app.example.com calls api.example.com, a different origin, with a JSON body.
The big ideas
What you need to know
Origin = scheme + host + port
http://localhost:5173 and http://localhost:3000 are different origins, just because the port differs.
Browsers enforce it
CORS is a browser rule. curl, Postman and other servers ignore it completely.
Preflight comes first
JSON bodies, custom headers, or methods like PUT and DELETE trigger an OPTIONS request before the real one.
Cookies need an exact origin
To send cookies cross-origin, the server must name the exact origin and allow credentials. "*" won't work.
See it in code
Walk through the code
1import express from "express";2import cors from "cors";3 4const app = express();5 6app.use(cors({7 origin: ["https://app.example.com", "http://localhost:5173"],8 methods: ["GET", "POST", "PATCH", "DELETE"],9 credentials: true, // allow cookies; origin can't be "*" then10}));11 12app.post("/orders", express.json(), (req, res) => {13 res.status(201).json({ ok: true });14});1/3List exactly which websites may read your responses.
The cors package answers OPTIONS preflights for you and adds the right Access-Control-* headers. On the frontend, send cookies with fetch(url, { credentials: "include" }).
Save yourself the pain
Common mistakes
Oops
Thinking CORS protects your API from attackers.
Do this instead
CORS only controls which websites a browser lets read responses. Scripts and curl skip it, so you still need real auth.
Oops
Setting origin "*" together with credentials: true.
Do this instead
Browsers reject that combination. List the exact origins that may send cookies.
Your mission
Trigger a CORS error, then fix it
Quick check
Your fetch from app.example.com fails with a CORS error, but the same request works in Postman. Why?
Go deeper
- 1Trigger a CORS error deliberately by calling an API from a different origin.
- 2Configure CORS headers on an Express server to allow a specific frontend origin.
- 3Learn the difference between simple requests and preflighted (OPTIONS) requests.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.