How Websites Detect You Are Using an Ad Blocker

Photo: Szabó Viktor / Pexels
When a website tells you to disable your ad blocker, it already knows you have one. That detection happened before any popup appeared — often within the first few hundred milliseconds of the page loading. Publishers have built increasingly sophisticated systems to identify blocked ads, and the methods go well beyond checking whether an ad script ran. Some detection techniques work entirely in CSS. Some exploit HTTP-level responses. One abuses an experimental browser feature called Early Hints. Understanding these methods requires tracing exactly what happens when a browser loads a page and an ad blocker intercepts part of that process.
What Ad Blockers Actually Do
Before examining detection, it helps to understand what ad blockers intercept. Most popular ad blockers — uBlock Origin, AdBlock Plus, Brave's built-in blocker — work primarily as network-level filters: they intercept outbound HTTP requests from the browser and block those matching a filter list before the request reaches the server.
Filter list — a curated database of URLs, domain patterns, and HTML element selectors that an ad blocker uses to identify advertising and tracking resources. The most widely used is EasyList, a community-maintained list updated daily that contains several hundred thousand rules. Filter lists also include cosmetic filters — CSS selectors that hide elements matching ad-related class names or IDs, even when the underlying request is not blocked.
The two-layer architecture matters for detection. A network-level block means a request never leaves the browser. A cosmetic filter means the request completes but the element is hidden via CSS display: none or visibility: hidden. Detection systems must handle both cases differently, because the observable evidence they leave is different.
Source: uBlock Origin documentation (2024), "How uBlock Origin Works" — official description of network filtering, cosmetic filtering, and scriptlet injection mechanisms. Available at github.com/gorhill/uBlock.
Source: EasyList (2025), "EasyList Filter List Statistics" — the primary filter list used by major ad blockers, maintained at easylist.to, containing rules for URL blocking and cosmetic element hiding.
Method 1: Bait Elements (The Honeypot)
The most common detection method is simple enough to implement in ten lines of HTML and JavaScript. The publisher creates an invisible DOM element specifically designed to look, to a filter list, like an advertisement.
Bait element — an HTML element placed in the page with class names, IDs, or attributes drawn directly from ad-blocker filter lists. For example: <div id="adBanner" class="ad-slot leaderboard" style="height:1px; width:1px;">. The element is invisible to human visitors (it has no content and is sized to 1×1 pixel). But to a cosmetic filter, it looks exactly like an ad container and gets hidden.
The detection script then checks the element's computed height or visibility:
const bait = document.getElementById('adBanner');
const styles = window.getComputedStyle(bait);
if (styles.display === 'none' || styles.height === '0px') {
// Ad blocker detected — element was hidden by cosmetic filter
}
If the ad blocker applied a cosmetic filter to the element, the height collapses to zero or display changes to none. If a network-level blocker prevented the loading of an ad script that would have populated the element, the element remains empty. Both cases are detectable.
The cat-and-mouse dimension: filter list maintainers eventually add rules to block the detection script itself, or to whitelist the bait element (preventing the cosmetic filter from touching it). Publishers respond by randomizing the class names and IDs of bait elements — generating them dynamically with JavaScript — so they never appear in filter lists. Modern bait-based detection uses randomly generated class names that change on each page load, making static filter rules ineffective against them.
Source: Zhu, Z. et al. (2018), "Ad-Versarial: Defeating Perceptual Ad-Blocking," ACM CCS Proceedings — analysis of bait-element detection methods and the adversarial dynamics between detection and evasion.
Method 2: Network Request Probing
A more reliable detection method does not use DOM manipulation at all. Instead, the publisher's code attempts to load a resource from a URL that matches ad-blocker network filter rules — and observes whether the request succeeds.
The implementation: a small JavaScript file (or image, or XHR request) is loaded from a URL path like /ads/banner.js or from a subdomain like ads.publisher.com/track.gif. These paths match the pattern rules in EasyList and similar filter lists, so a network-level blocker will intercept the request before it reaches the server.
The detection code uses a promise or callback:
fetch('/ads/prebid.js')
.then(() => { /* request succeeded, no blocker */ })
.catch(() => { /* request failed — blocked at network level */ });
A failed fetch, a network error, or a response with content-length zero all indicate a blocked request. The resource at /ads/prebid.js can be a 1-byte empty file — the server doesn't need to serve real ad code. The detection depends only on whether the browser's network layer allowed the request through.
This method is harder to evade than bait elements because it probes network-level blocking directly. To defeat it, an ad blocker must either allow the request (losing network blocking) or intercept the detection script itself (requiring the script URL to appear in a filter list, which the publisher can change).
Source: Storey, G. et al. (2017), "Future of the Web: Understanding Ad Blocking Using Measurements," WWW Proceedings — measured analysis of ad blocker detection prevalence and the network-probe method's effectiveness across major publishers.
Method 3: CSS-Based Detection Without JavaScript
CSS can detect ad blocker activity without any JavaScript executing — a technique that exploits the cascade behavior of stylesheets and the CSS visibility property in combination with server-side rendering.
The mechanism uses a CSS file served from an ad-related URL path. The publisher includes a stylesheet at a URL like /css/ads-layout.css that sets a CSS custom property (CSS variable) on the document root:
/* File served from /ads/layout.css — this URL is in filter lists */
:root {
--adblock-detected: 0;
}
A second, always-loaded stylesheet references that variable:
/* Main stylesheet */
#adblock-notice {
display: var(--adblock-detected, block);
}
If the ad blocker blocks the first stylesheet (because its URL matches a filter rule), the CSS variable is never defined, and var(--adblock-detected, block) falls back to its default value — block — making the "please disable your ad blocker" message visible. If the first stylesheet loads, the variable is set to 0 (maps to none), and the message stays hidden.
This entire mechanism requires no JavaScript. The detection is encoded in the CSS cascade itself, visible to server-side log analysis, and essentially undetectable to the user until the message appears.
CSS custom property (CSS variable) — a property defined with a -- prefix (e.g., --color-primary: blue) that can be referenced elsewhere in stylesheets using var(). Custom properties inherit through the document tree and can be set at any element level.
The limitation: CSS-based detection cannot trigger complex responses (modal dialogs, content paywalls, usage tracking) without JavaScript. It can show or hide elements, but the publisher's response to detection is constrained to CSS-expressible changes unless JavaScript is also available.
Source: MDN Web Docs (2025), "CSS Custom Properties (Variables)" — specification documentation for CSS custom properties and their cascade/fallback behavior, which underpins CSS-based ad detection.
Method 4: HTTP 103 Early Hints Abuse
One of the more technically elegant detection methods exploits HTTP 103 Early Hints, an experimental HTTP status code designed to improve page load performance.
HTTP 103 Early Hints — a status code that allows a server to send preliminary HTTP headers (typically Link preload headers) to the browser before the full response is ready. The browser can begin fetching referenced resources while the server finishes generating the main response, reducing perceived load time.
The detection technique, documented by researcher Sergey Danilov in 2024 and discussed on Hacker News, works as follows: the server sends a 103 response with a Link header pointing to an ad-related URL. The browser initiates a preload fetch for that URL. If an ad blocker intercepts the preload request (which it does, because the URL matches filter rules), the browser logs a network error for the preload.
The server, when it eventually sends the main response, includes a flag indicating that the 103 preload resource should have loaded. The page-side code checks whether the preloaded resource is available in the browser's cache. If it is not — because the ad blocker blocked the preload — the detection fires.
| Detection method | Requires JavaScript | Detects network blockers | Detects cosmetic filters | Bypass difficulty |
|---|---|---|---|---|
| Bait elements (static) | Yes | No | Yes | Low — static filter rules |
| Bait elements (dynamic) | Yes | No | Yes | High — randomized names |
| Network request probe | Yes | Yes | No | Medium — detect script must be blocked |
| CSS variable cascade | No | Yes (if CSS URL blocked) | No | Medium |
| HTTP 103 Early Hints | No | Yes | No | High — operates at HTTP layer |
| Service Worker interception | Yes | Yes | Yes | Very high |
Source: Danilov, S. (2024), "Detecting adblock without JavaScript by abusing HTTP 103 responses," Hacker News discussion thread — original technical write-up of the HTTP 103 Early Hints detection method. Available at news.ycombinator.com/item?id=39816835.
Method 5: Service Worker and Resource Timing API
Modern browsers expose a JavaScript API called the Resource Timing API that lets scripts measure how long network requests took. This API can be combined with Service Workers to detect ad blockers with high reliability.
Resource Timing API — a browser performance API that exposes detailed timing information for every network request made by the page: DNS lookup time, TCP connection time, response time, and total duration. Blocked requests appear in the timing data with zero duration or error states.
The detection implementation loads a set of resources including some from ad-related URLs. It then queries the Resource Timing API for each resource's performance entry. Blocked resources either have no entry (if blocked before the request was issued) or have a zero-duration entry (if blocked and returned empty). Successful resources have non-zero durations consistent with normal network latency.
This method is harder to evade because it operates through browser-native APIs that ad blockers cannot easily suppress without breaking legitimate page functionality. Some advanced blockers inject scriptlets that fake Resource Timing entries to defeat this detection, but this is an escalation that introduces its own compatibility risks.
Service Worker — a JavaScript file that runs in the background, separate from the main browser thread, and can intercept and modify all network requests from a given origin. Publishers can use Service Workers to detect which requests failed (were blocked) and report this data back to the server without relying on the main page's JavaScript context.
Source: W3C Resource Timing Level 2 Specification (2023), "Performance Timeline" — official specification for the Resource Timing API, which defines the timing attributes available for each network request.
The Arms Race Dynamic
Each detection method described above has a corresponding evasion, and each evasion has a counter-evasion. The pattern has repeated for over a decade.
Early ad blockers (2006–2010) worked by blocking requests to known ad server domains. Publishers responded by serving ads from their own domains. Ad blockers added heuristic pattern matching. Publishers obfuscated script names. Ad blockers added behavioral analysis (scripts that attempt to render iframes in certain ways). Publishers added detection-of-detection (code that identifies when its own detection script is blocked).
The current state, as of 2026: major publishers use multi-layered detection combining at least two methods simultaneously, typically a bait element check combined with a network probe. Browser extensions like uBlock Origin use dynamic filter generation and scriptlet injection to defeat detection. The half-life of any single detection or evasion technique before the other side patches it is typically weeks to months.
The fundamental asymmetry: publishers must detect ad blockers without breaking the experience for users who are not running one. Every detection heuristic that increases sensitivity also increases the risk of false positives (falsely flagging users without blockers). Ad blockers only need to defeat detection reliably for their users — they have no false-positive problem.
Source: Pujol, E. et al. (2015), "Annoyed Users: Ads and Ad-Block Usage in the Wild," IMC Proceedings — measurement study of ad blocker adoption rates and publisher detection responses, establishing the economic context of the arms race.
The Privacy and Ethics Angle
The conversation about ad blocker detection is inseparable from the privacy context that drove ad blocker adoption. The Interactive Advertising Bureau estimated in 2024 that approximately 42% of desktop users and 15% of mobile users in the United States use some form of ad blocking, up from roughly 11% desktop in 2014.
The primary driver of adoption is not hostility to advertising per se — surveys consistently show that users object to specific ad behaviors: autoplay video with audio, ads that cover content, tracking across sites, and malvertising (malicious code delivered through ad networks). Research from Princeton's Web Transparency and Accountability Project documented that third-party trackers are present on over 75% of the top million websites, and that ad networks have served malware to users on multiple occasions.
Malvertising — malicious code delivered through advertising networks. Because ad networks aggregate supply from thousands of publishers and serve dynamically loaded code, a compromised ad can reach millions of users across unrelated sites. Major malvertising campaigns have affected The New York Times, BBC, MSN, and AOL simultaneously, without those publishers' knowledge.
The ethics of detection, from a publisher's perspective: advertising revenue funds content production. Ad blocking at scale reduces that revenue. Detection systems allow publishers to request that users who block ads either disable the blocker or subscribe to an ad-free tier — a transaction the publisher argues is fair given the implicit content-for-ads exchange.
The ethics from a user's perspective: the "implicit exchange" was never explicitly agreed to, and the scope of data collection (behavioral tracking across sites, device fingerprinting, interest profiling) has expanded well beyond what early web users would have recognized as advertising. Detection systems, from this view, enforce a contract that was unilaterally revised by one party.
Both positions contain legitimate claims. What is clear technically: ad blocker detection is not hacking or unauthorized access. It is the publisher observing what the browser loads within their own web page — a process entirely within the publisher's legitimate control over their own content.
Source: Englehardt, S. and Narayanan, A. (2016), "Online Tracking: A 1-million-site Measurement and Analysis," ACM CCS Proceedings — Princeton study documenting the prevalence of third-party trackers, the most frequently cited research in the ad blocking ethics debate.
Source: Interactive Advertising Bureau (2024), "Ad Blocking Report" — annual measurement of ad blocker adoption rates by device type and geography.
Frequently Asked Questions
Q: Can websites detect ad blockers if JavaScript is completely disabled?
A: Some detection is possible without JavaScript. CSS-based detection using blocked stylesheet URLs and custom property fallbacks works entirely in CSS. HTTP 103 Early Hints detection operates at the HTTP level before any scripts run. However, the response to detection — displaying a modal, triggering a paywall, logging the event — typically requires JavaScript. Detection without JavaScript can only change what CSS renders, not trigger dynamic behavior.
Q: Why do some sites ask me to disable my ad blocker even when I am not running one?
A: False positives. Certain security software, corporate proxies, and privacy-focused browsers (like Brave's built-in shields) trigger the same signals as ad blockers — blocking certain network requests or modifying DOM elements. Detection systems calibrated for high sensitivity generate false positives for these users. Some VPN services also route traffic through IPs flagged as bot or proxy traffic, which can trigger anti-bot systems that resemble ad-block detection.
Q: What is the difference between an ad blocker and a content blocker?
A: An ad blocker targets specifically advertising and tracking resources, using filter lists like EasyList and EasyPrivacy. A content blocker is a broader category that can block any type of content based on user-defined or administrator-defined rules. iOS Safari uses the term "content blocker" for its extension API, which operates differently from browser extensions — it provides a static JSON rule list to the browser engine rather than running JavaScript, which makes it faster but less flexible.
Q: Do news paywalls use different detection than ad-blocker walls?
A: Yes. Paywalls typically detect reading behavior (number of articles read) and enforce limits through server-side session tracking or cookies — these do not depend on ad blocker detection at all. Metered paywalls count page views via server logs and set a cookie after the free limit; no client-side detection is needed. Soft paywalls that ask ad-block users to subscribe are typically combining metered access with ad-block detection as a separate trigger.
Q: Can ad blockers themselves detect when a site is trying to detect them?
A: Yes. Some ad blockers include scriptlets — small JavaScript snippets injected into the page — that override browser APIs used in detection (like getComputedStyle, XMLHttpRequest, and the Resource Timing API) to return fabricated values that conceal blocking activity. uBlock Origin's scriptlet library includes several specifically targeting known detection scripts from publishers and anti-ad-block vendors.
Q: Is ad blocker detection legal?
A: In all major jurisdictions, yes. A publisher observing what loads within their own web page involves no unauthorized access to a user's device. Conditioning access to content on disabling an ad blocker is similarly legal. What is legally contested in some jurisdictions is whether requiring acceptance of tracking cookies as a condition of accessing content violates GDPR's requirement that consent be freely given — a separate question from detection itself.
Read next:
Follow new articles
Add SciHub101 to your feed reader to see new science and technology stories.
About the Author
SciHub101 is an independent science and technology publication founded and edited by Buğra Sözeri, a software engineer and app developer based in Türkiye. AI tools assist with drafting and research. Source documentation in the existing archive is uneven, and articles are being reviewed and corrected. The Editorial Team byline identifies editorial responsibility; it does not certify specialist or independent human review. Where we compare products, anything built by our own team is labelled as such — see the editorial guidelines and About page for how corrections and disclosures work.
Related Articles

Next.js 15: The Developer's Guide to App Router, Server Components, and Turbopack
Next.js 15 shipped in October 2024 and made the App Router the official default for new projects, stabilized Turbopack for development builds, and introduced async request APIs that changed how developers access cookies, headers, and search parameters. Next.js 16 (October 2025) extended Turbopack to production. This guide covers the concepts, architecture decisions, and practical trade-offs of the Next.js 15 era, which remains the most widely deployed major version.

How to Use Figma for Beginners: UI Design Crash Course 2026
Figma is a browser-based design tool used by 99% of product teams and freelance designers. Unlike Photoshop or Sketch, Figma runs entirely in the browser, eliminates version control chaos, and enables real-time collaboration. Core concepts: Frames (artboards), Components (reusable design elements), Auto Layout (responsive design without code), and Prototyping (clickable mockups). A beginner workflow involves creating a Frame, adding shapes/text, converting frequently-used elements to Components, applying Auto Layout for scaling, and prototyping interactions. Most beginners spend 60% of time fighting tools instead of designing. This article covers what Figma actually is, the five foundational concepts, a beginner's first-hour workflow, and practical keyboard shortcuts that save hours of clicking.

Quantum Computing Explained Simply — What It Is, What It Isn't
Quantum computing promises to break modern encryption and simulate molecular biology. Is it real? Here's what qubits, superposition, and entanglement actually mean — and an honest assessment of the timeline to usefulness.

How Search Engines Index the Web — The Technology Behind Every Search
Google processes 8.5 billion searches per day. Behind every result is a system that has crawled and indexed hundreds of billions of web pages. Here's how it actually works — from crawling to PageRank to ranking signals.

How Social Engineering Hacking Works — Why Humans Are the Weakest Link
The most sophisticated cyberattacks don't exploit code — they exploit people. Here's how phishing, pretexting, spear phishing, and vishing manipulate human psychology to bypass any technical defense.

How VPNs Work — What They Actually Protect (And What They Don't)
VPNs are sold as privacy tools, but most people don't know what they actually do. Here's the real technical picture — tunneling protocols, no-log claims, and how Tor compares.