CORS
The browser protects visitors: a script on one site's page cannot simply read another site's response. A site is identified by its origin — the scheme, domain and port. CORS (Cross-Origin Resource Sharing) is a set of rules by which a server tells the browser which foreign origins may read its responses.
When you need it
Say the blog's React frontend runs at http://localhost:5173 and the API at http://localhost:3000. The ports differ, so the origins differ too. The frontend script makes a request:
// src/main.js (frontend)
const response = await fetch('http://localhost:3000/api/posts');
const posts = await response.json();
console.log(posts);The server answers, but the browser does not hand the response to the script and logs an error with the words blocked by CORS policy in the console. A request from curl or from another server still works: only the browser checks CORS.
Installation
npm install corsAllowing one origin
Add the middleware in src/app.js for the API addresses:
// src/app.js
import cors from 'cors';
app.use('/api', cors({ origin: 'http://localhost:5173' }));The middleware adds the header Access-Control-Allow-Origin: http://localhost:5173 to responses. Reload the frontend page and the array of posts appears in the console.
Several origins
origin also accepts an array — for example, the development address and the production domain:
// src/app.js
app.use('/api', cors({
origin: ['http://localhost:5173', 'https://example.com'],
methods: ['GET', 'POST', 'PATCH', 'DELETE'],
}));The browser still blocks requests from other sites.
The preflight request
Before "non-simple" requests — such as DELETE, or a POST with JSON and an Authorization header — the browser first sends a request with the OPTIONS method on its own. It asks the server whether such a request is allowed. The cors middleware answers it by itself when mounted with app.use(): no extra code is needed.
| Response header | What it allows |
|---|---|
Access-Control-Allow-Origin | Reading the response from the given origin |
Access-Control-Allow-Methods | Using the listed methods |
Access-Control-Allow-Headers | Sending the listed headers |
Access-Control-Allow-Credentials | Sending cookies |
Cookies from another origin
If the frontend must send the session cookie, you need two things: the credentials: true option in cors() on the server and credentials: 'include' in fetch() on the client. With a JWT in the Authorization header this is not required.
Common mistake
Calling cors() without options allows requests from any site. For a public read-only API that is acceptable, but not for addresses that change data. Always list your origins in origin. And remember: CORS does not replace authentication — it restricts only browsers, and programs can reach the API directly.