# How to Manage CORS Policy Properly in Express with the cors Middleware

> Securely manage CORS policy in Express with the cors middleware. Learn how this npm package simplifies handling cross-origin requests and pre-flight options automatically.

- Repository: [expressjs/express](https://github.com/expressjs/express)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Use the `cors` npm package as middleware in your Express application to handle Cross-Origin Resource Sharing headers and pre-flight requests automatically.**

Express does not implement CORS internally; you must add the `cors` module to manage cross-origin policies correctly. According to the `expressjs/express` source code, the framework relies on external middleware for CORS handling, with the `cors` package being the community standard for configuring `Access-Control-*` headers and OPTIONS pre-flight responses.

## Why Express Requires an External CORS Module

The core Express library focuses on routing and middleware orchestration, not protocol-level concerns like CORS. As shown in the repository's [`package.json`](https://github.com/expressjs/express/blob/main/package.json), CORS support is listed as an optional dependency rather than a built-in feature. The dedicated `cors` middleware implements the full W3C CORS specification, validates origin inputs to prevent security mistakes, and handles complex pre-flight scenarios that would require significant boilerplate if implemented manually.

## Installing and Mounting the CORS Middleware

Install the package via npm:

```bash
npm install cors

```

Mount the middleware early in your application stack using `app.use()`. In [`lib/application.js`](https://github.com/expressjs/express/blob/main/lib/application.js) (lines 190‑226), Express implements the `use` method to register middleware that processes every incoming request. Positioning CORS at the top ensures the middleware sets headers before your route handlers execute.

```javascript
const express = require('express')
const cors = require('cors')

const app = express()

// Mount CORS before route definitions
app.use(cors())

app.get('/data', (req, res) => {
  res.json({ message: 'CORS headers already set' })
})

```

## Configuring CORS Policy Options

The `cors()` function accepts an options object that maps directly to standard CORS headers. These settings control which origins, methods, and headers your Express application permits.

### Controlling Allowed Origins

The `origin` option accepts a string, regular expression, or function to validate request origins. Set it to a specific domain for strict control, or use a function to implement dynamic whitelist logic against a database.

```javascript
// Allow only example.com
app.use(cors({ origin: 'https://example.com' }))

// Dynamic validation with callback
const whitelist = ['https://example.com', 'https://app.example.org']

app.use(cors({
  origin: (origin, callback) => {
    if (!origin || whitelist.includes(origin)) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
}))

```

### Specifying HTTP Methods and Headers

Use `methods` to whitelist HTTP verbs and `allowedHeaders` to permit custom request headers. The `exposedHeaders` option determines which response headers the browser should expose to the client-side script.

```javascript
app.use(cors({
  methods: ['GET', 'POST', 'PUT'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  exposedHeaders: ['X-Total-Count']
}))

```

### Enabling Credentials and Pre‑Flight Behavior

Set `credentials: true` to allow cookies and authorization headers in cross-origin requests. The `preflightContinue` option determines whether the middleware passes OPTIONS requests to subsequent handlers or terminates them automatically.

```javascript
app.use(cors({
  origin: 'https://trusted-site.com',
  credentials: true,
  preflightContinue: false  // Automatically respond to OPTIONS
}))

```

## Handling Pre‑Flight OPTIONS Requests

When you mount the `cors` middleware, Express automatically responds to OPTIONS pre-flight requests with the appropriate `Access-Control-*` headers. This behavior is documented in the repository's [`History.md`](https://github.com/expressjs/express/blob/main/History.md) (line 2843), which notes the addition of automatic OPTIONS handling for CORS scenarios.

No manual route definition is required unless you need custom logic for specific endpoints.

### Manual Pre‑Flight Handling

For rare cases requiring additional processing during pre-flight, explicitly handle OPTIONS while keeping the CORS middleware active:

```javascript
app.options('/special-resource', cors(), (req, res) => {
  console.log('Pre-flight from:', req.get('Origin'))
  res.sendStatus(204)   // the cors middleware already set the needed headers
})

```

## Applying CORS Globally vs. Per‑Route

You can apply CORS settings application-wide or restrict them to specific routes based on security requirements.

Global application uses `app.use(cors())` before route definitions, as shown in previous examples.

### Route‑Specific CORS Configuration

Attach the middleware directly to route definitions to override global settings or protect sensitive endpoints:

```javascript
// Public endpoint – open to all origins
app.get('/public', cors(), (req, res) => {
  res.json({ data: 'Public information' })
})

// Admin endpoint – strict origin validation with credentials
app.get(
  '/admin',
  cors({
    origin: 'https://admin.example.com',
    credentials: true
  }),
  (req, res) => {
    res.json({ data: 'Sensitive admin data' })
  }
)

```

## Summary

- **Express does not include CORS handling** in its core; you must install the `cors` middleware package.
- **Mount the middleware early** using `app.use()` (implemented in [`lib/application.js`](https://github.com/expressjs/express/blob/main/lib/application.js) lines 190‑226) to ensure headers are set before route logic executes.
- **Configure policies** via the options object to control allowed origins, methods, headers, and credentials.
- **Pre‑flight requests** are handled automatically when the middleware is active, as noted in the repository's [`History.md`](https://github.com/expressjs/express/blob/main/History.md).
- **Apply globally or per‑route** depending on whether endpoints require public access or strict origin validation.

## Frequently Asked Questions

### How do I enable CORS for all origins in Express?

Use the default `cors()` middleware without options. Mount it with `app.use(cors())` at the top of your middleware stack. This sets `Access-Control-Allow-Origin: *` and allows all standard HTTP methods.

### Why is my Express API blocking cross‑origin requests even after adding the cors middleware?

Ensure you mounted the middleware **before** defining routes. In [`lib/application.js`](https://github.com/expressjs/express/blob/main/lib/application.js), Express processes middleware in the order registered via `app.use()`. If routes are defined first, they execute before CORS headers are set. Also verify that your `origin` option does not exclude the requesting domain.

### Can I allow multiple specific origins with the Express cors module?

Yes. Provide a function to the `origin` option that checks the requesting origin against your whitelist array. Return `callback(null, true)` for allowed origins or `callback(new Error('Not allowed by CORS'))` for rejected ones. This approach supports dynamic, database‑driven origin validation.

### Does the Express cors middleware handle pre‑flight OPTIONS requests automatically?

Yes. When mounted, the middleware intercepts OPTIONS requests and responds with appropriate `Access-Control‑Allow‑*` headers without reaching your route handlers. This behavior is documented in the Express repository's [`History.md`](https://github.com/expressjs/express/blob/main/History.md). You only need manual OPTIONS handling if you require custom logic during the pre‑flight phase.