# pihole_adlist_tool and deciding which Pi-hole adlists earn their place

> pihole_adlist_tool is a shell script that replays your Pi-hole FTL query log against your gravity database to work out which adlists would actually have blocked the domains you visited, so you can see which subscriptions are earning their keep. The interesting engineering is the unique covered domains concept, and the interesting limitation is that regex filtering and CNAME inspection are outside what a shell script can reproduce.

**yubiuser/pihole_adlist_tool** — A tool to analyse how your pihole adlists cover you browsing behavior

- Repository: https://github.com/yubiuser/pihole_adlist_tool
- Stars: 552 · Forks: 29
- Language: Shell
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/yubiuser-pihole-adlist-tool

## The question the tool answers

The tool exists to answer a narrow question that Pi-hole itself does not answer: which adlists do you actually need. It does that by matching your browsing history, which is FTL's query log, against your current adlist configuration, which is the gravity database, and generating a list of domains you visited in the past that would have been blocked had your current configuration been in place back then.

The second step attributes each of those domains to the adlists it appears on, in the manner of the pihole -q command. The final output is a table of every adlist with the number of covered domains, that is, domains you visited that would have been blocked had only that one adlist been used.

That framing is the key to understanding the tool. It is a retrospective analysis, not a live monitor. The comparison is between two artefacts you already have: a log of what you requested and a database of what you would now block. Neither is changed by the tool, and nothing in the Pi-hole configuration is touched.

The audience is a Pi-hole operator with a subscription to several adlists, or with several that accumulated over years, who has no principled way to tell which ones are pulling their weight. Removing an adlist is a decision people make by intuition, and intuition about adlists is usually wrong, since the lists overlap heavily and each individual list tends to look busy.

The primary language is Shell, the licence is MIT, and the recent releases are 2.6.6 from 2025-02-28, 2.6.5 from 2024-02-09 and 2.6.4 from 2023-05-01. The repository has a single script at its root, pihole_adlist_tool, alongside the README and the licence, so the entire tool is one file you read before running.

The last push was on 2026-06-20, and the project is in maintenance mode.

## Unique covered domains, and why the number matters

The most interesting idea in the tool is the concept of unique covered domains, and the reason it exists is stated directly: domains usually appear on more than one adlist, so a raw coverage count tells you little.

Unique covered domains are domains that have been visited, would have been blocked, and appear on just one adlist. The stated purpose is that this might help you value your adlists not just by how many domains are covered but also by what would happen if you disable that adlist.

That is the right metric for the decision people are actually facing. If a list covers four hundred domains and three hundred and ninety of them are also on other lists, disabling it changes almost nothing. If it covers forty domains that nothing else covers, disabling it opens forty holes. The first number is a popularity measure and the second is a risk measure, and only the second tells you what to do.

The output list is broad enough to be worth reading in full. The script reports the number of adlists and how many are enabled, the number of unique domains in gravity.db, the number of blocked domains as reported by Pi-hole together with how often they were blocked, using both the blocked by gravity status and the blocked during CNAME inspection status and the hits count. Then the number of covered domains and how often those would have been blocked.

There is also a special case for domains on your own personal blacklist that are also on an adlist and have been visited in the past, with hits, and the documentation points at pihole -q to see on which adlist those domains appear.

Optional outputs include the top blocked domains with hit counts, the adlist table itself with id, status, total domains on adlist, covered domains, hits, unique covered domains and address, the sum of unique covered domains, an optional list of unique covered domains with their adlist id and address, and an optional regex blacklist analysis.

So the tool produces a coverage report and a risk report from the same data, and the second is the one that changes behaviour.

## Installing it and running the first analysis

Installation is deliberately minimal, because the tool is one script with no dependencies to resolve. You download it either via git clone or from a raw link, make it executable and run it:

The two commands are `chmod +x ./pihole_adlist_tool` and then `./pihole_adlist_tool`.

The options are documented in the script's own help output:

```bash
  -d [Num]                        Consider the last [Num] days (Default: 30). Enter 0 for all-time analysis.

  -t [Num]                        Show top blocked domains. [Num] defines the number to show.
```

The -d flag sets the analysis window, defaulting to the last thirty days, and entering 0 gives an all-time analysis. The -t flag adds the top blocked domains and defines how many to show.

