CORS errors are one of the most common browser debugging headaches. Here's how Firefox handles CORS, how to debug it, and how to avoid common pitfalls.
What CORS Is (Quick Review)
CORS (Cross-Origin Resource Sharing) is a browser security mechanism that blocks JavaScript from reading responses from different origins by default.
Origin = protocol + hostname + port. https://api.example.com and https://app.example.com are different origins.
When your JavaScript at app.example.com makes a fetch to api.example.com, the browser enforces CORS. The server at api.example.com must explicitly allow this by returning the right headers.
The Firefox CORS Error Message
In the DevTools Console, Firefox shows:
Cross-Origin Request Blocked: The Same Origin Policy disallows
reading the remote resource at https://api.example.com/data.
(Reason: CORS header 'Access-Control-Allow-Origin' missing).
This message is from Firefox, not the server. The request was made, the server responded, but Firefox blocked JavaScript from reading the response.
Important: The request usually succeeds at the network level — Firefox blocks the JavaScript from reading the response, not the request itself.
Debugging CORS in Firefox DevTools
Network Tab
- Open DevTools (
F12) → Network tab - Find the failing request
- Click it → look at the Response Headers
For a CORS request to succeed, you need to see:
Access-Control-Allow-Origin: https://app.example.com
(or * for public APIs)
If this header is missing: the server isn't configured for CORS.
The Preflight Request
For "complex" requests (POST with JSON, custom headers, PUT, DELETE), browsers send a preflight OPTIONS request first. Check for:
- An OPTIONS request to the same URL
- It returns 200 or 204
- Response has:
Access-Control-Allow-Methods: GET, POST, ...andAccess-Control-Allow-Headers: Content-Type, ...
If the preflight fails or returns wrong headers, the actual request won't be made.
Firefox-Specific CORS Errors
Firefox error messages are more descriptive than Chrome's. Examples:
"Reason: header 'access-control-allow-origin' does not match 'null'"
— Your request included credentials (cookies) but Access-Control-Allow-Origin: * was returned. With credentials, the origin must be specific, not *. Also: Access-Control-Allow-Credentials: true must be set.
"Reason: CORS preflight response did not succeed"
— The OPTIONS preflight got a non-2xx response or wrong CORS headers.
"Reason: Did not find method in CORS header 'Access-Control-Allow-Methods'"
— The method (e.g., PATCH) is missing from the allowed methods list.
"Reason: CORS request not HTTP"
— You're making a cross-origin request to file:// or an insecure origin. CORS doesn't work with file://.
Common CORS Gotchas
Credentials + Wildcard Origin
This never works:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
When credentials are involved (credentials: 'include'), the origin must be specific. Fix:
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Vary Header
When your server dynamically sets Access-Control-Allow-Origin based on the request's Origin header (to support multiple origins), you must include:
Vary: Origin
Without this, CDNs and proxies may cache the response with one Allow-Origin value and serve it to requests from a different origin.
Local Development (localhost)
localhost and localhost:3000 are different origins. If your API is on port 8080 and your frontend is on port 3000:
# Server must allow:
Access-Control-Allow-Origin: http://localhost:3000
Testing Without CORS (Temporarily)
For local development, you might want to disable CORS checking:
Option 1: Firefox extension — Extensions like "CORS Everywhere" disable CORS in Firefox for development. Don't use this in production or for real browsing.
Option 2: about:config — There's no stable flag to disable CORS entirely in Firefox for regular use.
Option 3: Proxy — Run a development proxy that adds CORS headers. Tools like local-cors-proxy (npm) can wrap any API with CORS headers for development.
Option 4: Same-origin proxy — In your development webpack/vite config, proxy /api requests to your backend. The browser sees requests to the same origin.
CORS and Fetch vs XHR
Fetch API and XMLHttpRequest both follow CORS. The key difference: Fetch is mode-explicit:
// With CORS handling
fetch('https://api.example.com/data', {
mode: 'cors', // Default — browser enforces CORS
credentials: 'include' // Send cookies cross-origin
});
// No-CORS mode (can't read the response)
fetch('https://api.example.com/ping', {
mode: 'no-cors' // Request goes through but response is opaque
});
Firefox vs Chrome CORS Error Messages
Firefox provides much more detailed CORS error messages than Chrome. When debugging CORS issues, Firefox's console message tells you exactly which header is wrong or missing. Chrome often just says "CORS error."
For CORS debugging: use Firefox.
The key insight for CORS debugging: the request usually succeeds at the network level. Firefox blocks the JavaScript from reading it. Check the Response Headers on the OPTIONS preflight and the actual request — the specific CORS error message tells you exactly what's missing.
Top comments (0)