Quick answer: "Failed to load resource: net::ERR_BLOCKED_BY_CLIENT" means something inside the browser cancelled the request before it reached the network, almost always an ad or tracker blocker, sometimes Chrome itself, DevTools request blocking, or a Lighthouse blocked-URL pattern. The server was never contacted. Re-run Lighthouse without extensions, then make the page resilient so a blocked analytics script cannot break it.
This console message means something inside the browser cancelled the request before it left the device. No bytes reached the server, so the server did not fail and the network did not time out. The blocker is almost always an ad or tracker blocking extension. It can also be Chrome's own ad filter, a request-blocking rule in DevTools or Lighthouse, or a company URL blocklist. Lighthouse surfaces the message through the audit "Browser errors were logged to the console" (errors-in-console), and it fails that audit on its own. This page covers who blocks the request, how to get a clean lab run, and how to make the page resilient for the visitors who block it in the wild.
TL;DR
- What:
Failed to load resource: net::ERR_BLOCKED_BY_CLIENTis Chrome's error code for a request stopped by the client. Common targets: analytics beacons, Facebook pixel, Google Ads and DoubleClick, session-recording scripts, and any URL withads,trackorpixelin it. - Why it matters: One console error fails the Lighthouse audit. More important, the same block happens for every visitor with a blocker, and a page that depends on the blocked script can break for them.
- Fix: Run Lighthouse without extensions to see the real score. Then guard every call into a tracker object, load trackers after
window.load, and move the data you cannot lose to a server-side or first-party endpoint. Do not try to evade blockers.
What does "net::ERR_BLOCKED_BY_CLIENT" mean?
Chrome returns ERR_BLOCKED_BY_CLIENT when a client-side rule cancels a request. The rule can come from several places:
| Who blocked it | How to recognise it |
|---|---|
| A browser extension (uBlock Origin, AdBlock, Privacy Badger, Ghostery, and others) | The blocked URL is a known tracker, ad, or pixel. The error disappears in an incognito or guest window. This is the cause in nearly every local run. |
| Chrome's built-in ad filter | Chrome blocks ad requests on sites that fail the Better Ads Standards, with no extension installed. Rare, and the site owner sees a notice in Search Console's Ad Experience Report. |
| Brave Shields and privacy browsers | Same effect as an extension, built into the browser. |
| DevTools request blocking or a Lighthouse blocked-URL pattern | The code reads net::ERR_BLOCKED_BY_CLIENT.Inspector. The .Inspector suffix means the DevTools protocol blocked it, which is what the Network panel's "Block request URL" and the Lighthouse blockedUrlPatterns option use. |
| An enterprise URL blocklist | A managed Chrome profile blocks the URL by policy. Only your own staff see it. |
The error is not a server response. Do not look for it in server logs, because the request never arrived.
Why does Lighthouse show ERR_BLOCKED_BY_CLIENT?
Lighthouse records every console message during the page load and lists the errors under "Browser errors were logged to the console" in the Best Practices section. Where the block came from depends on how you ran the audit:
- Lighthouse in DevTools: it audits in your normal Chrome profile, so your extensions run during the audit. An ad blocker cancels the tracker, Chrome logs the error, and Lighthouse reports it. This is the common case.
- The Lighthouse CLI:
lighthouse <url>starts Chrome with a fresh profile and extensions disabled by default. An extension is not the cause unless you set up the run to load one, for example through--chrome-flags. Check for a blocked-URL pattern, an enterprise policy, or your service worker instead. - A row ending in
.Inspector: the run blocked the URL on purpose. Check the Network panel's request blocking list, and the--blocked-url-patternsflag orblockedUrlPatternsconfig in your Lighthouse setup. - PageSpeed Insights or lighthouse-md.com: no extensions run, so a row here is Chrome's own filter, a request the page cancelled itself, or a URL your service worker refuses. Read the URL to decide which.
The audit is binary. One row fails it, and the audit carries a small weight in Best Practices. It does not touch the Performance score. A blocked tracker that never loads cannot slow the page.
How do I find the blocked request?
- In the Lighthouse report, expand "Browser errors were logged to the console". Each row gives the source and the message. The URL in the source is the blocked resource.
- In DevTools, open the Network panel, reload, and type
blockedin the filter box. Blocked requests show a red(blocked:...)value in the Status column. The row shows the URL and the initiator, which is the script that made the request. - Sort by ownership. A URL on
google-analytics.com,googletagmanager.com,facebook.net,doubleclick.net,hotjar.comor similar is a third-party tracker, and the block is expected. A URL on your own domain means a rule matched your asset by name, which the next section covers. - Reproduce without extensions. Open an incognito or guest window with extensions disabled and reload. If the error is gone, an extension caused it.
How do I fix ERR_BLOCKED_BY_CLIENT in Lighthouse?
1. Audit without extensions
Run Lighthouse in an incognito window, a guest profile, or a fresh Chrome profile with no extensions. The Lighthouse CLI already does this by default: it starts a fresh profile with extensions disabled. Or use PageSpeed Insights or the audit at lighthouse-md.com, which run in a clean Chrome. The row disappears and the audit passes. This is the only fix for a block caused by your own extension, because the page did nothing wrong.
2. Remove a deliberate block you did not mean
If the row ends in .Inspector, clear the Network panel's request blocking list, or remove the pattern from your Lighthouse config. Keep the pattern only when you added it on purpose, for example to measure the page without a chat widget.
3. Rename assets that match a filter list by accident
Blockers match URL patterns, not intent. A first-party file named ads.js, tracking.css, /banner/, or /pixel/ can be blocked even though it draws your own hero banner. Rename the file and the path to something that describes the content, such as hero.js. This is a legitimate fix for your own assets. It is not a technique for sneaking trackers past a blocker, which the filter lists catch within days.
How do I make the page work for visitors who block requests?
A large share of visitors run a blocker, and you cannot change that. What you control is whether the page still works when the tracker never loads.
1. Guard every call into a tracker object
A blocked script never defines its global, so the next call throws Uncaught ReferenceError or Uncaught TypeError, which is a second console error and sometimes a broken feature.
// Throws when the pixel script was blocked:
fbq('track', 'AddToCart');
// Safe:
if (typeof fbq === 'function') fbq('track', 'AddToCart');
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ event: 'add_to_cart' });
Wrap analytics calls in a small helper that checks the global exists, and push to dataLayer rather than calling the vendor function directly.
2. Never make rendering wait on a third party
Do not gate content, forms, or checkout on a tracker callback. Do not await a request to an analytics endpoint before showing the page. Load trackers after window.load, so a slow or blocked tracker cannot delay anything the visitor sees.
3. Move the data you cannot lose server-side
Blocked requests are lost data. For conversions and revenue, use server-side tagging (Google Tag Manager server container, Meta Conversions API, or your own endpoint) so the event leaves your server, not the visitor's browser. First-party collection endpoints also survive many list-based blockers, as long as you are honest about what they collect in your privacy policy.
4. Check whether Chrome itself is blocking you
If the blocked URLs are your own ad slots and visitors without extensions still see the error, check the Ad Experience Report in Google Search Console. Chrome filters all ads on sites that fail the Better Ads Standards. Fix the flagged ad formats and request a review.
How do I fix ERR_BLOCKED_BY_CLIENT in Shopify, WordPress, or Next.js?
- Shopify: the blocked rows are almost always the Facebook pixel (
connect.facebook.net,/tr/), Google Ads, and app scripts for reviews or chat. The theme does not need them to render. Keep the pixels in the Shopify channel settings rather than in theme code, and the platform loads them after the page. The Lighthouse row is noise for the score; it does not affect customers. - WordPress: a pixel plugin that calls
fbqinline on every page throws when the pixel is blocked. Switch the plugin to its safe-mode ordataLayeroption, or move the pixel into Google Tag Manager, which handles a blocked tag without throwing. Caching plugins that delay scripts until interaction also hide the error from the lab run. - Next.js and other frameworks: a web-vitals or analytics beacon sent from the client is a common blocked row. Send it with
navigator.sendBeaconorfetchwithkeepaliveinside atryblock, and route it to a first-party API path that proxies to the vendor.
How do I verify the fix?
- Re-run Lighthouse in an incognito window or at lighthouse-md.com. "No browser errors logged to the console" should appear in the passed audits.
- Load the page in a profile with a blocker switched on. The console may still show the blocked request, but it should show no
ReferenceErrororTypeErrorafter it, and every visible feature should work. - Check the Network panel with the blocker on. Only the tracker rows should show a blocked status, never your own CSS, scripts, or images.
What mistakes should I avoid?
- Treating it as a server or hosting problem. The request never left the browser. Restarting the server, changing DNS, or opening a hosting ticket cannot help.
- Renaming trackers to evade blockers. Filter lists update within days, and some blockers treat evasion as a reason to block the whole domain. Rename only your own assets that were caught by accident.
- Retrying the blocked request in a loop. It fails instantly every time and fills the console.
- Letting one blocked script break the page. A missing
fbqorgtagglobal should never throw into a feature the visitor is using.
Related audits
- Browser errors were logged to the console: the audit this message fails, with the other common console errors
- Issues were logged in the Issues panel in Chrome DevTools: the blocked tracker is often the same embed that sets a flagged cookie
- Reduce unused JavaScript: tags that are blocked for a third of your visitors are candidates to remove for everyone
Audit your URL at https://lighthouse-md.com.
Audit your page now
Paste your URL, get scores plus a CLAUDE.md plan for Claude Code.