Two more options shape the table itself. The -s flag sets the sorting order to total, covered, hits or unique, all descending, with the default sorting given as id ASC. And -u shows the covered unique domains.

The default window of thirty days is worth understanding rather than accepting. A month is long enough that the query log contains a representative sample of your browsing, and short enough that the comparison against your current adlist configuration stays meaningful, because the more distant the query, the more likely your adlist setup has changed since. The documentation names change in adlist configuration over time as one of the reasons the numbers Pi-hole reports and the numbers the tool calculates can differ.

Running with no arguments is the sensible first step, since it produces the base report with the default thirty day window, and only then add -u or -t once you know the shape of the data.

## The limits, and the gap the author cannot close in shell

The limits section is the most useful part of the documentation, and it is honest in a way that is rare.

The first limit is the mismatch between enabled adlists and the data in the gravity database. The tool warns when these disagree, and the user chooses between running gravity to clear the mismatch or proceeding anyway, in which case all available data is analysed and the results must be interpreted with caution. The reason it matters is that gravity does not include domains from deactivated adlists, so a disabled list contributes nothing to the analysis, and the script will enable all adlists from within itself if you want them counted.

The second is black and whitelisted domains, which are not considered when calculating covered domains and hits, and this cuts both ways. Whitelisted domains reduce the number of blocked domains Pi-hole reports compared to the calculated numbers, and blacklisted domains increase it.

The third is CNAME inspection, which was a limitation and is now handled after a pull request. The original problem was that the tool could not deal with domains blocked due to CNAME inspection, because Pi-hole stores the CNAME and a corresponding status rather than the actual blocked domain, and a CNAME domain will not match an adlist domain because if it did it would have been blocked directly.

The fourth is the regex blacklist analysis, whose own limits are in the notes of another pull request, and which is disabled when running Pi-hole in a Docker container.

Then there is the honest reason the author gives for the whole design. When the first version was released four years ago, Pi-hole's blocking capabilities were more limited, and it was simpler to deduce from the gravity database which queries would have been blocked than it is today. Pi-hole's regex filtering could only be taken into account by parsing the output of the pihole-FTL regex engine, which is already kind of a hack, and adding all the code to apply ABP-style filtering to the queries is out of scope, and maybe even impossible in a shell script. So the gap between what Pi-hole filters and what the tool reports gets wider over time.

That is a statement about the tool's future, not just its present, and it is the reason the project is in maintenance mode rather than being extended.

## Why it is in maintenance mode, and what a rewrite would look like

The maintenance note at the top of the documentation explains the position in the author's own words, and it is unusual to find a maintainer writing it out.

The decision not to add new features is attributed to three reasons: the growing gap between Pi-hole's actual filtering and what the tool reports, the fact that the tool is quite slow and the author is not sure it could be improved within the limits of a shell script, and a lack of motivation and time to address those issues. The author says external pull requests are welcome, and that the MIT licence was added so anyone who would like to continue to improve or use the tool is able to do so.

The rewrite sketch is the most useful sentence in the whole document. If the author started fresh, they would probably use another language, maybe C, maybe Go, which would allow implementing or reusing the FTL regex engine and parsing the regex domains and the ABP-style entries.

That is the shape of the fix, and it identifies exactly what a fork could achieve. The blocker is not the database handling, which the script already does, it is that a shell process cannot ask the same engine Pi-hole uses whether a given query would be blocked, and so it approximates that question by looking the domain up in the lists. A native program could link the same library and ask it directly, which would make the tool's answer match Pi-hole's behaviour instead of diverging from it.

The alternative for a user who wants an answer now is pihole -q, which the documentation itself points to for the blacklist case, and which answers the attribution question for individual domains without the retrospective coverage analysis. The difference in approach is that pihole -q is a lookup against the current configuration, while this tool is a comparison between your history and that configuration, which is the question a person deciding what to unsubscribe from actually has.

## Performance, requirements and the Docker caveat

The caveat section sets expectations about time, and the numbers are given.

Depending on the number of enabled adlists and the number of visited domains in the selected time period, the calculation might take some time. On the author's NanoPi NeoPlus2, an ARM quad-core Cortex A53 board, it takes about seventeen to eighteen seconds to analyse 2.3 million queries from pihole-ftl.db and 347603 domains in gravity.db. And the analysis of the regex blacklist can take minutes easily.

