Block Ads and Trackers at the Network Level: Pi-hole vs AdGuard Home, Set Up and Verified
A DNS blocker cuts advertising and tracking traffic for every device on your network, including the ones that will never accept a browser extension. It is also the most over-sold home networking project: much of what people expect from it is what a content blocker does, not what DNS does.
The short version
A DNS blocker answers "where is ads.example.com?" with a dead address instead of the real one, so the device never connects.
- It works on everything that asks your network for DNS — phones, TVs, consoles, the fridge — with no per-device software.
- It cannot touch content served from the same domain as the page. Sponsored listings and first-party video ads survive.
- It is bypassed by any client that resolves its own names — browser secure DNS, Android Private DNS, or an app with a hardcoded resolver.
- It is not antivirus. Some lists include known-bad domains, but DNS blocking inspects nothing that arrives.
Set it up as a complement to a browser content blocker, not a replacement, and verify device by device.
Pi-hole or AdGuard Home?
Both do the same core job; the honest differences are operational.
| Pi-hole | AdGuard Home | |
|---|---|---|
| Setup | Installer, then web admin; docs at docs.pi-hole.net | One guided first-run page, then web admin; see the official AdGuard Home overview |
| Blocklists | Gravity pulls hosts-style groups on a schedule | Filter lists, hosts-style and other formats, per list |
| Custom rules | Exact block/allow plus regex lists | Filtering rules, allow/block domains, DNS rewrites |
| Per-client control | Groups from client entries; policies attach to groups | Clients by static address or CIDR, each with own settings |
| Encrypted DNS server | Usually a separate component in front | Handled directly, including DoH and DoT |
Pi-hole has the larger documentation and community-list ecosystem; AdGuard Home's single binary and built-in encrypted endpoints are easier to place somewhere narrow. Either way, run exactly one instance — two blockers in a chain multiply the failure modes.
Where to put it
| Placement | Covers | Misses |
|---|---|---|
| LAN box, handed out by DHCP | Most devices as they join | Static-IP clients, guest networks, private-DNS devices |
| Router's DNS setting | Clients that ask the router | Clients that override it entirely |
| Per-device manual DNS | That one device, reliably | Everything else |
| On the VPN server or exit | Off-site devices | Local traffic; watch for a circular dependency |
| Secondary Wi-Fi network for IoT | Chattiest devices, contained | Any client on the main network |
Two traps. The blocker needs a fixed address — a static lease, or one outside the DHCP pool — because if its IP changes, clients keep querying a device that is no longer there. And if your router hands out its own address as DNS and forwards upstream, clients never learn about the blocker.
Choosing upstream resolvers
The blocker must forward whatever it does not block, and that choice is a privacy decision, not a formality:
- Your ISP's resolver is usually fastest and gives the nearest CDN answers, but every query the blocker allowed is visible to them.
- A public recursive resolver such as Cloudflare's 1.1.1.1 service shifts trust from your ISP to the resolver operator, whose options are on its 1.1.1.1 setup page. Read the operator's logging claims rather than relying on reputation.
- Your own recursive resolver (Unbound in front of the root servers) removes the third party, at the cost of the upstream's blocklist and cache warmth.
Configure at least two upstreams so one outage is not an internet outage, and remember that if the blocker is unreachable and the client falls back to the router, blocking silently stops.
Many resolvers reject private addresses by design, so local hostnames stop resolving — DNS-rebind protection usually needs local entries added rather than disabled. And a VPN that pushes its own DNS can loop: the client uses your blocker, which forwards through the VPN.
Verify it is actually blocking
Do not infer coverage from a dashboard: test each device with a name you deliberately blocked.
- Add one test domain to your block list — one you chose, not one from a list you cannot audit.
- Query the blocker directly from a client on that network:
nslookup my-test-domain.example 192.168.1.20
dig @192.168.1.20 my-test-domain.example +short
ipconfig /flushdns # Windows, after a change - Expect a dead address such as
0.0.0.0or::, or no answer. Confirm the same query against your router's resolver returns a real address — that difference proves the path goes through the blocker. - Check the query log for the client's address and the blocked status: that entry is your evidence the device really uses this resolver.
- Test the browser separately. If the system query is blocked but the resource loads, secure DNS is in use — check the browser's DNS setting, the Android Private DNS field, and any DNS profile on iOS or macOS.
- Repeat for smart TVs and consoles, which frequently ignore DHCP DNS details.
Undoing a rule that broke something
Something will break — usually a login flow, a captcha, a video embed, or a game launcher. Work the loop instead of guessing:
- Reproduce the failure, then filter the query log to that client and look for denied queries.
- Identify the single domain the site needed. If several were denied, allow them one at a time and retest.
- Add an exact-domain allow entry. Prefer that over a regex, and never over a disabled list.
- Have the client drop its cached answer — flush DNS or restart the browser — because a cached failure persists after the fix.
- Write down what you allowed and why: an unexplained allow entry is a bug waiting to be deleted.
The over-blocking mistake to avoid
The most damaging rules are the broad ones. Allowing a whole content-delivery or authentication provider to "fix" one site can unblock tracking for thousands of domains in one line. Equally, blocking a domain many unrelated services share — an analytics endpoint, an OCSP address, a storage bucket host — breaks things where you will not think to look. Make a necessary rule as narrow as the interface allows and as short-lived as you can.
Limits, stated honestly
- Nothing is inspected. Queries are names, so the blocker cannot rewrite a page, hide an element, or strip a parameter.
- Lists lag reality. New tracker domains rotate faster than lists update.
- Caching and alternate paths. Devices cache answers; some use DNS-over-QUIC or hardcode IPs, bypassing resolution.
- Not anonymity, not security. A DNS blocker changes nothing about what your IP address reveals. Keep the browser extension and endpoint protection — see our antivirus roundup.
A VPN changes which network sees your traffic, and its own DNS behaviour is worth testing rather than assuming — our VPN leak and kill-switch testing guide covers how to confirm which resolver a device really uses. For where the blocker lives, our VPN router picks and best Wi-Fi routers pages discuss the router-side customisation that makes per-network DNS practical.
It also degrades quietly — lists stop updating, addresses change after a firmware update — so re-run the test-domain query every few months.
Frequently asked questions
Does DNS blocking stop all ads?
No. It stops requests for separate advertising and analytics hostnames that appear on your lists. Content served from the page's own domain — sponsored results, promoted listings, first-party video ads — usually remains, and so does any tracker on a domain the lists have not caught yet.
Why do some devices ignore it?
Those devices resolve their own names: browser secure DNS, Android Private DNS, an encrypted DNS profile, or an app with a hardcoded resolver. Each request then never reaches your blocker. Coverage has to be tested per device.
Is this enough protection on its own?
No. It reduces advertising and tracking traffic and can stop access to domains a list has already flagged, but it inspects nothing, cannot catch a fresh phishing domain, and does nothing about content that reaches the device. Use it beside a content blocker and real endpoint security.
How do I fix a site that broke after enabling blocking?
Find the exact denied domain in the query log, allow that single domain, flush the client's DNS cache, and retest. Avoid broad regex allowances and never disable an entire list to fix one site.