← field notes

Adblock Detection: Inside The Quiet War Between Ad Blockers And Publishers

Open a news site with an ad blocker running and, on plenty of pages, you won’t get a clean read. You’ll get a modal asking you to whitelist the domain, a blurred article body, or a polite little banner insisting the site “runs on ads.” That interruption is the visible tip of a much older, much quieter conflict: publishers trying to detect ad blockers, and ad blockers trying not to be detected. Neither side is winning outright. It’s more like a border that keeps getting redrawn.

A revenue model under pressure

Most ad-supported publishers don’t sell ads directly to advertisers one at a time. They plug into programmatic exchanges, header bidding setups, and ad servers like Google Ad Manager, where impressions get auctioned in the time it takes a page to load. That whole pipeline depends on an ad request actually reaching an ad server and a creative actually rendering in the browser. An ad blocker breaks that chain before it starts, so from the publisher’s side, every blocked impression is an auction that never happened.

That’s the actual stake here. It’s not really about ideology on either side, it’s about whether the request-response cycle that pays for the content completes or not.

How an ad blocker stops an ad in the first place

Ad blockers mostly work in two layers. The first is network-level filtering: browser extensions use APIs like declarativeNetRequest to intercept outgoing requests and cancel any that match a domain or URL pattern on a filter list, so a script trying to load from a known ad-serving domain never even gets a response. The second is cosmetic filtering: CSS rules that hide page elements matching known ad container patterns, things like div[id*="banner-ad"] or specific class names that ad networks have used for years.

Those filter lists, EasyList being the best known example, are crowdsourced and updated constantly by people who watch for new ad-serving patterns and submit rules to catch them. It’s a living document, not a fixed database, which is exactly why static detection is so hard to keep up with.

The bait div and other detection tricks

Publishers fight back with a handful of well-worn techniques, most of which boil down to setting a trap and watching what happens to it. A common one is the bait element: inject a div into the page with a class name known to appear on blocklists, wait a beat, then check its computed style or offsetHeight. If the browser reports it as hidden or zero-height when nothing legitimate should have hidden it, that’s a strong signal something intercepted or suppressed it.

Other checks look for absence rather than presence. A page might expect the googletag object to exist after its ad library loads, or expect a network request to an ad domain to resolve within some time window. If the object never appears, or the request errors out or never fires at all, the detection script infers a blocker is active. None of this tells the publisher exactly which extension is running, only that ad-related resources didn’t behave the way they should have.

Anti-adblock scripts and the lists built to beat them

Once detection scripts became common, ad blockers had a new problem: the detection code itself. Community filter lists responded by targeting the detection scripts specifically, the same way they target ad domains, adding rules that block known anti-adblock detection payloads before they can run their checks. Publishers countered by obfuscating those scripts, randomizing variable and class names between deploys, and splitting detection logic across multiple requests so no single pattern stays stable long enough to blocklist.

This is the actual mechanics of the “arms race” people talk about. It isn’t some abstract standoff, it’s a pattern-matching contest where one side writes rules against known signatures and the other side keeps changing the signature. Every update on either side buys a temporary edge that erodes as soon as the other side catches up.

Moving the ad off the publisher’s own doorstep

The more durable countermove isn’t detection at all, it’s making ads harder to distinguish from content in the first place. Server-side ad insertion, common in streaming video, splices ad segments directly into the same content stream the video player is already pulling from, so there’s no separate third-party request for a network-level blocker to catch. Some publishers apply a similar idea to display ads by proxying ad creative through their own first-party domain instead of loading it straight from an ad network’s domain, which defeats domain-based blocklist rules since everything now resolves under the publisher’s own hostname.

This raises the cost of blocking meaningfully, because a filter list can no longer rely on a simple domain match. It has to fall back on cosmetic filtering or content inspection, which is slower, more fragile, and more prone to breaking legitimate parts of the page by accident.

The subscription off-ramp

Not every publisher wants to keep fighting a detection war indefinitely. A lot of sites have quietly shifted the goal of detection from “shame the user into disabling it” to “gate the content behind a subscription or a one-time whitelist prompt.” In that model, adblock detection isn’t trying to win a technical fight, it’s just a trigger for a business decision: either turn the blocker off for this site, or pay for a version of the content that doesn’t need ads at all. It sidesteps the arms race by making the ad blocker’s presence irrelevant to whether the publisher gets paid.

Where this overlaps with fingerprinting

Adblock detection rarely lives in isolation on a page. The same probing techniques, checking for objects that should exist and don’t, watching for elements that got quietly hidden, measuring how long a resource takes to fail, show up in broader visitor fingerprinting and bot-detection stacks too. Both problems come down to inferring something about the browser environment from indirect signals, since there’s no honest API that says “yes, I am running an extension” or “yes, I am a real human.” Detection scripts end up reusing the same bag of tricks whether they’re looking for an ad blocker, a headless browser, or an automated script, because the underlying question is the same: does this environment behave the way an unmodified one would.

Browsers moved the fight up a layer

The harder shift for publishers has been ad blocking that lives in the browser itself rather than in an extension. Browsers like Brave block ad and tracker requests at the network engine level before any page JavaScript runs, and tracking-prevention features in Safari and Firefox restrict a lot of the third-party requests ad tech depends on by default. That matters for detection because there’s no DOM side effect left to probe. A bait div doesn’t get hidden by CSS injected from an extension, it simply never gets the ad content in the first place, and from the page’s perspective that looks identical to an ad simply not being sold for that impression. Client-side detection scripts can’t reliably tell the difference between “blocked” and “unsold,” which takes away one of the cleaner signals publishers used to rely on.

No finish line, just shifting cost

Neither side gets to declare victory here. Every detection method eventually gets a countermeasure, and every countermeasure eventually gets detected again, because the two systems are locked to each other by design. What actually changes over time is the cost of playing: how much engineering effort it takes to keep a filter list current, how much latency a publisher is willing to add to obfuscate a detection script, how much of the page a browser is willing to block before legitimate content breaks too. That’s the real shape of the war. Not a battle with an ending, just a cost that keeps getting pushed back and forth.

If you want more of this kind of breakdown, on fingerprinting, bot detection, proxies, and the rest of the adversarial machinery running underneath the ordinary internet, you can find the full archive here.

Get new guides and videos first — join the Telegram channel.

watch
The Hidden Internet on YouTube

Every field note starts as a short documentary. Watch the systems in this piece explained on screen.

subscribe →
read on
More field notes

The rest of the series on how the modern internet detects, tracks, and sorts the traffic that reaches it.

browse the archive →