Learn how to allow frontend applications to communicate with your Node.js and Express.js APIs using Cross-Origin Resource Sharing (CORS).
An origin consists of three parts:
Frontend: http://localhost:3000
Backend API: http://localhost:5000
These are different origins because their port numbers are different. A browser request from the frontend to the backend may require CORS permission.
Two URLs can have different origins if their protocol, hostname, or port differs.
Suppose you create a React application on port 3000 and an Express API on port 5000. Your frontend tries to fetch student data from the API.
fetch("http://localhost:5000/students")
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
If the backend does not provide the required CORS headers, the browser may block JavaScript from reading the response.
Express applications commonly use the cors middleware
package to configure CORS headers.
npm install cors
Run this command inside your Node.js project directory.
The following example allows requests from any origin for this API. Use an appropriate origin policy for your application.
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.get("/", (req, res) => {
res.send("CORS is enabled!");
});
app.get("/students", (req, res) => {
res.json([
{ id: 1, name: "Rahul" },
{ id: 2, name: "Priya" }
]);
});
app.listen(5000, () => {
console.log("Server running on port 5000");
});
require("express") imports Express.require("cors") imports the CORS middleware.app.use(cors()) enables the package's default CORS configuration./students returns a JSON array of students.app.listen(5000) starts the server on port 5000.In production, it is usually better to allow only the frontend origins that need access to your API.
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors({
origin: "http://localhost:3000"
}));
app.get("/students", (req, res) => {
res.json([
{ id: 1, name: "Aman" },
{ id: 2, name: "Neha" }
]);
});
app.listen(5000, () => {
console.log("Server running on port 5000");
});
In this example, the CORS configuration allows the frontend origin
http://localhost:3000. Replace it with your actual
frontend origin when deploying your application.
If your application has multiple trusted frontend URLs, you can check the request origin against an allowlist.
const express = require("express");
const cors = require("cors");
const app = express();
const allowedOrigins = [
"http://localhost:3000",
"https://soopropathshala.com"
];
app.use(cors({
origin: function (origin, callback) {
// Requests without an Origin header may come from
// tools or server-to-server clients.
if (!origin || allowedOrigins.includes(origin)) {
return callback(null, true);
}
return callback(new Error("Origin not allowed by CORS"));
}
}));
app.get("/api", (req, res) => {
res.json({
message: "Welcome to the API"
});
});
app.listen(5000, () => {
console.log("Server running on port 5000");
});
You can specify which HTTP methods browser requests may use.
app.use(cors({
origin: "http://localhost:3000",
methods: ["GET", "POST", "PUT", "DELETE"]
}));
The configuration above lists the permitted methods for CORS requests. Your Express routes must still implement the corresponding operations.
Sometimes the frontend sends custom headers, such as an authorization token. You can configure which request headers the browser may use.
app.use(cors({
origin: "http://localhost:3000",
methods: ["GET", "POST", "PUT", "DELETE"],
allowedHeaders: ["Content-Type", "Authorization"]
}));
For example, a frontend can send a JSON request with an authorization header:
fetch("http://localhost:5000/students", {
method: "GET",
headers: {
"Authorization": "Bearer YOUR_TOKEN"
}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
Before some cross-origin requests, the browser sends an HTTP
OPTIONS request to check whether the actual request is allowed.
This is called a preflight request.
Requests using certain methods, custom headers, or content types may trigger preflight checks. A simple GET request does not always require preflight.
When the CORS middleware is correctly installed before your routes, it can handle the preflight requests for those routes.
If a frontend needs to send cookies or other browser credentials, the server and client must be configured accordingly.
app.use(cors({
origin: "http://localhost:3000",
credentials: true
}));
On the frontend, a fetch request can include credentials:
fetch("http://localhost:5000/profile", {
method: "GET",
credentials: "include"
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
origin: "*". Configure a specific trusted origin instead.
CORS settings do not replace secure cookie settings, authentication,
authorization, or CSRF protection where applicable.
| Problem | Possible Solution |
|---|---|
| CORS error in browser | Check the response headers and configure the required origin. |
| Wrong frontend origin | Check the protocol, hostname, and port carefully. |
| OPTIONS request fails | Check middleware order, server handling, and preflight headers. |
| Custom header is rejected | Configure the required header in allowedHeaders. |
| Credentials are not working | Use a specific allowed origin and configure credentials on both sides. |
| API does not respond | Check the server, URL, port, network, and route separately. |
Follow these steps to test your Express API:
fetch().Create a Node.js application with the following requirements:
cors package./courses.http://localhost:3000.Bonus: Add a POST route and configure the required request headers.
Select the correct answer for each question.