A CORS error means the browser blocked a cross-origin request because the server's response didn't include permission for it - the fix is telling the server to grant that permission correctly, not disabling the browser's enforcement of it. Disabling CORS checks in the browser (a flag, a extension) "fixes" the error on your machine while leaving every real user's browser still blocking the request in production - it isn't a fix, it's turning off the error message.
First: Confirm What the Error Actually Says
Open the browser console - the exact message tells you which of a few distinct problems you have:
No 'Access-Control-Allow-Origin' header is present- the server isn't sending CORS headers at allThe 'Access-Control-Allow-Origin' header contains multiple values- a duplicate header, often from both your app and a proxy/CDN setting it...has been blocked by CORS policy: Response to preflight request doesn't pass- theOPTIONSpreflight request itself is failing...credentials mode is 'include'combined with a wildcard origin - browsers reject this specific combination outright, covered separately below
Missing Header Entirely
The most common case: the server never sends Access-Control-Allow-Origin because CORS wasn't configured at all, not because it was misconfigured.
# Express (Node.js)
const cors = require('cors');
app.use(cors({ origin: 'https://yourapp.com' }));
# Django
# settings.py
INSTALLED_APPS += ['corsheaders']
MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware', ...] + MIDDLEWARE
CORS_ALLOWED_ORIGINS = ['https://yourapp.com']
# Laravel
# config/cors.php
'allowed_origins' => ['https://yourapp.com'],
# Nginx (reverse proxy in front of an API with no CORS logic of its own)
add_header 'Access-Control-Allow-Origin' 'https://yourapp.com' always;
The Preflight (OPTIONS) Request Is Failing
Browsers send an automatic OPTIONS request before certain cross-origin requests (anything beyond a simple GET, or with custom headers like Authorization) to ask permission first. If your server only handles CORS logic on the actual GET/POST route and never answers OPTIONS, the preflight itself gets a 404 or 405, and the browser blocks the real request without ever sending it.
# Express: explicitly handle OPTIONS, or let the cors middleware do it globally
app.options('*', cors()); // must exist for preflighted requests
# Laravel: the framework's cors middleware handles OPTIONS automatically
// once config/cors.php lists the right paths in 'paths' (e.g. 'api/*')
Wildcard Origin Plus Credentials - a Combination Browsers Reject Outright
Access-Control-Allow-Origin: * together with a request sent using credentials: 'include' (cookies, HTTP auth) is rejected by the browser regardless of server configuration - this isn't a bug to work around, it's a deliberate security boundary. The fix is listing the specific origin instead of a wildcard whenever credentials are involved.
// Vulnerable/broken combination - browser rejects this for credentialed requests
'Access-Control-Allow-Origin': '*'
'Access-Control-Allow-Credentials': 'true'
// Correct: an explicit origin, never a wildcard, when credentials are used
'Access-Control-Allow-Origin': 'https://yourapp.com'
'Access-Control-Allow-Credentials': 'true'
Duplicate Headers From a CDN or Proxy
If both your application and a CDN/reverse proxy (Cloudflare, an API gateway, an Nginx layer) add CORS headers independently, the response ends up with two Access-Control-Allow-Origin values, which browsers reject as invalid. Set CORS at exactly one layer, and remove it from wherever else it was accidentally duplicated.
What Not to Do
Setting Access-Control-Allow-Origin: * everywhere because it makes the error go away is the actual security risk this whole mechanism exists to prevent - it means any website on the internet can make authenticated-looking requests to your API from a visitor's browser. Scope the allowed origin(s) to exactly the domains that should be making cross-origin requests, and nothing broader.
Confirming the Fix Actually Worked
Test with a real cross-origin request, not just by reading the config - a header set correctly in code can still fail to reach the actual response if a proxy strips it, or if the route path doesn't match what the CORS config expects. Shieldome checks CORS configuration as part of every scan, flagging exactly which origins and methods are actually permitted on the live site.