CORS Error

Browser Security - Cross-origin request blocked

CORS Errors Explained

What is CORS?

CORS (Cross-Origin Resource Sharing) is a browser security feature that restricts web pages from making requests to a different domain than the one serving the page. When blocked, you'll see an error like:

Access to fetch at 'https://api.example.com/data' from origin
'https://myapp.com' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present.

Why Does This Happen?

Same-Origin Policy

Browsers block requests where origin (protocol + domain + port) differs between the page and the API. This prevents malicious sites from stealing data.

  • https://app.comhttps://api.com Blocked
  • http://app.comhttps://app.com Blocked (different protocol)
  • https://app.com:3000https://app.com:8080 Blocked (different port)

Common CORS Errors

Missing Access-Control-Allow-Origin

Server doesn't include the required CORS header in response.

Preflight Request Failed

OPTIONS request returned an error or wrong headers.

Credentials Not Supported

Trying to send cookies but server doesn't allow credentials.

Server-Side Fixes

Express.js

const cors = require('cors');

// Allow all origins (development only!)
app.use(cors());

// Production: specific origins
app.use(cors({
  origin: ['https://myapp.com', 'https://www.myapp.com'],
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE']
}));

Nginx

location /api/ {
    add_header 'Access-Control-Allow-Origin' 'https://myapp.com';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';

    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Max-Age' 86400;
        return 204;
    }
}

Django

# settings.py
INSTALLED_APPS = [..., 'corsheaders']
MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware', ...]

CORS_ALLOWED_ORIGINS = [
    'https://myapp.com',
]
CORS_ALLOW_CREDENTIALS = True

Required Headers

Header Purpose
Access-Control-Allow-Origin Which origins can access
Access-Control-Allow-Methods Allowed HTTP methods
Access-Control-Allow-Headers Allowed request headers
Access-Control-Allow-Credentials Allow cookies/auth headers

Preflight Requests

For non-simple requests (custom headers, PUT/DELETE methods), browsers send an OPTIONS request first:

# Browser sends preflight
OPTIONS /api/users HTTP/1.1
Origin: https://myapp.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization

# Server must respond with:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization

Common Mistakes

  • Using * with credentials: Can't use wildcard origin with cookies
  • Missing OPTIONS handler: Preflight returns 404 or 405
  • Headers not exposed: Custom response headers need Access-Control-Expose-Headers
  • Caching issues: Browser cached old CORS response

Debugging Tips

  • Check the Network tab for the actual response headers
  • Look for the preflight OPTIONS request
  • Test with curl (bypasses CORS): curl -I https://api.example.com
  • Server-side errors may also cause CORS to fail (fix the 500 first)

Monitor your API endpoints

UptimeSignal monitors your APIs from the server side, bypassing CORS restrictions.

Start monitoring free →

Related Topics