Short answer:
ERR_BLOCKED_BY_CLIENT
means a browser extension (almost always an ad blocker) stopped the browser from making a request.
ERR_BLOCKED_BY_RESPONSE
means the server did respond, but the browser’s cross-origin security rules (CORS or Cross-Origin Read Blocking) rejected the response. The first is a user-side block that site owners cannot fix. The second is a server-side CORS configuration problem that developers can fix.
They look similar in the console. The fix paths are completely different. This guide covers how to tell them apart and what to do in each case.
Quick reference#
| If you see | What it means | Who can fix it |
|---|---|---|
| ERR_BLOCKED_BY_CLIENT | Browser extension blocked the outgoing request | The user (disable extension) |
| ERR_BLOCKED_BY_RESPONSE | Browser blocked the response – usually CORS or ORB | The site owner/developer (fix headers) |
| ERR_BLOCKED_BY_ORB | Specifically ORB (Cross-Origin Read Blocking) | The site owner (adjust content-type) |
| ERR_BLOCKED_BY_XSS_AUDITOR | Legacy – Chrome XSS Auditor (removed in 2020) | Not applicable in modern Chrome |
| ERR_BLOCKED_BY_CSP | Content Security Policy header blocked the resource | The site owner (update CSP) |
How the three main blocked errors differ#
| Error | Where the block happens | Typical cause |
|---|---|---|
| ERR_BLOCKED_BY_CLIENT | Before the request leaves the browser | Ad blocker, privacy extension, custom filter list |
| ERR_BLOCKED_BY_RESPONSE | After the response arrives, before it is used | Missing or wrong CORS headers on the response |
| ERR_BLOCKED_BY_ORB | After the response arrives | Cross-Origin Read Blocking – wrong content-type for the context |
Knowing which category you are in narrows the fix path immediately. The rest of this guide walks through both in depth.
How to tell which error you actually have#
Both errors show up in the browser DevTools Console and the Network tab. The Network tab tells you more.
Steps to diagnose
- Open the site where the error occurs
- Open DevTools: F12 (Windows/Linux) or Cmd+Option+I (Mac)
- Switch to the Network tab
- Refresh the page
- Look for failed requests (shown in red)
- Click on a failed request and check the Headers tab and the right-hand panel
What to look for:
- Status column says
(blocked:other)or(blocked:client)→ERR_BLOCKED_BY_CLIENT. The request never went anywhere. - Status column shows a response code (200, 304, etc.) but the request is marked failed → likely
ERR_BLOCKED_BY_RESPONSE. The server responded; the browser rejected the response. - Console message mentions CORS specifically (
has been blocked by CORS policy) →ERR_BLOCKED_BY_RESPONSEfrom CORS - Console message mentions “was blocked because its MIME type” →
ERR_BLOCKED_BY_ORB - Console message mentions “Content Security Policy directive” →
ERR_BLOCKED_BY_CSP
A fast sanity check: open the site in an incognito window with extensions disabled. If the error disappears, it was
ERR_BLOCKED_BY_CLIENT
. If it persists, it is a server-side CORS/ORB/CSP issue.
ERR_BLOCKED_BY_CLIENT in depth#
This error means a browser extension stopped the request from ever being sent. The extension intercepted the outgoing request, matched it against a rule, and blocked it. Chrome surfaces the resulting failed fetch as
ERR_BLOCKED_BY_CLIENT
.
Typical causes
- Ad blockers (uBlock Origin, AdBlock, AdGuard) – by far the most common. Their filter lists block millions of URLs, hostnames, and path patterns.
- Privacy extensions (Privacy Badger, DuckDuckGo Privacy Essentials, Ghostery) – block tracking requests based on behavior heuristics.
- Enterprise security extensions (corporate web filtering, Microsoft Defender SmartScreen extensions) – block URLs the organization has deemed unsafe.
- Pi-hole or NextDNS custom filter lists – while these run at the DNS layer, they produce errors that look similar to client-side blocks (usually
ERR_NAME_NOT_RESOLVED, but sometimesERR_BLOCKED_BY_CLIENTwhen combined with extensions). - YouTube Vanced / ad-block enabling extensions on specific sites – block analytics, tracking pixels, and video ad networks.
The extensions do not care what the legitimate purpose of the request is. If a URL matches a pattern (
/ads/
,
/analytics/
,
googletagmanager.com
,
doubleclick.net
), it gets blocked even on sites where the resource is essential.
What users can do to fix it
If you are seeing
ERR_BLOCKED_BY_CLIENT
while browsing a site you trust:
- Try incognito mode. Chrome extensions are disabled by default in incognito. If the site works in incognito, an extension is the cause.
- Identify the offending extension. Open
chrome://extensions, disable extensions one at a time, and refresh the page between each. When the error disappears, the last disabled extension was the culprit. - Whitelist the site in the extension. Most ad blockers support per-site exceptions. In uBlock Origin, click the uBlock icon and toggle the power button to disable it for the current site. In AdBlock Plus, click the extension icon and “Pause on this site.”
- Disable the extension entirely if you do not need its protection on any site.
What site owners cannot do
This is the frustrating part. Site owners have no direct control over what browser extensions users install or what those extensions block. An ad blocker that decides
yoursite.com/js/analytics.js
matches a tracking pattern will block it regardless of your intent. You cannot inject around it, cannot detect it reliably, and cannot override the user’s extension.
What site owners can do proactively
While you cannot defeat extensions, you can avoid triggering them by accident:
- Do not name legitimate files after ad patterns. Files named
ads.js,banner.png,tracking.js,analytics-script.jsget blocked even when they are not actually ad or tracking code. Use neutral names:metrics.jsinstead ofanalytics.js,promo.jsinstead ofad.js. - Avoid URLs that match common blocklists. Anything with
/ads/,/banners/,/sponsors/,/tracker/in the path is almost guaranteed to be blocked. Move these to generic paths like/assets/or/static/. - Self-host essential third-party resources where possible. If your analytics provider is on a blocked domain (Google Analytics, Facebook Pixel, Hotjar), self-hosting the script (or using a server-side proxy) reduces block rate for users with ad blockers.
- Do not rely on tracking pixels for critical functionality. If your checkout form depends on a tracking pixel loading, the ~30% of users with ad blockers will have a broken checkout. Keep tracking separate from functionality.
- Serve your own ads from first-party subdomains if you actually run ads.
ads.yoursite.comis less blocked thangoogleads.g.doubleclick.net, but still expect some block rate.
Users with ad blockers are a permanent fact of the web (~30-40% of desktop users in 2026). Design for them, not against them.
ERR_BLOCKED_BY_RESPONSE in depth#
This error means the server sent a response but the browser rejected it for security reasons. The two most common reasons are CORS (Cross-Origin Resource Sharing) and ORB (Cross-Origin Read Blocking).
CORS causing ERR_BLOCKED_BY_RESPONSE
Browsers enforce the same-origin policy: JavaScript on
siteA.com
cannot read responses from
siteB.com
unless
siteB.com
explicitly allows it. The mechanism for that explicit permission is CORS.
When a page on
siteA.com
makes a
fetch()
to
api.siteB.com
, two things have to be true for the response to be readable:
- The server at
api.siteB.commust sendAccess-Control-Allow-Originheaders allowingsiteA.com - For non-simple requests (PUT, DELETE, requests with custom headers), the browser first sends a preflight
OPTIONSrequest. The server has to respond correctly to that preflight, or the actual request is never sent.
If the CORS headers are missing or wrong, the browser still receives the response but refuses to hand it to the JavaScript that asked for it. Chrome surfaces this as
ERR_BLOCKED_BY_RESPONSE
in the network tab with a more specific CORS error in the console.
Common CORS misconfigurations
- No
Access-Control-Allow-Originheader at all. The server does not know CORS exists. Browser blocks. - Wrong origin in the header. Server sends
Access-Control-Allow-Origin: https://example.combut the request came fromhttps://www.example.com. Must match exactly including subdomain, port, and protocol. - Using
<em>when credentials are involved. If the request includes cookies or auth headers (credentials: 'include'), the server cannot respond withAccess-Control-Allow-Origin: </em>– it must echo back the specific origin, and also sendAccess-Control-Allow-Credentials: true. - Preflight failing. The server correctly responds to the actual request but returns 404 or 403 on the
OPTIONSpreflight. The browser never gets to send the real request. - Missing
Access-Control-Allow-MethodsorAccess-Control-Allow-Headerson preflight response. The server has to explicitly allow the methods and custom headers the actual request will use.
How to fix CORS on your server
For Nginx, a minimal CORS config on an API endpoint:
location /api/ {
# Handle preflight
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://yoursite.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
# Actual request
add_header 'Access-Control-Allow-Origin' 'https://yoursite.com' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
proxy_pass http://upstream;
}
The
always
flag is important – without it, Nginx skips the header on non-2xx responses, which produces very confusing CORS errors when the underlying request fails.
For Apache, use
Header
directives in the vhost or
.htaccess
:
Header always set Access-Control-Allow-Origin "https://yoursite.com"
Header always set Access-Control-Allow-Credentials "true"
For Node.js with Express, the
cors
middleware handles most cases:
app.use(cors({
origin: 'https://yoursite.com',
credentials: true
}));
For WordPress, CORS for the REST API is handled automatically for same-origin requests. For headless setups where the frontend is on a different domain, either configure the web server (as above) or use a plugin like WP REST API CORS.
ORB (Cross-Origin Read Blocking) causing ERR_BLOCKED_BY_RESPONSE
ORB is a newer, stricter layer on top of CORS introduced by Chrome in 2022-2023. It blocks responses where the content-type does not match the context in which the resource was loaded.
Example: a page on
siteA.com
tries to load
https://siteB.com/data.json
as a script (
<script src="https://siteB.com/data.json">
). ORB looks at the response, sees it is JSON with
Content-Type: application/json
, and refuses to deliver it to the script context – because JSON should not be loaded as a script. This prevents a class of cross-origin data exfiltration attacks.
ORB blocks produce errors like:
Cross-Origin Read Blocking (ORB) blocked a cross-origin response...
How to fix ORB errors
- Use the correct content-type for the context. If you are loading JSON, use
fetch()with the correct CORS headers, not a<script>tag. If you are loading a script, make sure it is served asapplication/javascriptortext/javascript. - Ensure the
X-Content-Type-Options: nosniffheader is sent on responses where applicable – this tells the browser to trust the declared content-type. - Do not load cross-origin resources in contexts that expect a different type. Loading an image tag pointed at a JSON endpoint, for example, is exactly the pattern ORB is designed to catch.
Most ORB issues are the result of trying to use a browser feature in a way the feature was not designed for. The fix is usually to use the right feature – if you want data across origins, use
fetch()
with CORS, not script tags or image tags.
CSP causing ERR_BLOCKED_BY_RESPONSE
A
Content-Security-Policy
header with a restrictive
connect-src
,
script-src
, or
img-src
directive can block responses the browser would otherwise accept.
Example CSP that blocks third-party scripts:
Content-Security-Policy: script-src 'self'
This only allows scripts from the same origin. A
<script src="https://cdn.example.com/lib.js">
triggers
ERR_BLOCKED_BY_RESPONSE
because CSP does not allow cross-origin scripts.
Fix: update the CSP to allow the specific domain, or remove the restrictive directive if it is not serving a security purpose. Do not use
'unsafe-inline'
or
*
as a workaround – those negate the CSP’s protection.
How long does it take to fix#
| Cause | Time to fix | Notes |
|---|---|---|
| ERR_BLOCKED_BY_CLIENT (user-side) | 30 seconds | Disable extension or whitelist the site |
| Missing Access-Control-Allow-Origin | 5-10 minutes | Add header to nginx/apache, reload |
| Wrong origin in CORS header | 2-5 minutes | Fix the exact origin string (watch for www/non-www, protocol) |
| Preflight failing with 404 | 10-20 minutes | Configure OPTIONS handling at the same location as the actual endpoint |
| Credentials mode CORS misconfig | 15 minutes | Cannot use
*
, must echo specific origin + add Allow-Credentials |
| ORB blocking wrong content-type | 15-30 minutes | Either fix content-type or change how the resource is loaded |
| CSP blocking legitimate resource | 5-30 minutes | Review CSP policy, add specific allowed source |
| Tracking script on ad-blocker list | Not fixable server-side | Rename, self-host, or accept the block rate for ad-blocker users |
If you have been debugging for more than 30 minutes on a CORS issue, check three things: the exact origin string, the preflight OPTIONS response, and whether
always
is on your Nginx
add_header
directives. 90% of CORS debugging ends at one of those three.
Symptom to cause quick lookup#
| What you observe | Most likely cause |
|---|---|
| Error shows in DevTools but site works in incognito | Extension blocking (
ERR_BLOCKED_BY_CLIENT
) |
| Error only on specific third-party resources (ads, tracking) | Ad blocker extension |
| Error only on your API calls, not your page load | CORS misconfiguration on your API |
| Error on POST/PUT requests but not GET | Preflight (OPTIONS) failing |
| Error only when sending cookies | Credentials mode CORS – cannot use
*
origin |
| Error mentions “MIME type” or “ORB” | Wrong content-type for the context |
| Error mentions “Content Security Policy” | CSP header too restrictive |
| Error only in Chrome, not Firefox | Usually ORB (Chrome-only) or a Chrome-specific extension |
| Error only on some users’ browsers, not yours | Their extension, not your server |
What developers can do proactively#
Ship proper CORS headers from day one on any API that will be called from a different origin. This prevents a class of confusing errors that only appear in production when the frontend and backend end up on different domains.
For public APIs or APIs intended for cross-origin use:
Access-Control-Allow-Origin: https://yourfrontend.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
Test CORS from a browser early – not just with
curl
, which does not enforce CORS. Open a browser console and try
fetch('https://your-api.com/endpoint')
from a different origin. If that fails, your CORS is wrong.
For content-types: always set the correct
Content-Type
header on responses, and set
X-Content-Type-Options: nosniff
as a blanket policy. This prevents browsers from guessing at content-type and triggering ORB.
For CSP: start permissive and tighten. A broken site with a perfect CSP helps no one. Use
Content-Security-Policy-Report-Only
first to see what your site actually loads, then build the strict policy from there.
What site owners cannot control#
Whatever extensions users install. Whatever corporate proxies or DNS filtering their IT department runs. Whatever VPN or privacy tools they use. If a meaningful percentage of your users see
ERR_BLOCKED_BY_CLIENT
on essential functionality, the functionality is too dependent on resources that extensions block – that is a design problem, not a server problem.
Chrome’s exact ORB behavior also changes between versions. What works today may trigger an ORB block in six months if Chrome tightens the rules. Keep an eye on Chrome’s release notes if you rely on cross-origin resource loading.
How Hostney handles these errors#
On Hostney, the nginx configuration ships with a full security and CORS baseline preset at the platform level, so the common sources of
ERR_BLOCKED_BY_RESPONSE
are handled automatically on every site:
- Security headers are applied site-wide:
X-Frame-Options: SAMEORIGIN,X-Content-Type-Options: nosniff,X-XSS-Protection,Referrer-Policy,Content-Security-Policy: upgrade-insecure-requests,Permissions-Policy,Alt-Svc(HTTP/3), and HSTS on HTTPS. These are not opt-in – every site gets them. - Correct content-types for every static asset served by nginx, which prevents the ORB-triggering mismatches where a resource is served with a wrong or sniffed type.
- CORS on static assets is configured automatically: fonts, CSS, JS, images, icons, and JSON files served by nginx allow cross-origin requests from any subdomain of the same base domain, plus the platform’s
*.hostney.appdomain. PreflightOPTIONShandling is included. This means cross-subdomain font loading, media embedding, and asset sharing within the same site’s subdomain family work out of the box without any configuration.
WordPress REST API CORS for same-origin requests is handled by WordPress itself. For separate cross-origin subdomains (frontend on one account, WordPress API on another under the same base domain), the platform’s static-asset CORS baseline covers static resources automatically. For dynamic API endpoint CORS to a completely different base domain (e.g., a React app on
app.example.com
calling a WordPress API on
api.example.org
), the CORS headers need to be handled at the application layer for now – through WordPress plugins for the WP REST API, or through the framework’s response handling for Node.js apps.
Custom per-site nginx response headers and custom CORS policies beyond the preset baseline are on the roadmap. Until then, the presets cover the common cases, and application-layer CORS handles the specialized setups.
For the client-side blocks, nothing changes on the platform – those are inherently out of the server’s control. What we can do is make the server side clean and predictable so that when you see
ERR_BLOCKED_BY_CLIENT
, you know it is the extension and not a server misconfiguration hiding as one.
Summary#
ERR_BLOCKED_BY_CLIENT
is a user-side block – an extension (usually an ad blocker) refused to send the request. The only fix is on the user’s end: disable the extension or whitelist the site. Site owners cannot override this, but they can avoid triggering false positives by not naming legitimate resources after ad or tracking patterns.
ERR_BLOCKED_BY_RESPONSE
is a server-side problem. The server responded, but the browser’s CORS, ORB, or CSP rules rejected the response. The fix is on the developer: set the right headers, use the right content-types, and write a CSP that matches what your site actually does.
Start by running the incognito test. If the error disappears, it is an extension. If it persists, it is your server. From there the diagnostic paths diverge completely. Get the diagnosis right first and the fix falls out naturally.
For related browser errors, see ERR_CONNECTION_REFUSED, ERR_CONNECTION_TIMED_OUT, and ERR_CONNECTION_RESET.