GuidesFIREFOX
Fix Reason: CORS request did not succeed in Firefox
Firefox logs Cross-Origin Request Blocked with Reason: CORS request did not succeed and Status code: (null) when a cross-origin request failed before any response arrived, and fetch() rejects with TypeError: NetworkError when attempting to fetch resource. The cause is almost never a missing CORS header: it is a blocked, refused or broken connection. This page lists the 6 causes we see most, with a 2-minute check for each, and the one case where putting https://proxy.cors.dev/ in front of a public API URL (free, no signup, GET and HEAD, 1 MiB responses) is the right fix.
What the message means
Firefox prefixes every cross-origin failure with the same Cross-Origin Request Blocked sentence and puts the real diagnosis in the Reason: part. CORS request did not succeed is the reason for a request that never produced an HTTP response in the browser: the connection was blocked, refused, reset or failed its TLS handshake. That is why the status code is (null). Header problems look different: they carry a real status code and name the header.
# Console
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource
at https://api.example.com/data. (Reason: CORS request did not succeed). Status code: (null).
# What your code catches
TypeError: NetworkError when attempting to fetch resource.
# Compare: a real CORS header problem names the header and carries a status code
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). Status code: 200.| Reason in the console | Status code shown | What it means |
|---|---|---|
| CORS request did not succeed | (null) | The connection failed: nothing came back to check. This page. |
| CORS header 'Access-Control-Allow-Origin' missing | 200 or another real code | The server answered without the header. |
| CORS preflight channel did not succeed | (null) | The OPTIONS request itself failed at the network level. |
| CORS request external redirect not allowed | 3xx | A preflighted request was redirected to another origin. |
| CORS request not HTTP | none | The page is a file: URL or the target is not http(s). |
The 6 causes, in the order to check them
- A privacy extension or ad blocker
uBlock Origin, Privacy Badger and similar tools cancel requests to hosts on their lists, and Firefox reports the cancelled request as a CORS failure. Check: open the page in a private window with extensions disabled, or in Troubleshoot Mode. The Network tab shows the request as Blocked with the extension name in the details.
- Enhanced Tracking Protection
Firefox blocks known tracking domains itself in Strict mode and on some sites in Standard mode, which hits analytics and ad-tech APIs and the occasional CDN. Check: click the shield icon in the address bar and turn protection off for the site once. If the request succeeds, the host is on the tracking list.
- A certificate Firefox does not trust
Self-signed, expired or wrong-host certificates break fetch() silently: Firefox shows the warning page only for top-level navigations, never for a background request. Check: open the API URL in a new tab. If you see a certificate warning, fix the certificate on the server, or for local development, accept it in that tab once and reload your app.
- Mixed content
A page served over https:// may not call an http:// API; the browser blocks the request outright. Check: look at the scheme in the error. Fix: serve the API over HTTPS. No proxy helps here, including this one, which accepts HTTPS targets only.
- The server is unreachable from the browser
Wrong port, DNS name that only resolves inside your network, a firewall, a VPN that is down, or a local server that is not running. Check: curl -v the URL from the same machine and read the first lines. For localhost APIs, also compare the port in the error with the port the server prints at startup.
- The server drops the connection on the request
Some servers close the connection on an OPTIONS preflight they do not implement, crash on the request, or reset HTTP/2 streams; nothing comes back, so Firefox cannot even report a status. Check: curl -i -X OPTIONS with an Origin header and watch for an empty reply. Fix your own server by answering OPTIONS with 204; for a public API you do not control, read the next section.
# 1. Can anything reach it? Look for DNS, connection refused, timeout, or a certificate error
curl -v https://api.example.com/data -o /dev/null
# 2. Does the server survive a preflight? A dropped connection here shows up as "did not succeed"
curl -i -X OPTIONS https://api.example.com/data \
-H 'Origin: https://www.yoursite.com' \
-H 'Access-Control-Request-Method: GET'
# 3. Does the real request answer, and with which CORS headers?
curl -i https://api.example.com/data -H 'Origin: https://www.yoursite.com'When a proxy is the fix
For a public API that is up but hostile to browsers, dropping preflights, resetting connections on cross-origin requests, or sitting on a blocklist your visitors use, routing the GET through a CORS proxy removes the browser from the equation: the browser talks to proxy.cors.dev only, the proxy answers the OPTIONS preflight itself with a 600 second Access-Control-Max-Age, fetches the API from its own servers with a 10 second deadline and 4 redirect hops at most, and relays the response with Access-Control-Allow-Origin for your origin.
// The browser now talks to proxy.cors.dev only: the proxy answers the OPTIONS preflight itself
// and fetches the API from its servers, so a flaky or preflight-hostile public API stops failing.
const feed = 'https://feeds.bbci.co.uk/news/technology/rss.xml';
const response = await fetch('https://proxy.cors.dev/' + feed, { credentials: 'omit' });
if (!response.ok) {
// upstream_unreachable or upstream_timeout: the API really is down or slow
throw new Error(response.headers.get('X-Cors-Error') ?? `HTTP ${response.status}`);
}
const xml = await response.text();It does not help for causes 3, 4 and 5 when the server is yours: a bad certificate, an http:// endpoint or a server that is down stays broken, and the proxy reports it as upstream_unreachable with a 502. Private hosts, localhost and IP literals are refused with target_not_allowed, so local development problems need the fixes above, not a proxy.
Limits and pricing
| Limit | Free, no key | Pro, $5 per month |
|---|---|---|
| Price | $0 | $5 per month; 7-day trial with 1,000 requests, no card |
| Methods | GET and HEAD | GET, HEAD, POST, PUT, PATCH and DELETE |
| Destinations | Any public HTTPS host | Public HTTPS hosts enabled on your Connection |
| Response size | 1 MiB, text types only | 6 MiB, any content type |
| Upstream deadline | 10 seconds | 10 seconds |
| Preflight | Answered by the proxy, cached 600 seconds | Answered by the proxy, cached 600 seconds |
| Rate | Shared pool with fair-use limits | 600 requests per minute, 10 concurrent per account |
| Monthly requests | No quota | 500,000 per billing period, $5 per extra 500,000 |
| Request headers forwarded | Accept, If-None-Match, If-Modified-Since | Plus Authorization and custom headers |
| Redirects | Followed, up to 4 hops | Followed when every hop host is enabled |
Good questions.
Does CORS request did not succeed mean my CORS headers are wrong?
No. Firefox never received a response to check, so it cannot say anything about headers. Fix the connection first; if a header problem remains, the reason changes to one that names the header and shows a status code.
Why does the same request work in Chrome?
Different extension sets, different tracking protection, and different certificate handling. Chrome reports the same failures as net::ERR_FAILED, net::ERR_CERT_AUTHORITY_INVALID or a plain Failed to fetch, so the request is usually failing there too, with a less specific message.
Why does it work in a private window?
Private windows start without most extensions and with their own Enhanced Tracking Protection state. If the request succeeds there, cause 1 or 2 is confirmed; the fix is on the visitor side or in choosing a host that is not on a blocklist.
Why does curl work when Firefox does not?
curl runs no extensions, applies no tracking protection and, with -k, skips certificate validation. A clean curl -v with a certificate error or a connection reset tells you more than a success with -k.
Can the proxy fix a mixed content error?
No. The proxy itself is HTTPS, but it only fetches HTTPS targets, so an API that is only available over http:// stays out of reach. Put TLS in front of the API or move it behind a host that has it.
What does Status code: (null) tell me?
That no HTTP status exists for this request: the failure happened at the DNS, TCP, TLS or extension level, before a single header arrived. A real code in that position means the connection worked and the problem is in the response.