Fixing “CORS request did not succeed” in Firefox
You call fetch() against another origin, and Firefox’s console prints:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the
remote resource at https://api.example.com/v1/data.
(Reason: CORS request did not succeed). Status code: (null).
The word “CORS” in the message misleads thousands of developers into editing Access-Control-Allow-Origin headers for hours. That is the wrong layer. This exact Firefox string — specifically the Status code: (null) clause — means no HTTP response ever reached the browser. There were no headers to check because there was no response.
This page is part of Decoding Browser CORS Error Messages, which maps each browser’s console strings to their true root cause; here we resolve this one Firefox message end to end.
Root Cause
The WHATWG Fetch Standard runs its CORS check (§4.9) only after a response is obtained. When the underlying fetch fails to obtain any response — the TLS handshake aborts, the connection is refused or times out, the request is blocked as mixed content, or the server never answers the preflight OPTIONS — the algorithm returns a network error before the CORS check runs. Firefox surfaces that pre-response network error with the generic reason CORS request did not succeed and Status code: (null), because a status code only exists once an HTTP response line has been received. This is categorically different from CORS header 'Access-Control-Allow-Origin' missing, which always carries a real numeric status because a response did arrive.
Prerequisite State
Before applying the fix, confirm:
- The console message literally contains
(Reason: CORS request did not succeed)andStatus code: (null). If it shows any numeric status, this is not your page — see resolving “No ‘Access-Control-Allow-Origin’” in Chrome instead. - You have shell access to run curl from the same network the browser is on.
- You know whether the request is “simple” or triggers a preflight — see simple vs preflight requests.
The Four Transport Faults Behind This Message
Step-by-Step Fix
Step 1 — Confirm it really is a “no response” failure
Open the Firefox Web Console (F12) and read the full line. The signature is (Reason: CORS request did not succeed). Status code: (null). The (null) is the proof: no status line was received.
Step 2 — Test raw connectivity and TLS with curl
Run a verbose curl from the same machine and network:
curl -v https://api.example.com/v1/data
Watch the TLS handshake lines. If curl reports SSL certificate problem: unable to get local issuer certificate or certificate has expired, the browser is rejecting the certificate too — that is your fault. If curl completes only when you add -k, the certificate is untrusted and Firefox is correctly refusing it.
Step 3 — Fix the TLS chain
Serve the full certificate chain (leaf plus intermediates), not just the leaf. In Nginx:
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/ssl/certs/fullchain.pem; # leaf + intermediates
ssl_certificate_key /etc/ssl/private/privkey.pem;
}
A leaf-only ssl_certificate passes in curl (which may already trust the intermediate) but fails in Firefox, which requires the server to supply the chain.
Step 4 — Rule out mixed content
If the page is served over HTTPS, the request URL must also be HTTPS. Firefox blocks an http:// subresource request from an https:// document before it leaves the browser. Correct the URL:
// Blocked as mixed content on an HTTPS page:
fetch('http://api.example.com/v1/data');
// Correct:
fetch('https://api.example.com/v1/data');
Step 5 — Confirm the server answers OPTIONS
If the request is non-simple (custom headers, PUT/DELETE, or a JSON Content-Type), Firefox sends a preflight first. If the server drops or 5xx-es that OPTIONS, no response returns and you get this exact error. Verify:
curl -v -X OPTIONS https://api.example.com/v1/data \
-H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: PUT"
The server must answer with a 2xx status line. If curl hangs or the connection drops, add an OPTIONS handler — see OPTIONS endpoint design.
Verification
Re-run the request in Firefox with the Network panel open. A fixed transport produces a request row with a real status code (e.g. 200, 204, or even 403) instead of a red “blocked” row. At that point, if a CORS header problem remains, the message changes to name a header — which is progress, and a different fix.
curl one-liner to confirm a real response line now arrives:
curl -sS -o /dev/null -w "%{http_code}\n" https://api.example.com/v1/data
A numeric code (not 000) means the transport is healthy. curl’s 000 is the analogue of Firefox’s (null).
DevTools check:
Security Boundary Note
Do not “fix” a certificate error by having users add a security exception or by disabling certificate validation in the client. The CORS request did not succeed message for a TLS fault is the browser enforcing transport integrity — bypassing it exposes users to interception. Likewise, never work around a mixed-content block by downgrading the page to HTTP; serve the API over HTTPS instead. The correct remediation is always to make the transport genuinely valid, never to weaken the client’s trust checks.
Common Mistakes
| Mistake | Technical impact | Fix |
|---|---|---|
Editing Access-Control-Allow-Origin to fix Status code: (null) |
Hours lost; the header layer never runs because no response arrives | Treat (null) as a transport fault; fix TLS/mixed-content/OPTIONS first |
| Shipping a leaf-only certificate | Passes in curl, fails in Firefox with this exact error | Serve fullchain.pem (leaf + intermediates) |
Requesting http:// from an https:// page |
Firefox blocks as mixed content before sending | Use an https:// request URL |
Server drops or 5xx-es OPTIONS |
Preflight never returns; browser reports the failure against the real URL | Add an OPTIONS handler returning 204 with CORS headers |
FAQ
Why does Firefox say “Status code: (null)” instead of a real number?
Because no HTTP response line was ever received. A status code exists only once the server sends an HTTP response. When the TLS handshake fails, the connection is refused, or the request is blocked as mixed content, Firefox never gets a status line, so it reports (null). This distinguishes the failure from a header mismatch, which always has a real status code.
Does adding Access-Control-Allow-Origin fix “CORS request did not succeed”?
No. Response headers only matter once a response arrives. This error means no usable response arrived at all, so no header change on the server will resolve it. Fix the transport cause first — TLS certificate, mixed content, connection reachability, or a missing OPTIONS answer — then the CORS header check can even run.
Why does the same request work in curl but fail in Firefox with this error?
curl by default trusts a wider or differently configured CA set and does not enforce the browser’s mixed-content rule. A self-signed or untrusted certificate, or an HTTP subresource on an HTTPS page, will fail in Firefox but pass in curl. Add -v to curl and check whether you had to pass -k to bypass certificate validation — if so, the browser is correctly rejecting the same certificate.
Related
- Decoding Browser CORS Error Messages — parent: decode any browser’s CORS console string
- Resolving “No ‘Access-Control-Allow-Origin’” in Chrome — the header-mismatch counterpart with a real status code
- OPTIONS Endpoint Design — make the server answer preflight requests reliably