Those figures are useful precisely because the board is small. A Raspberry Pi class machine is a common home Pi-hole host, and a script that needs under twenty seconds there will be comfortable on a desktop.

The stated requirement is Pi-hole FTL v5.5, referenced to a pull request that raised the minimum version.

The Docker note is the one to read carefully. The author states plainly that they do not run Pi-hole on Docker themselves and have only limited ability to test the script, and that you should expect things to break anytime. Combined with the earlier note that regex blacklist analysis is disabled when running Pi-hole in a Docker container, that means the tool is best treated as a maintenance-side utility on a Pi-hole installed natively, and as something to approach with care on a containerised one.

The final piece of advice in the documentation is a good one to end on, because it is the point of the whole exercise. While lists that have attracted no or only very few hits in the analysis are prime candidates for removal, you should also consider the type of blocklist before you ultimately decide to remove a list, for example you may want to keep malware or telemetry focused blocklists nonetheless. A blocklist that blocks nothing you visit is not necessarily worthless, and the tool measures coverage, not value.

One more limitation is implied rather than stated. The tool needs the FTL query log and the gravity database in the format Pi-hole keeps them, and it needs to read them from where Pi-hole stores them, so the analysis window is bounded by how long the query log has been retained rather than by how long you have been browsing.

## Conclusion

pihole_adlist_tool is a good fit for a Pi-hole operator who has accumulated several adlist subscriptions and wants evidence rather than guesses about which to keep, because the tool measures coverage against your own query log rather than against a generic list of sites, and the unique covered domains figure is exactly the number that answers what would break if you dropped a list. It is a poor fit if your Pi-hole runs in Docker, since the author states outright that regex blacklist analysis is disabled in that setup and that things are expected to break, and a poor fit if you have moved to Pi-hole v6, since the stated requirement is FTL v5.5. Before running it, decide whether you accept a historical answer, because the comparison is against your current adlist configuration applied to past queries rather than a replay of what was configured at the time.

## FAQ

### What does pihole_adlist_tool actually do?

It matches your browsing history from FTL's query log against your current adlist configuration in the gravity database, producing the list of domains you visited that would have been blocked had that configuration been in place, then attributes each domain to the adlists it appears on.

### How do I install and run pihole_adlist_tool?

Download the script by git clone or from the raw link in the documentation, make it executable with `chmod +x ./pihole_adlist_tool` and run it with `./pihole_adlist_tool`. There is nothing else to install.

### What are unique covered domains?

They are domains that have been visited, would have been blocked, and appear on just one adlist. The point is to value adlists not only by how many domains they cover but by what would happen if that particular adlist were disabled.

### Which Pi-hole version does the tool require?

Pi-hole FTL v5.5. The author also states that they do not run Pi-hole on Docker themselves, have only limited ability to test the script, and that you should expect things to break anytime in that setup, and regex blacklist analysis is disabled when Pi-hole runs in a Docker container.

### How long does the analysis take?

It depends on the number of enabled adlists and visited domains in the selected period. The author reports about seventeen to eighteen seconds on a NanoPi NeoPlus2 to analyse 2.3 million queries from pihole-ftl.db and 347603 domains in gravity.db, and notes that regex blacklist analysis can take minutes easily.

### Why is pihole_adlist_tool in maintenance mode?

The author gives three reasons: the gap between Pi-hole's actual filtering and what the tool reports widens over time, the tool is slow and not sure it can be improved within the limits of a shell script, and there is a lack of motivation and time. External pull requests are welcome, and the MIT licence was added so others can continue the work, probably in another language so the FTL regex engine can be reused.

## Sources

- [Issues](https://github.com/yubiuser/pihole_adlist_tool/issues)
- [License: MIT](https://github.com/yubiuser/pihole_adlist_tool/blob/master/LICENSE)
- [README](https://github.com/yubiuser/pihole_adlist_tool/blob/master/README.md)
- [Releases](https://github.com/yubiuser/pihole_adlist_tool/releases)
- [yubiuser/pihole_adlist_tool on GitHub](https://github.com/yubiuser/pihole_adlist_tool)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/yubiuser-pihole-adlist-tool
