What is CORS?
CORS stands for Cross-Origin Resource Sharing. It is a security mechanism implemented by web browsers to prevent malicious websites from accessing resources and data from another domain without permission.
Understanding the Same-Origin Policy
To understand CORS, first you need to understand the Same-Origin Policy (SOP). This policy restricts how documents or scripts loaded from one origin can interact with resources from another origin.
An origin is defined by:
- Protocol (http or https)
- Domain (example.com)
- Port (80, 443, etc.)
Example:
- Request from
http://example.com
tohttp://api.example.com
is a cross-origin request, even though the domains look similar.
The Same-Origin Policy prevents this request unless the server at api.example.com
explicitly allows it using CORS headers.
Why CORS Exists
The purpose of CORS is to protect users from potential cross-site request forgery (CSRF) and data leakage attacks. For instance, without CORS, any website could make requests to your bank’s API using your browser credentials and steal sensitive information.
By enforcing CORS, browsers ensure that only trusted sources can communicate with external servers, based on server-configured rules.
How the Error Happens
When your front-end JavaScript code tries to send an HTTP request to a different origin (for example, from http://localhost:3000
to https://api.example.com
), the browser sends a preflight request (an OPTIONS
request) to ask the server: “Is it okay if I make this request?”
If the server does not respond with appropriate CORS headers, the browser blocks the actual request and shows a CORS error in the developer console, like:
Access to XMLHttpRequest at 'https://api.example.com/data' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Key CORS Headers
To allow CORS, the server needs to include specific headers in its HTTP response:
Access-Control-Allow-Origin
: Specifies which origins are allowed (e.g.,*
,http://localhost:3000
).Access-Control-Allow-Methods
: Lists HTTP methods allowed (e.g.,GET
,POST
,PUT
).Access-Control-Allow-Headers
: Lists allowed headers (e.g.,Content-Type
,Authorization
).Access-Control-Allow-Credentials
: Whether cookies and credentials are allowed.
Common Use Cases That Trigger CORS
- JavaScript apps making API calls to a different domain
- Frontend apps running on localhost trying to communicate with a remote server
- Mobile or desktop apps using web views
- Using
fetch
oraxios
in a React, Angular, or Vue app to connect to a different server
Step-by-Step: Fixing CORS Error
Step 1: Identify the Error
Check your browser’s console. A typical CORS error message may look like this:
Access to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000' has been blocked by CORS policy
This means the browser blocked the request due to CORS policy violation.
Step 2: Confirm the Server Origin
Ensure you’re calling a server that’s on a different origin. If your frontend is on http://localhost:3000
and your backend is on http://localhost:8000
, it’s considered a different origin.
Step 3: Update the Server to Allow CORS
You need to change the server-side code to include the correct CORS headers. This cannot be done from the frontend.
For Node.js with Express:
const cors = require('cors');
app.use(cors());
For more control:
app.use(cors({
origin: 'http://localhost:3000',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true
}));
For Python Flask:
from flask_cors import CORS
CORS(app)
For ASP.NET Core:
services.AddCors(options =>
{
options.AddPolicy("AllowMyOrigin",
builder => builder.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader());
});
app.UseCors("AllowMyOrigin");
Step 4: Handle Preflight Requests
Browsers send a preflight request (an OPTIONS
method call) before the actual request. Your server must handle this.
Example in Express:
app.options('*', cors());
Step 5: Avoid Browser Block in Development
For development purposes, you can use workarounds like:
- Using a proxy server
- For React:
"proxy": "http://localhost:5000"
inpackage.json
- For React:
- Using browser extensions like “CORS Unblock” (not recommended for production)
- Disabling CORS in browser (very unsafe, never do this for production or real users)
Step 6: Check and Restart
After adding the correct headers on the server, restart your server. Then retry your frontend code.
Advanced CORS Settings
- Allow specific origins instead of
*
for better security - Enable
Access-Control-Allow-Credentials
only when necessary - Limit allowed methods (
GET
,POST
, etc.) - Use HTTPS in production to avoid mixed content issues
Best Practices
- Always configure CORS on the server, never on the client
- Never use
Access-Control-Allow-Origin: *
with credentials - Use environment-specific configuration (different CORS settings for dev and prod)
- Log preflight and actual requests on the server to debug
Important Notes
- CORS is enforced by browsers, not servers. If you use
curl
or Postman, you won’t get blocked by CORS. - If you’re getting blocked, it’s not because of a problem in your code, but because the server is not configured to allow your request.
- CORS errors don’t reach your JavaScript
.catch()
block; they are blocked before your code gets the response.