Overview
CORS, or Cross-Origin Resource Sharing, is a security mechanism implemented by web browsers that controls how resources on a web page can be requested from another domain. It operates as a gatekeeper, enforcing a set of rules that determine whether a browser should allow a script from one origin (domain, protocol, or port) to access resources from a different origin.
Developers commonly encounter CORS when building web applications that make API calls to external services or when their frontend and backend are hosted on separate domains. The mechanism is essential for maintaining security on the web, preventing unauthorized cross-site requests that could lead to data leakage or malicious behavior.

Why It Matters
CORS is critical for maintaining web application integrity and user data protection. Without CORS, browsers would not enforce any restrictions on cross-origin requests, leaving applications vulnerable to attacks such as Cross-Site Request Forgery (CSRF) or data exfiltration. When CORS is misconfigured, it can either block legitimate requests or expose sensitive endpoints to unauthorized access.
For developers, CORS directly impacts how APIs are structured and how frontend and backend services communicate. A misconfigured CORS policy can prevent legitimate API consumers from accessing resources, while overly permissive policies can expose internal services to malicious actors. Understanding CORS is crucial for secure, maintainable, and interoperable web applications.
How It Works
CORS operates through a series of HTTP headers that are exchanged between the client and server during a request. The browser sends a preflight request using the OPTIONS method for certain types of cross-origin requests, and the server responds with appropriate headers to indicate whether the request is allowed.
- Requests to origins that are not the same as the document’s origin are considered cross-origin and are subject to CORS checks.
- The browser automatically sends an OPTIONS preflight request for requests with custom headers or for non-simple HTTP methods such as PUT or DELETE.
- The server must respond with headers like
Access-Control-Allow-Origin,Access-Control-Allow-Methods, andAccess-Control-Allow-Headersto indicate which origins, methods, and headers are permitted. - If the server does not respond with appropriate headers, the browser blocks the request and throws a CORS error in the console.
- Simple requests (GET, POST with certain content types) are sent without a preflight, but still require server-side CORS headers to be accepted.
Quick Reference
| Item | Purpose | Notes |
|---|---|---|
| Access-Control-Allow-Origin | Defines which origins are permitted to access the resource | Must match the requesting origin or be set to * |
| Access-Control-Allow-Methods | Lists the HTTP methods allowed for cross-origin requests | Used in preflight responses |
| Access-Control-Allow-Headers | Specifies which headers are allowed in cross-origin requests | Used in preflight responses |
| Access-Control-Allow-Credentials | Indicates whether credentials (cookies, authorization headers) are allowed | Must be set to true for credentials to be included |
| Access-Control-Max-Age | Defines how long preflight results can be cached | Reduces repeated preflight requests |
Basic Example
This example demonstrates a simple CORS-enabled server that allows requests from any origin.
const express = require('express');
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
app.get('/', (req, res) => {
res.send('Hello, CORS-enabled world!');
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
The Access-Control-Allow-Origin header allows all origins to access the resource. The Access-Control-Allow-Methods and Access-Control-Allow-Headers headers define the allowed methods and headers for cross-origin requests.
Production Example
This example shows a more secure and production-ready CORS configuration that restricts access to specific origins and handles credentials properly.
const express = require('express');
const cors = require('cors');
const app = express();
const corsOptions = {
origin: ['https://example.com', 'https://admin.example.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
optionsSuccessStatus: 204
};
app.use(cors(corsOptions));
app.get('/api/data', (req, res) => {
res.json({ message: 'Secure data access' });
});
app.listen(3000, () => {
console.log('Secure server running on port 3000');
});
This version uses the cors middleware to enforce a strict origin policy, enables credentials, and sets a specific success status for preflight requests. It is more secure and maintainable than a basic wildcard configuration.
Common Mistakes
- Setting
Access-Control-Allow-Originto*for APIs that require authentication. This allows any domain to access sensitive data, increasing the risk of unauthorized access. - Forgetting to include required headers in preflight responses, causing browsers to block requests even when the server accepts them.
- Using wildcard headers like
Access-Control-Allow-Headers: *instead of specifying exact headers. This can lead to security vulnerabilities. - Not setting
Access-Control-Allow-Credentialsto true when credentials are needed, resulting in failed authentication attempts. - Not properly handling preflight requests in server-side code, leading to inconsistent behavior across browsers and environments.
Security And Production Notes
- Always validate the
Originheader on the server to prevent unauthorized domains from making requests. - Never use
*forAccess-Control-Allow-Originin production environments that handle sensitive data. - Set
Access-Control-Allow-Credentialsto true only when necessary, as it can reduce security by allowing cookies to be sent across origins. - Use
Access-Control-Max-Ageto cache preflight results and reduce redundant requests. - Ensure that all headers in
Access-Control-Allow-Headersare explicitly defined and validated to prevent header injection attacks.
Related Concepts
CORS is closely related to several other web security and networking concepts:
- Same-Origin Policy: The foundational browser security model that CORS extends and modifies for cross-origin communication.
- HTTP Headers: CORS relies heavily on specific HTTP headers to control access and request behavior.
- Pre-flight Requests: The OPTIONS request sent by browsers to determine if a cross-origin request is safe to proceed.
- Authentication: CORS works alongside authentication mechanisms to control access to protected resources.
- API Security: CORS is a key component in securing APIs against unauthorized access from external domains.