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.

The two Firefox messages for one failure
# 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.

Firefox CORS reasons that are often confused
Reason in the consoleStatus code shownWhat it means
CORS request did not succeed(null)The connection failed: nothing came back to check. This page.
CORS header 'Access-Control-Allow-Origin' missing200 or another real codeThe 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 allowed3xxA preflighted request was redirected to another origin.
CORS request not HTTPnoneThe page is a file: URL or the target is not http(s).

The 6 causes, in the order to check them

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

Three terminal checks that find the cause
# 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.

Public API that drops preflights or connections: fetch it through a proxy
// 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

cors.dev limits when a proxy is the fix
LimitFree, no keyPro, $5 per month
Price$0$5 per month; 7-day trial with 1,000 requests, no card
MethodsGET and HEADGET, HEAD, POST, PUT, PATCH and DELETE
DestinationsAny public HTTPS hostPublic HTTPS hosts enabled on your Connection
Response size1 MiB, text types only6 MiB, any content type
Upstream deadline10 seconds10 seconds
PreflightAnswered by the proxy, cached 600 secondsAnswered by the proxy, cached 600 seconds
RateShared pool with fair-use limits600 requests per minute, 10 concurrent per account
Monthly requestsNo quota500,000 per billing period, $5 per extra 500,000
Request headers forwardedAccept, If-None-Match, If-Modified-SincePlus Authorization and custom headers
RedirectsFollowed, up to 4 hopsFollowed 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.