CORS Configuration: Secure Your API with Express Middleware
Learn how to configure CORS in Express to allow your frontend to communicate with your API, handle preflight requests, and keep your application secure.

Previously in this course, we discussed adding logging to your API to track request activity. Now that we can monitor our traffic, we need to address a common "gotcha" for new backend developers: the browser's security mechanism that blocks your frontend from calling your API.
Understanding CORS from First Principles
By default, browsers implement the Same-Origin Policy (SOP). This security feature prevents a script on one website (e.g., myapp.com) from making requests to a different domain (e.g., api.myapp.com) unless the server explicitly gives permission.
Cross-Origin Resource Sharing (CORS) is the mechanism that allows servers to "opt-in" to allowing requests from specific origins. Without a proper CORS policy, your browser will block your frontend application from reading the data returned by your API, even if the request technically reaches the server.
Installing and Configuring the CORS Middleware
The most efficient way to manage these headers in an Express application is by using the community-standard cors package.
First, install the package in your project directory:
Bashnpm install cors
Once installed, you need to register it as middleware. In your main server file (usually index.js or app.js), import and use it:
JAVASCRIPTconst express = require(CE9178">'express'); const cors = require(CE9178">'cors'); const app = express(); // Enable CORS for all routes app.use(cors()); app.get(CE9178">'/api/data', (req, res) => { res.json({ message: CE9178">'Hello from the API!' }); });
Using app.use(cors()) without arguments enables CORS for all origins (using the * wildcard). While this works for development, it is not recommended for production.
Restricting Allowed Origins
In a production environment, you should only allow requests from the specific domains that host your frontend. You can configure this by passing an options object to the cors function:
JAVASCRIPTconst corsOptions = { origin: CE9178">'https://www.my-frontend-app.com', // Only allow this domain methods: [CE9178">'GET', CE9178">'POST'], optionsSuccessStatus: 200 }; app.use(cors(corsOptions));
Handling Preflight Requests
When your frontend makes "non-simple" requests (like those using PUT, DELETE, or custom headers), the browser performs a "preflight" check. It sends an OPTIONS request to your server to ask, "Are you allowed to receive this type of request?"
The cors middleware handles these OPTIONS requests automatically. You don't need to write custom logic to respond to them; simply configuring the middleware correctly ensures that the browser receives the necessary headers (Access-Control-Allow-Origin, Access-Control-Allow-Methods, etc.) to proceed with the actual request.
| Request Type | Description | Handled by cors? |
|---|---|---|
| Simple | GET, POST (standard content types) | Yes |
| Preflight | PUT, DELETE, custom headers | Yes (automatic) |
Hands-on Exercise
- Open your project and install the
corspackage. - In your Express app, configure the middleware to only allow requests from
http://localhost:3000(the common default for React/Vue development servers). - Test your API using a simple frontend fetch call from a different port. Verify that the response is successful and that you see the
Access-Control-Allow-Originheader in your browser's Network tab.
Common Pitfalls
- Over-permissiveness: Never use
app.use(cors())in production if you don't have to. Always restrict theoriginto your specific frontend URL to prevent unauthorized sites from interacting with your API. - Order of Middleware: Always place your
app.use(cors())call before your route definitions. If you place it after, the routes will be processed before the CORS headers are attached, causing the browser to block the response. - Ignoring Preflight Errors: If your browser console shows "CORS error" on a
DELETErequest but not on aGETrequest, it is likely a preflight failure. Check your server logs to ensure theOPTIONSmethod isn't being blocked by other custom logic.
For more detailed security considerations, read about preventing improper CORS policy configuration to avoid common vulnerabilities like credential theft.
FAQ
Does CORS protect my API from hackers?
No. CORS is a browser-level security feature. It does not stop someone from using tools like Postman or curl to hit your API endpoints. Always use proper authentication and authorization for that.
Why am I still getting a CORS error after adding the middleware?
Check your browser console. If the error mentions "Origin not allowed," double-check that your origin configuration matches the frontend URL exactly, including the protocol (http vs https).
Can I allow multiple origins?
Yes, you can pass an array of strings to the origin property: origin: ['https://app1.com', 'https://app2.com'].
Recap
We've covered the basics of enabling communication between your frontend and your API. By using the cors middleware, restricting origins to production domains, and letting Express handle preflight OPTIONS requests, you've bridged the gap between your server-side logic and the browser.
Up next: We'll dive into how to process user search queries using URL parameters.
Work with me

Laravel REST API Development
Clean, secure, well-documented Laravel REST APIs โ the backend engine for your app, mobile client, or SaaS. Built by an API specialist.

VPS Server Setup, Deployment & Hardening
Get your app live on a fast, secure server โ properly configured, hardened, and deployment-ready. No more wrestling with the command line.


