liminfo

CORS Guide & Debugger

Free reference guide: CORS Guide & Debugger

15 results

About CORS Guide & Debugger

The CORS Reference is a searchable guide covering the complete Cross-Origin Resource Sharing specification that every web developer encounters when building frontend-backend applications. The Headers section documents all six CORS response headers: Access-Control-Allow-Origin for specifying allowed origins (exact domain or wildcard *), Access-Control-Allow-Methods for permitted HTTP verbs, Access-Control-Allow-Headers for custom request headers like Authorization and Content-Type, Access-Control-Allow-Credentials for enabling cookie and auth header transmission, Access-Control-Expose-Headers for making custom response headers visible to JavaScript, and Access-Control-Max-Age for caching preflight results.

The Request Types section explains the critical difference between simple requests and preflight requests. Simple requests (GET, HEAD, POST with safe content types like application/x-www-form-urlencoded) are sent directly without a preflight. Any request that uses PUT/DELETE/PATCH, sends custom headers like Authorization, or uses Content-Type: application/json triggers a preflight — an OPTIONS request sent by the browser to check whether the server permits the actual request. The Server Config section provides ready-to-use CORS configuration code for the four most common server environments: Express (cors npm package with origin and credentials options), Django (django-cors-headers with CORS_ALLOWED_ORIGINS), Spring Boot (@CrossOrigin annotation or WebMvcConfigurer), and Nginx (add_header directives with OPTIONS handling).

The Troubleshooting section addresses the three most common CORS failures developers encounter. Origin Mismatch occurs when the server returns no Access-Control-Allow-Origin header or the value does not match the request's Origin header — common causes include misconfigured server middleware or a missing CORS policy on a new route. Credentials Errors occur when Access-Control-Allow-Credentials: true is set alongside Access-Control-Allow-Origin: *, which the browser always rejects; the fix is to specify the exact origin. Preflight Failures occur when the server does not handle OPTIONS requests, causing the browser to block the actual request. This reference is essential for frontend developers, API designers, and DevOps engineers configuring web application firewalls or reverse proxies.

Key Features

  • All 6 CORS response headers with correct syntax and valid value examples
  • Access-Control-Allow-Credentials behavior and the wildcard origin restriction
  • Simple request conditions (safe methods, safe content types, no custom headers)
  • Preflight OPTIONS request structure with Access-Control-Request-Method and -Headers
  • Express cors() middleware configuration with origin callback and credentials
  • Django django-cors-headers CORS_ALLOWED_ORIGINS and CORS_ALLOW_CREDENTIALS settings
  • Spring Boot @CrossOrigin annotation and WebMvcConfigurer.addCorsMappings()
  • Nginx add_header CORS directives with OPTIONS method 204 handling

Frequently Asked Questions

Why does the browser block CORS requests but Postman does not?

CORS is a browser security policy, not a server or network restriction. Postman is not a browser and does not enforce the Same-Origin Policy, so it can make cross-origin requests without restriction. The browser automatically includes the Origin header and enforces the CORS handshake for cross-origin requests from JavaScript. This is why CORS errors only appear in browser DevTools and not in API testing tools.

Why can I not use Access-Control-Allow-Origin: * with credentials?

The CORS specification explicitly forbids using a wildcard origin (*) when Access-Control-Allow-Credentials: true is set. This is a deliberate security decision: a wildcard would allow any website to send authenticated requests (with cookies or auth headers) to your API on behalf of any logged-in user. Instead, you must specify the exact origin, and your server must dynamically reflect the request's Origin header after validating it against an allowlist.

What triggers a CORS preflight request?

A preflight OPTIONS request is triggered when any of these conditions are met: (1) the method is PUT, DELETE, PATCH, or CONNECT; (2) the request includes custom headers beyond Accept, Accept-Language, Content-Language, or Content-Type; (3) the Content-Type is anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain. Most API calls that send JSON (Content-Type: application/json) or include Authorization headers will trigger a preflight.

How do I debug a CORS error in the browser?

Open the browser DevTools Network tab and look for the failing request. If you see a red request with status "CORS error" or "(blocked:other)", click it and check the Response Headers tab — the absence of Access-Control-Allow-Origin is the most common cause. For preflight failures, look for an OPTIONS request just before the actual request and check its response. The browser Console will also show a descriptive error message naming which header is missing or has an incorrect value.

How does Access-Control-Max-Age reduce preflight requests?

Access-Control-Max-Age specifies the number of seconds the browser can cache the result of a preflight request. During this time, repeated requests to the same endpoint with the same method and headers will not trigger a new preflight. Setting it to 86400 (24 hours) significantly reduces network overhead for SPAs that make frequent API calls. The maximum value is browser-dependent — Chrome caps it at 7200 seconds, Firefox at 86400.

How do I configure CORS in Nginx without a backend framework?

In Nginx, add CORS headers inside the server or location block. Use add_header Access-Control-Allow-Origin $http_origin to reflect the request origin dynamically. Add an if ($request_method = OPTIONS) block that returns 204 immediately after setting the preflight response headers. The $http_origin variable lets you validate the origin against a list using an Nginx map block, preventing open CORS policies.

What is the difference between Access-Control-Allow-Headers and Access-Control-Expose-Headers?

Access-Control-Allow-Headers is sent in the preflight response and tells the browser which request headers the client is allowed to include in the actual request (e.g., Authorization, Content-Type). Access-Control-Expose-Headers is sent in the actual response and tells the browser which response headers JavaScript is allowed to read via the XMLHttpRequest or Fetch API. By default, only a small set of "safe-listed" response headers (like Content-Type) are visible to JavaScript.

How do I allow multiple specific origins in CORS without using a wildcard?

CORS only allows a single origin value in Access-Control-Allow-Origin per response. To support multiple origins, the server must dynamically check the incoming request's Origin header against an allowlist and reflect the exact origin back if it matches. In Express: set the cors origin option to a function that calls callback(null, allowlist.includes(origin)). In Django: CORS_ALLOWED_ORIGINS is a list and django-cors-headers handles the reflection automatically.