The block happens at the lookup. A name on the list gets a dead-end answer, so your device never even tries to connect to it. Everything else resolves as normal.
Every page you open starts with a name to look up. DNS blocking steps in right there, deciding which names get a real answer and which get a dead end, before a single byte of an ad is fetched.
The idea in one picture
- A blocklist - a list of domains to refuse
- A long, regularly updated list of domain names known to serve ads, track you, or host malware. Things like ads.example-network.com. People maintain these lists so you do not have to.
- The block - a dead-end answer
- When a name on the list comes in, the resolver does not return its real address. It returns nothing useful (an empty answer, or 0.0.0.0), so your device has nowhere to connect. The ad or tracker is never contacted. Names that are not on the list resolve completely normally.
Check it yourself: one name, two resolvers
The whole mechanism fits in two commands. Ask a filtering resolver for a well-known ad domain, then ask one that does not filter, and compare what comes back. Both use dig, from the dnsutils or bind-utils package.
$ dig @194.180.189.33 doubleclick.net A +short
0.0.0.0
$ dig @1.1.1.1 doubleclick.net A +short
108.177.14.100
108.177.14.101
108.177.14.138Same name, seconds apart, two different answers. 0.0.0.0 is not a short address, it is the absence of one: a device handed it has nowhere to connect, so the request stops there and no ad server is ever contacted. Your addresses from 1.1.1.1 will not match the ones above, because Google answers from whichever edge is near you and the set rotates. That does not matter. The only thing being compared is an address against no address.
Telling a block apart from a domain that is simply dead
A refusal does not always look like 0.0.0.0. There are three shapes it can arrive in, and only the first one is obvious:
| What you see | Where | What it means |
|---|---|---|
| 0.0.0.0, TTL 300 | this resolver, A queries | Refused. The fixed 300-second TTL is the resolver's own, not the domain's. |
| NOERROR, ANSWER: 0 | this resolver, AAAA queries | The same refusal on the IPv6 side, phrased as "no such record". The giveaway is the authority record: the name fake-for-negative-caching.adguard.com is the filter admitting authorship. |
| NXDOMAIN | Quad9 and others | Refused by claiming the name does not exist - the same wording a genuinely dead domain gets. |
$ dig @194.180.189.33 doubleclick.net AAAA +noall +comments +authority
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55099
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
doubleclick.net. 300 IN SOA fake-for-negative-caching.adguard.com. ...
$ dig @9.9.9.9 <a name from a malware feed> A +noall +comments
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 16163
; EDE: 17 (Filtered)Quad9 at least labels its refusal: EDE: 17 (Filtered) is an Extended DNS Error, the standard way for a resolver to say "I withheld this on purpose" instead of letting you guess. Our resolver sends no such code; the 0.0.0.0 is the entire signal.
So when a name will not resolve and you want to know why, the reliable test is the second command: ask a resolver that does not filter. A real address back means you watched a block. The same refusal from both means the domain is dead and nobody blocked anything.
The same two checks on Windows
Nothing to install: Resolve-DnsName takes the resolver address directly, and prints the answer as a table.
PS> Resolve-DnsName -Name doubleclick.net -Server 194.180.189.33 -Type A
Name Type TTL Section IPAddress
---- ---- --- ------- ---------
doubleclick.net A 300 Answer 0.0.0.0
PS> Resolve-DnsName -Name doubleclick.net -Server 1.1.1.1 -Type A
doubleclick.net A 118 Answer 172.253.130.102
doubleclick.net A 118 Answer 172.253.130.138
doubleclick.net A 118 Answer 172.253.130.101This pair was run from a Windows desktop while the dig output further up came from a server in a different country, which is why the addresses from 1.1.1.1 are a different set again. The refusal is identical in both places, down to the 300-second TTL that never counts down.
On the IPv6 half, Windows is the clearer of the two tools. dig prints the authority record as one long line that scrolls off the screen; PowerShell puts the interesting field in a column with a name on it:
PS> Resolve-DnsName -Name doubleclick.net -Server 194.180.189.33 -Type AAAA
Name Type TTL Section PrimaryServer NameAdministrator
---- ---- --- ------- ------------- -----------------
doubleclick.net SOA 300 Authority fake-for-negative-caching.a hostmaster.doubleclick.net
dguard.comThere is the filter admitting authorship, wrapped over two lines by the console width: PrimaryServer = fake-for-negative-caching.adguard.com. A real domain's SOA names a real nameserver, so nothing in an ordinary answer looks remotely like that.
nslookup doubleclick.net 194.180.189.33 reaches the same conclusion and prints Address: 0.0.0.0, with two cosmetic quirks: it labels the server UnKnown, because that address has no reverse record, and its surrounding text is translated into the machine's display language. Resolve-DnsName is the better of the two for this.
Why one setting covers everything
Almost every app on your device, the browser, the games, the smart TV, the phone that will not let you install an ad-blocker, has to do DNS lookups to reach the internet. They all go through the same resolver. So when the resolver filters, the filtering applies to all of them at once. There is no extension to install per browser and no app to keep updated. Point a device, or a whole home network, at a filtering resolver, and that is the configuration done.
That is the real strength of blocking at the DNS layer: it is network-wide and app-agnostic. It is also why it pairs naturally with encrypted DNS. The same resolver that hides your lookups from the network can filter out the bad names while it is at it.
The lists doing the work
A filtering resolver is only as good as its lists. These are the four open, well-maintained sources behind our own filtering, each aimed at a different problem. You can see the live counts on our server info page.
| List | What it targets | In short |
|---|---|---|
| AdGuard DNS filter | Ads and trackers | A broad, curated list of advertising and analytics domains |
| OISD Blocklist Small | Ads, trackers, malware, phishing | A large aggregated list tuned to keep false positives low |
| PhishTank + OpenPhish | Phishing sites | Community-reported pages that impersonate real services |
| URLHaus (abuse.ch) | Malware distribution | Live domains caught handing out malware |
Lists update constantly as new ad and threat domains appear and old ones go quiet, which is why filtering is a moving service rather than a one-time setting - and why no list should be trusted blindly. A blocklist is an opinion that can be wrong: we once watched an imported IP list quietly ban Googlebot from our own server.
The opinion shows in what a list leaves alone, too. dig @194.180.189.33 www.googletagmanager.com A +short returns a real address: the four lists carry rules for look-alike names such as googletagmanager-cn.com, but none for Google Tag Manager itself, even though it is analytics plumbing on a large share of the web. Whether that is the right call is precisely the judgement you hand to a list maintainer when you point a device at a filtering resolver.
How much of a live threat feed the lists actually reach
The malware and phishing half of the filtering is the part no browser extension replaces, because the connections it stops mostly do not come from a browser. It is also measurable in a few minutes. URLHaus publishes the malware URLs it is currently seeing; strip them to hostnames and ask both resolvers about them.
$ curl -s https://urlhaus.abuse.ch/downloads/text_online/ \
| sed -E 's#^https?://##; s#[:/].*##' | sort -u | head -5
0022a601.pphost.net
0following.com
123.ywxww.net
132.red-81-42-249.staticip.rima-tde.net
1717.1000uc.com
$ dig @194.180.189.33 0022a601.pphost.net A +short
0.0.0.0
$ dig @1.1.1.1 0022a601.pphost.net A +short
185.216.144.21Running that against the feed on 30 August 2026: 15,909 live URLs, which reduce to 1,833 unique hosts. Two disjoint samples of 100 hostnames each, asked of this resolver, came back with 90 refused in the first sample and 89 in the second. The interesting part is the rest.
- 1,299 of those 1,833 hosts are bare IP addresses. A URL written as http://203.0.113.10/x.exe never asks a resolver anything, so no DNS blocklist can see it, let alone refuse it. That is the raw-IP limit in one number: on this feed, on this day, most malware URLs skip DNS entirely.
- The names that were not refused were shared platforms. Across both samples: raw.githubusercontent.com, docs.google.com, sites.google.com, firebasestorage.googleapis.com, web.archive.org, an Amazon S3 bucket and a Backblaze one. Malware parked on infrastructure whose domain cannot be refused without taking a great deal of legitimate work down with it - the same first-party problem as ads, wearing a different suit.
Two samples minutes apart, so treat 89 and 90 as the shape rather than a constant; the feed turns over continuously and your own run will land somewhere else. The shape is the point. Most of what a name-based filter can be asked to refuse, it refuses. What it cannot reach is not a gap in the list, it is names the attacker never bothered to use.
DNS blocking vs a browser ad-blocker
They are not rivals. They work at different points and miss different things, so the strongest setup runs both. Here is who does what.
| DNS-level blocking | Browser extension | |
|---|---|---|
| What it covers | Every app and device on the resolver | Only that one browser |
| Blocks by | Whole domain name | Page elements and domains |
| First-party ads (same domain as the content) | Cannot block | Can block |
| Cosmetic cleanup (blank gaps, banners) | No | Yes |
| Setup | One resolver setting | Installed per browser |
What DNS blocking cannot do
DNS blocking only knows domain names. It decides yes or no for a whole name and nothing finer. The instant an ad is served from the same domain as the thing you actually came for, that bluntness becomes a wall: refusing the domain would break the content too, so the ad has to be let through. This is the single reason most of the ads people complain about still get past it. Here is where it shows up in real life.
$ dig @194.180.189.33 ads.youtube.com A +short
0.0.0.0
$ dig @194.180.189.33 www.youtube.com A +short
142.251.157.4
142.251.156.4
142.251.150.4
$ dig @194.180.189.33 googlevideo.com A +short
216.58.201.4That output is the entire limitation in three commands. YouTube's ad domain is on the lists and is refused. The site itself and the servers that stream the video are not, and cannot be, because the ads that actually interrupt you arrive down that same playback path. Refusing it would not remove the ads; it would remove YouTube.
Watch for one pattern running through all of it: every modern social platform serves its ads first-party, from the very same domain as the posts and videos you came to see, and flags them as ads only inside the app's own code, never at the domain level. That design is precisely what defeats domain-level blocking. Here is how it plays out platform by platform.
-
YouTube video ads
The ads stream from the googlevideo.com servers that also stream the video you want, spliced into the same playback. There is no separate ad domain to refuse. Block it and the video stops too, so DNS filtering simply cannot remove YouTube's in-stream ads. A browser blocker can, because it works inside the player and can tell an ad segment from the real video and skip past it.
-
TikTok "For You" ads
Sponsored clips are dropped in among the organic ones in your feed and delivered through the same content network, especially inside the app. To DNS the ad is just another video in the endless scroll, coming from the same place as everything else. Only TikTok's own app data marks which clip is paid, and DNS never sees that data.
-
X (Twitter) promoted posts
"Promoted" posts are slotted straight into your timeline from the same servers (twimg.com and the site's API) that serve ordinary posts. The only thing that says "Ad" is a label in the data the app draws on screen. Refuse the domain and the entire timeline disappears with the ad, so DNS has to let it through.
-
Instagram feed, Stories and Reels ads
Sponsored posts in the feed, and the ads slipped between Stories and between Reels, all come from the same Meta network (cdninstagram.com, fbcdn.net) that delivers your friends' photos and videos. Content and ads share the infrastructure completely, so there is no separate name for DNS to single out.
-
Facebook sponsored posts
The same Meta story from the other side: sponsored posts sit inline in the feed, served from facebook.com and fbcdn.net, indistinguishable at the domain level from every other post you scroll past. A browser blocker can read the page and hide the marked post; DNS has nothing to grab onto.
-
Twitch stream ads
Ads are stitched directly into the live video stream on the server, from the same servers as the broadcast, before it ever reaches you. To DNS it is one continuous stream from one domain, with no seam to cut at.
-
Spotify free-tier audio ads
The audio ads come down the same delivery network as the music. Block that domain and the songs go silent too, so DNS filtering leaves the ads untouched.
-
Ads baked into mobile apps
Beyond the big names, countless apps pull ads through their own first-party domain, or connect to a hardcoded IP address that never asks the resolver at all. Either way there is no separate name to refuse, and a browser extension cannot reach inside an app, which is the awkward gap where some ads survive both approaches.
There are two more limits worth naming. DNS blocking does no cosmetic cleanup: when it kills an ad slot, nothing tells the page to close the gap, so you can be left with a blank rectangle where the ad would have been. And anything that connects by raw IP address, skipping the lookup entirely, is never seen by the resolver and so is never filtered.
The honest summary: inside a browser, a dedicated content blocker like uBlock Origin blocks more, and more correctly. It can pick apart the page, hide the right element, reflow the layout cleanly, block an ad path on a domain while allowing the rest of it, and push back on anti-adblock scripts. DNS blocking can do none of that. On the web, in the browser, the extension wins.
So why block at DNS at all?
Because the browser is not the only thing on your network, and a browser extension only protects the browser it is installed in. DNS blocking works where extensions cannot reach, and it does a few things the extension structurally cannot.
- It covers every device and app at once. Smart TVs, consoles, phones, IoT gadgets, and the apps you cannot install an extension into, all of it filtered from one resolver setting. A TV that begs you to install nothing still obeys the resolver it was handed.
- It stops the connection before a single byte is fetched. A blocked tracker or malware domain is never contacted at all. The extension blocks the ad after the page has started reaching for it; DNS refuses the address up front, which also means the phone-home and the bandwidth never happen.
- It catches traffic the browser never sees. Background telemetry from the operating system, chatty apps, and connected devices all do DNS lookups. A browser extension has no visibility into any of that. The resolver does.
- It is one setting, with nothing to maintain. No per-browser install, no per-device upkeep. Point the network at the resolver once and new devices are covered the moment they join.
So they are not competing for the same job. DNS blocking is the baseline that protects everything, the floor under your whole network, especially strong against trackers and malware that never reach a browser. A content blocker is the precision tool for the browser, where it cleans up what DNS is too blunt to touch. The strongest setup is plainly both: DNS filtering for the network, uBlock Origin in the browser on top.
Filter and encrypt in one move
The resolver that blocks ad, tracker and malware domains for every device on your network can also encrypt your lookups so the network cannot read them. Point your device at it once.
Set up encrypted, filtered DNSNew to how a resolver fits in? Start with what a DNS resolver is, or check the live blocklist counts on the server info page.