net::ERR_BLOCKED_BY_CLIENT and net::ERR_ABORTED (tested)

net::ERR_BLOCKED_BY_CLIENT means something inside the browser, almost always an ad or privacy blocker extension, cancelled the request before it left the machine. Your server never sees it. net::ERR_ABORTED means the browser itself cancelled a request, usually on purpose. We reproduced both in Chromium 153 and logged exactly what each layer reports.

1. What the two errors mean

ERR_BLOCKED_BY_CLIENT: the "client" is the browser plus its extensions. An extension rule matched the URL, and Chromium refused to send the request. There is no HTTP status, because there was no HTTP exchange.

ERR_ABORTED: the request started, and then the browser dropped it. Common reasons: a new navigation replaced it, the response was a download, the response was a 204, or your code called abort(). Most ERR_ABORTED entries are harmless.

2. Our test setup

We wrote a minimal Manifest V3 extension with two declarativeNetRequest block rules: urlFilter: "/ads.js" and urlFilter: "/analytics". We loaded it unpacked with Playwright's launchPersistentContext and --load-extension.

{"id":1,"priority":1,"action":{"type":"block"},
 "condition":{"urlFilter":"/ads.js",
   "resourceTypes":["script","xmlhttprequest","image","ping","main_frame"]}}

A note on headless: with Playwright's default headless shell, the extension did not load. /ads.js ran normally. With channel: 'chromium' (the new headless mode) the extension loaded and blocked as expected. All extension results below use that mode.

The test page loaded <script src="/ads.js"> and an <img src="/analytics/pixel.gif">, then ran fetch, XHR and sendBeacon against /analytics/....

3. Results: what each layer sees when an extension blocks a request

RequestWhat your code seesConsoleDevTools protocol (Network panel)
<script src="/ads.js">onerror fires (event type error). Script does not run.Failed to load resource: net::ERR_BLOCKED_BY_CLIENTScript, errorText net::ERR_BLOCKED_BY_CLIENT, blockedReason "other"
<img src="/analytics/pixel.gif">onerror firessame messageImage, ERR_BLOCKED_BY_CLIENT
fetch('/analytics/collect')TypeError: Failed to fetchsame messageFetch, ERR_BLOCKED_BY_CLIENT
XHR GET /analytics/xonerror, status 0, readyState 4same messageXHR, ERR_BLOCKED_BY_CLIENT
navigator.sendBeacon('/analytics/b')Returned true, even though it was blockedsame messagePing, ERR_BLOCKED_BY_CLIENT
Top-level navigation to /analytics/pageError page: "127.0.0.1 is blocked. This page has been blocked by an extension. Try disabling your extensions. ERR_BLOCKED_BY_CLIENT"-Document, ERR_BLOCKED_BY_CLIENT; Playwright page.goto: net::ERR_BLOCKED_BY_CLIENT

Our server log had zero hits for /ads.js or /analytics during this run. The block happens before any network traffic. Server logs, curl and uptime checks will all look fine.

The fetch error is the same generic TypeError: Failed to fetch you get for CORS failures and refused connections. JavaScript cannot tell them apart. See TypeError: Failed to fetch for the full list.

Also note sendBeacon: it returning true only means the beacon was queued. It does not mean it was delivered.

4. Testing without an extension

Playwright can fake the same error with route.abort('blockedbyclient'). In our run, script and image onerror fired and fetch threw TypeError: Failed to fetch, just like the real extension. One visible difference: the console said net::ERR_BLOCKED_BY_CLIENT.Inspector. That suffix marks a block made by DevTools, not by an extension.

await page.route('**/ads.js', r => r.abort('blockedbyclient'));

5. Which URLs get blocked (from the docs, not measured)

Real blockers use filter lists such as EasyList and EasyPrivacy. Per the EasyList and uBlock Origin docs, they match on URL substrings and domains, not on what the file does. Patterns that often match:

So an innocent file named /static/ads.js or an API route /api/analytics/ can break your own site for blocker users.

6. How to fix ERR_BLOCKED_BY_CLIENT

7. net::ERR_ABORTED: five cases we measured

Same Chromium 153, no extension. A /slow route answered after 3 s.

CaseWhat happenedNetwork / PlaywrightConsole
Navigation interrupted by another navigation (location.href set again after 300 ms, or a second page.goto)New page loads; first request cancelledDocument, net::ERR_ABORTED, canceled=true; first page.goto rejects with net::ERR_ABORTED at .../slowNothing
Navigating to a response with Content-Disposition: attachmentResponse 200 arrived, then became a download; page stayed on old URLDocument 200, then net::ERR_ABORTED; page.goto throws "Download is starting"Nothing
Navigating to a 204 No ContentResponse 204 arrived; page stayed on old URLDocument 204, then net::ERR_ABORTED; page.goto throws net::ERR_ABORTEDNothing
fetch + AbortController.abort() at 300 msAbortError: signal is aborted without reasonFetch, net::ERR_ABORTED, canceled=trueNothing
XMLHttpRequest.abort() at 300 msonabort fires, status 0XHR, net::ERR_ABORTED, canceled=trueNothing

Two more fetch variants: AbortSignal.timeout(300) threw TimeoutError: signal timed out. abort('user left') rejected with the plain string "user left", not an Error object. Check signal.aborted rather than err.name if you pass a custom reason.

Unlike ERR_BLOCKED_BY_CLIENT, none of the ERR_ABORTED cases wrote a console error. You mostly see them in the Network panel, in test runners like Playwright, and in error monitoring tools.

On the server side, an aborted request did arrive, and the client just left early. nginx logs that as 499 Client Closed Request.

8. How to fix ERR_ABORTED

For CORS messages that also end in "Failed to fetch", see CORS error messages explained.

Frequently asked questions

Does ERR_BLOCKED_BY_CLIENT mean my server is down?

No. The request never left the browser. In our test the server logged zero hits for the blocked URLs, and the same URLs returned 200 with curl. An extension or browser policy blocked it.

Can JavaScript detect that a request was blocked by an extension?

Not exactly. fetch throws the generic TypeError: Failed to fetch, XHR gets status 0, and script or img onerror fires. These look the same as network or CORS errors. Only DevTools shows ERR_BLOCKED_BY_CLIENT.

Why is my own /api/analytics endpoint blocked?

Filter lists match URL substrings like /analytics, /ads/ and pixel (per the EasyList docs). Our test rule urlFilter /analytics blocked fetch, XHR, img, sendBeacon and navigation. Rename the route to something neutral.

Is net::ERR_ABORTED an error I need to fix?

Usually not. In our tests it came from a second navigation, a download, a 204 response, or an explicit abort(). None of them wrote a console error. Fix it only if a request you needed is being cancelled.

Why does Playwright page.goto throw net::ERR_ABORTED on a 204?

A 204 has no content to show, so Chromium cancels the navigation and stays on the old page. We measured Document 204 followed by net::ERR_ABORTED. Use page.request or fetch for that endpoint instead.

Written with AI assistance. Measured on 2026-10-02 with Chromium 153.0.8010.12 driven by Playwright 1.63 (new headless mode via channel 'chromium'), a test Manifest V3 extension with declarativeNetRequest block rules, and a Node.js 24.21.0 server. Which URLs real blocklists match is from the EasyList and uBlock Origin docs, not measured. PlainHeaders is our extension; Chromium, Playwright and Node.js are free.