This is an old revision of the document!
Table of Contents
Filter Lists
An Adblock-syntax filter list — EasyList, EasyPrivacy, Disconnect, and a few hundred smaller ones — is the closest thing web measurement has to a shared instrument. It is free, comparable across papers, and reviewable rule by rule, which is why 198 papers in this corpus1) used or produced one, and why a large share of what the field knows about advertising and tracking on the web rests on one.
It is also a moving, crowd-maintained, anglophone artefact with a known and large error rate in both directions, and the field uses it simultaneously as the instrument that produces a measurement and as the ground truth that the measurement is scored against. That circularity is this page's subject.
This page is about the list itself: what it is, which ones exist, how to record which one you used, how to apply it, where its coverage runs out, and how to say something defensible when your labels came from it. What to do with the requests once they are labelled is on Classifying web requests; that page carries the ML lineage, the request-unit ladder and the link-decoration material, and this page carries the list.
The one thing to take away. In this corpus the filter list is both the instrument and the definition, and almost nobody separates the two. Of the 167 papers that used a list as part of a classification step, 119 (71.3%) report no validation of the list's labels at all — every validation value they carry is not-applicable or none-reported. The list is the label. Calzavara et al. [1Calzavara, Stefano; Casarin, Samuele; Squarcina, Marco; Maffei, Matteo (2026): "From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques", in: Proceedings on Privacy Enhancing Technologies. (Link)] put a number on what that costs: comparing syntactic list matching against dynamic taint tracking request by request over the same crawl, they estimate 16%–19% of the list's own matches are false positives, rising to 27%–30% among requests only the list flagged, and find 7,021 requests (≈17% of their 40,605) that only taint tracking saw. Treat a filter-list hit as a noisy label with error bars in the high teens. Say so in your paper.
What to Read First
- Who Filters the Filters? [2Snyder, Peter; Vastel, Antoine; Livshits, Ben (2020): "Who Filters the Filters: Understanding the Growth, Usefulness and Efficiency of Crowdsourced Ad Blocking", Proc. ACM Meas. Anal. Comput. Syst. 4(2). (DOI) (Link)] — the measurement of how much of EasyList is dead weight: 90.16% of its resource-blocking rules provided no benefit in common browsing. Published at SIGMETRICS, outside this corpus's seven venues, and still the reference for “the list grows and never shrinks”.
- Missed by Filter Lists [3Fouad, Imane; Bielova, Nataliia; Legout, Arnaud; Sarafijanovic-Djukic, Natasa (2020): "Missed by Filter Lists: Detecting Unknown Third-Party Trackers with Invisible Pixels", in: Proceedings on Privacy Enhancing Technologies, pp. 499-518. (DOI)] — the reference for what a list does not catch, measured behaviourally rather than against another list.
- From Syntactic Matching to Taint Tracking and Back [1Calzavara, Stefano; Casarin, Samuele; Squarcina, Marco; Maffei, Matteo (2026): "From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques", in: Proceedings on Privacy Enhancing Technologies. (Link)], PoPETs 2026 — the only head-to-head evaluation of list matching against an independent detector, and the source of the false-positive estimate above. One study, one taint-tracking browser, 7,614 sites: read it as the best available number, not as a settled one.
- Understanding Regional Filter Lists [4Böttger, Christian; Demir, Nurullah; Hörnemann, Jan; Acharya, Bhupendra; Pohlmann, Norbert; Holz, Thorsten; Grosse-Kampmann, Matteo; Urban, Tobias (2025): "Understanding Regional Filter Lists: Efficacy and Impact", in: Proceedings on Privacy Enhancing Technologies, pp. 309-325. (DOI)], PoPETs 2025 — the only systematic study of what the non-anglophone lists add, and the reason the section below exists.
- Blocking Tracking JavaScript at the Function Granularity [5Amjad, Abdul Haddi; Munir, Shaoor; Shafiq, Zubair; Gulzar, Muhammad Ali (2024): "Blocking Tracking JavaScript at the Function Granularity", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)], CCS 2024 — read §4.4 specifically. It states the precision assumption the whole field runs on (“a network request labeled as tracking by filter lists is actually tracking — as experts vet each rule”) and then, in its evaluation, gets list authors to confirm on GitHub that some tracking scripts are deliberately not blocked because blocking them breaks pages. Absence from a list is sometimes a policy decision, not an oversight — which is the deepest reason “not on the list” cannot mean “not a tracker”.
What a Filter List Is, for a Measurement
Three properties decide whether a list can answer your question at all. None of them is about syntax; the syntax is documented by the list maintainers and there is no reason to restate it here.
1. Most of a list is not about requests
Rules split into network rules (stop the request), cosmetic rules (hide an element that already loaded, expressed as a CSS-superset selector) and exception rules (@@, un-block something a network rule would have caught). Only network rules can answer “would this request have been blocked”, and the split is not what people assume.
Measured live at 2026-08-29 13:20 UTC by the script in Recording Which List You Used (its unedited output is in that section). These are one snapshot of a moving artefact — the EasyList row was 54,731 twenty-four minutes earlier:
| List | Network | Cosmetic | Exception | What that means |
|---|---|---|---|---|
| EasyList | 54,748 | 24,512 | 758 | Nearly a third of it cannot answer a request question |
| EasyPrivacy | 55,100 | 33 | 836 | Effectively all network — this is the tracking list |
| EasyList Cookie List | 1,674 | 23,057 | 428 | Inverted: hiding a banner is a rendering problem |
| AdGuard URL-tracking (filter 17) | 2,520 | 2 | 91 | Purpose-built for link decoration |
| Peter Lowe's list | 3,530 | 0 | 0 | Domain-level only; high precision, low recall |
Exception rules are the part people silently drop. EasyList carries 758 and EasyPrivacy 836. An engine that evaluates them and a script that greps for rule strings will not agree, and the grep will over-count blocks with no error message.
2. A rule is evaluated against a request //in context//, not against a URL
$third-party, $domain=, the resource-type options ($script, $image, $xmlhttprequest, $sub_frame, …) and @@ exceptions all depend on where the request came from and what kind of thing it is. Brave's engine says so in its own constructor signature — Request::new(url, source_url, request_type, method).2)
So a crawl that logged only request URLs cannot be post-processed with a list, and it will fail silently rather than error. Record, per request:
- the request URL;
- the initiator or document URL of the frame that issued it — without this every
$third-partyand$domain=modifier evaluates against nothing; - the resource type, which CDP and Playwright both expose (
resourceType()); - the redirect chain, because a rule may match a hop you did not keep;
- and then actually evaluate the exception rules.
The crawler page compares which libraries expose each of these. Cosmetic filters are a separate matter: modern cosmetic syntax is a superset of CSS — procedural filters such as `:has-text()`, and HTML filtering (##^) — so do not try to evaluate them with your automation library's selector engine. Use the cosmetic API of the Ghostery or Brave engine to resolve selectors for a hostname first, then query with those.
3. The list you downloaded is not the list you downloaded ten minutes ago
EasyList publishes both a Version: and the exact Commit: that produced the file, and it changes several times an hour. Three fetches of the same URL on 2026-08-29, ten minutes apart, produced by the check script on the provenance page:
| Fetched (UTC) | Version: the file declares | Commit: | Network rules | sha256 (12) |
|---|---|---|---|---|
| 12:56 | 202608291231 | 304d779d6e53 | 54,731 | 015a6f8f1310 |
| 13:06 | 202608291255 | 722b6a02c822 | 54,733 | a4c232235a24 |
| 13:16 | 202608291255 | 722b6a02c822 | 54,733 | a4c232235a24 |
Twenty minutes, two different builds, two different rule counts, two different hashes. Recording the Version: and Commit: is necessary; archiving the bytes is what actually makes you reproducible, because a Version: string is only resolvable while the maintainers keep the history and the CDN in front of easylist.to does not guarantee two requests agree.
Seventeen days earlier the same list carried 52,557 network rules — +4.1% in 17 days.3) “We used EasyList” identifies nothing.
Which Lists Exist
If you want the short answer: load EasyList and EasyPrivacy, add the regional lists your population needs, and add AdGuard's CNAME list if — and only if — your crawl recorded DNS resolution. That is what the field does: 56.6% of the list-using papers below name EasyList and 35.9% name EasyPrivacy. Everything else in this table is a reference for when that default is wrong for your question — a domain-level comparison point, a cookie-notice ruleset, an entity map, or a list that is dead and should not appear in a 2026 paper.
Who maintains this, and what that implies
The instrument is crowd-maintained, and its shape follows from that. The EasyList repository has 326 contributors, roughly 290,000 commits (289,674 at the moment of checking) and 9,038 closed issues as of 2026-08-29.4) Three consequences you will meet in your data:
- Coverage tracks attention, not prevalence. Widely-deployed trackers have precise, current rules; the long tail does not. This is the mechanism behind every row of Coverage Holes, Measured, and the reason a non-English or non-desktop population is under-measured by the default lists.
- Rules accumulate and are rarely retired. Snyder et al. [2Snyder, Peter; Vastel, Antoine; Livshits, Ben (2020): "Who Filters the Filters: Understanding the Growth, Usefulness and Efficiency of Crowdsourced Ad Blocking", Proc. ACM Meas. Anal. Comput. Syst. 4(2). (DOI) (Link)] measured 90.16% of EasyList's resource-blocking rules as providing no benefit in common browsing, and Böttger et al. [4Böttger, Christian; Demir, Nurullah; Hörnemann, Jan; Acharya, Bhupendra; Pohlmann, Norbert; Holz, Thorsten; Grosse-Kampmann, Matteo; Urban, Tobias (2025): "Understanding Regional Filter Lists: Efficacy and Impact", in: Proceedings on Privacy Enhancing Technologies, pp. 309-325. (DOI)] reproduced the shape of that on regional lists five years later. A rule count is not a coverage measure.
- Some rules are short-lived by design, because the maintainers are in an arms race with the sites they block. A list six months old is not a slightly worse version of today's list; it is a different instrument, and the difference is concentrated exactly on the sites people argue about.
The lists
Status checked 2026-08-29 against the primary source in each row — the list's own canonical URL, or the GitHub API for repository state. Nothing here comes from a vendor blog or a listicle. Filter lists die quietly, and a dead list in a live crawl is a silent measurement error, so re-run external_checks_filter_lists.sh (on the provenance page, with its unedited output) rather than trusting this table's date.
| List | What it is for | Status, 2026-08-29 |
|---|---|---|
| EasyList | Advertisements, except first-party self-promotion. Full policy | Active, pushed 13:11 UTC the day this was checked. Version: and Commit: in the header |
| EasyPrivacy | Tracking and privacy. Its policy sorts every block into four categories, verbatim: “Generic blocks (common URL/tracking filter patterns) used by 1st/3rd-parties”; “1st-party tracking. Self-hosted trackers and CNAME trackers”; “3rd-party tracking. Hosted by another provider, which hosts a tracking script, but not actually a tracking company”; “Tracking-servers. Where the server has only one purpose to track/analyze user, will be blocked at the url level”5) | Active |
| Disconnect tracking protection | Tracker domains grouped by company and category; also the entities.json entity map | Active (pushed 2026-08-28). CC BY-NC-SA 4.0 — read the LICENSE file before redistributing; it is not permissive.6) Firefox does not consume this repo directly — it ships the Safe-Browsing-format build from shavar-prod-lists (pushed 2026-08-27) |
| DuckDuckGo Tracker Radar | Automatically constructed tracker domains with company attribution, prevalence, fingerprinting and cookie signals. Data model | Active (pushed 2026-08-28). The derived blocklist is duckduckgo/tracker-blocklists — note the plural; the singular name returns 404 |
| Ghostery WhoTracks.me | Tracker prevalence dataset over the top sites, with company attribution | Active (repo pushed 2026-08-04, MIT). Both URLs moved: whotracks.me redirects to ghostery.com/whotracksme, and the repository is whotracksme/whotracks.me |
| AdGuard filters | Ads, tracking, annoyances, and a separate URL-tracking filter | Active (pushed 2026-08-29, GPL-3.0). GitHub Releases is empty — the canonical download is filters.adtidy.org/<platform>/filters/<N>.txt, whose header carries Version, TimeUpdated and Expires. The ID-to-list registry is FiltersRegistry. The base filter (ID 2) is 79,406 network and 51,193 cosmetic rules — larger than EasyList on both counts |
| Peter Lowe's list | Ad and tracking servers, domain-level, deliberately small | Active: 3,530 entries, Last-Modified: Sat, 29 Aug 2026 11:35:42 GMT. A useful high-precision, low-recall comparison point |
| AdGuard CNAME disguised trackers | The one list for the problem that defeats hostname matching: trackers reached through a first-party CNAME [6Dimova, Yana; Acar, Gunes; Olejnik, Lukasz; Joosen, Wouter; Van Goethem, Tom (2021): "The CNAME of the game: Large-scale analysis of DNS-based tracking evasion", Proceedings on Privacy Enhancing Technologies 2021:394–412. (DOI) (Link)] | Active (pushed 2026-08-17, MIT) — data/combined_disguised_trackers.txt, 224,830 lines on 2026-08-29. You cannot use it from request logs alone: you need the CNAME chain, which means recording DNS resolution at crawl time. Most crawlers do not, by default |
| CMP interaction rulesets — autoconsent, Consent-O-Matic, I Still Don't Care About Cookies | Not Adblock-syntax filter lists: JavaScript rule sets that click a consent banner rather than block a request | Compared, dated and status-checked on Granting consent to websites, which is where a banner-clicking decision belongs; keeping a second copy of their statuses here would only rot. One that page does not carry: Firefox's mozilla/cookie-banner-rules-list is archived on GitHub (last push 2025-01-07) — note the org, mozilla-extensions/ 404s — so do not start there |
| justdomains | Not a list: a domain-only re-encoding of EasyList, EasyPrivacy, AdGuard DNS and others | Active as a conversion layer (HTTP 200). Cite the upstream list, not this. Three papers in this corpus label cookies with it |
| EasyList Cookie List | CSS selectors for cookie notices. Lives in the main easylist repo under easylist_cookie/ | Active (Last modified: 2026-08-29 12:50 UTC). No Version: field, only Last modified: — so record the date and the hash |
| hpHosts / Malwarebytes ATS | Historic hosts-file ad/tracking list | Dead. hosts-file.net still has a DNS record but HTTPS to it timed out on 2026-08-29; Malwarebytes stopped updating around 2020. It appears in older papers. 27 papers in this corpus used a hosts-file list of some kind, but that family also contains live ones (Pi-hole, NoTrack), so the 27 is not 27 papers using a dead list — read the hosts-file row in Which lists below |
| DNS-blocking lists generally | Domain-level, no path granularity | See Website classification, and the smart-TV row in Coverage Holes, Measured |
Regional and Non-English Lists
The anglophone core is a sampling decision that nobody declares. EasyList and EasyPrivacy target what Sjösten et al. [7Sjösten, Alexander; Snyder, Peter; Pastor, Antonio; Papadopoulos, Panagiotis; Livshits, Benjamin (2020): "Filter List Generation for Underserved Regions", in: Proceedings of the ACM Web Conference. (DOI)] call “global” sites, “which in practice means either websites in English, or resources popular enough to appear on English-speaking sites in addition to sites targeting speakers of other languages”. If your population is a national top list, a non-English corpus, or a geographically diverse crawl, EasyList alone under-measures it, and the size of the gap is not a footnote.
Two papers in the whole 5,859-paper corpus are about regional lists. That is the finding: this is a systematically under-studied dependency of a very large literature.
- Sjösten et al. [7Sjösten, Alexander; Snyder, Peter; Pastor, Antonio; Papadopoulos, Panagiotis; Livshits, Benjamin (2020): "Filter List Generation for Underserved Regions", in: Proceedings of the ACM Web Conference. (DOI)], TheWebConf 2020, generated rules automatically for three under-served regions and produced 1,310 new rules identifying 1,771 advertising URLs missed by existing lists, blocking 27.1% more advertising resources than the existing lists alone.
- Böttger et al. [4Böttger, Christian; Demir, Nurullah; Hörnemann, Jan; Acharya, Bhupendra; Pohlmann, Norbert; Holz, Thorsten; Grosse-Kampmann, Matteo; Urban, Tobias (2025): "Understanding Regional Filter Lists: Efficacy and Impact", in: Proceedings on Privacy Enhancing Technologies, pp. 309-325. (DOI)], PoPETs 2025, is the efficacy study. Across their crawl profiles, of 122,548 distinct rules in the regional lists they tested, only 8,163 (6.6%) identified at least one tracking request — the Snyder result, reproduced on regional lists five years later. A “master list” rebuilt from just those 8,163 rules identified 9,650,332 (83%) more trackers than their baseline list.7)
The regional lists are real, maintained, and roughly the size you would want. Measured 2026-08-29 with the same script as above:
| List | Network | Cosmetic | Exception | Header |
|---|---|---|---|---|
| EasyList China | 11,377 | 6,935 | 986 | Version: 202608291312, Expires: 1 days |
| EasyList Germany | 2,149 | 3,650 | 164 | Version: 202608271302, with a Commit: field |
| Liste FR | 9,892 | 3,545 | 157 | Version: 202608291312 |
Note that EasyList China carries more than five times EasyList Germany's network rules; these are not interchangeable increments on a common base, and there is no reason to expect them to behave alike. The full index is at easylist.to (HTTP 200, 2026-08-29).
What to do about it. If your crawl visits sites in languages other than English, load the matching regional lists, say which, and report your results both with and without them. If you cannot, say that the anglophone lists are your instrument and treat non-English results as a lower bound — that is the standard defensible framing. What is not defensible is a per-country tracking comparison built on EasyList alone, because the instrument's sensitivity varies with the thing being compared.
Recording Which List You Used
Of the 178 papers in this corpus that name a filter list as a tool they used, 53 (29.8%) attach any version or date, and only 4 (2.2%) give something that identifies the actual rules — a list Version: string or a commit hash. The rest is “EasyList”, or a bare year. Some of the 53 do better than that — EasyList :: 2024-08-17 and EasyList :: 2021-07-05 come close to identifying a daily build — but a date is not the Version: the list itself publishes. Given that the list publishes its own commit and changes several times an hour, this is the single largest reproducibility gap in this literature.
The four that got it right, and the form to copy:
| Paper | What it recorded |
|---|---|
| Matte et al. [8Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)], IEEE S&P 2020 | Disconnect list, commit eb817fb1 (2019-12-10) |
| Demir et al. [9Demir, Nurullah; Hörnemann, Jan; Große-Kampmann, Matteo; Urban, Tobias; Pohlmann, Norbert; Holz, Thorsten; Wressnegger, Christian (2023): "On the Similarity of Web Measurements Under Different Experimental Setups", in: Proceedings of the ACM Internet Measurement Conference, pp. 356-369. ACM DOI 10.1145/3618257.3624795 is listed by DBLP but was not registered with the DOI resolver as of 2026-08-12; the DOI above resolves to the authors' institutional record of the same paper (DOI)], IMC 2023 | EasyList 202203300945 |
| Not Your Average App, PoPETs 20238) | EasyList 202105250854 |
| Li et al. [10Wang, Xinzhe; Zhuang, Zeyang; Meng, Wei; Cheng, James (2024): "Detecting and Understanding Self-Deleting JavaScript Code", in: Proceedings of the ACM Web Conference. (DOI)], TheWebConf 2024 | EasyList 202306271740 with EasyPrivacy |
A version is not enough on its own — archive the bytes. A Version: string is only resolvable while the maintainers keep the history; the .txt you actually matched against is the artefact. Run this at the start of the crawl, not when you write the paper, and put the JSON and the raw lists in your artefact.
- filterlist_provenance.py
#!/usr/bin/env python3 """Record exactly which filter list you used, so your crawl is reproducible. Filter lists change several times a day. "We used EasyList" is not a method; "EasyList, Version 202608291255, commit 722b6a02, 54,733 network rules" is. Every Adblock-Plus-syntax list carries that metadata in its own header comments -- this script extracts it, counts the rules by kind, and writes a JSON record you can archive next to your crawl data and paste into your methodology section. Run it at the START of a crawl, not when you write the paper. python3 filterlist_provenance.py > filterlists.json python3 filterlist_provenance.py --save lists/ # also archive the raw .txt """ import argparse import hashlib import json import pathlib import re import sys import urllib.request from datetime import datetime, timezone # The lists a tracking measurement usually wants. The anglophone core is the # first block; if your crawl visits sites in any other language, the second # block is not optional -- see the regional-lists section of the page. LISTS = { "easylist": "https://easylist.to/easylist/easylist.txt", "easyprivacy": "https://easylist.to/easylist/easyprivacy.txt", "easylist-cookie": "https://secure.fanboy.co.nz/fanboy-cookiemonster.txt", "adguard-url-tracking": "https://filters.adtidy.org/windows/filters/17.txt", "peter-lowe": "https://pgl.yoyo.org/adservers/serverlist.php" "?hostformat=adblockplus&showintro=0&mimetype=plaintext", # Regional. Add the ones your population needs and delete the rest; the # full index is at easylist.to/pages/other-supplementary-filter-lists-and- # easylist-variants.html "easylist-china": "https://easylist-downloads.adblockplus.org/easylistchina.txt", "easylist-germany": "https://easylist.to/easylistgermany/easylistgermany.txt", "liste-fr": "https://easylist-downloads.adblockplus.org/liste_fr.txt", } # Header fields Adblock-syntax lists publish about themselves. Not every list # sets every field; a missing field is reported as None rather than guessed. HEADER_FIELDS = ("Version", "Last modified", "TimeUpdated", "Expires", "Commit", "Title") # A cosmetic rule hides an element that has already loaded; a network rule stops # the request. Only network rules answer "would this request have been blocked". # Note the order in classify(): a cosmetic *exception* (`site.com#@#.ad`) is # counted as cosmetic, not as an exception, because the question this count # answers is "how much of this list is about requests at all". COSMETIC = re.compile(r"#[@?$]?#|#\$#") def classify(line): if not line.strip() or line.startswith("!") or line.startswith("["): return "comment" if COSMETIC.search(line): return "cosmetic" if line.startswith("@@"): return "exception" return "network" def describe(name, url): req = urllib.request.Request(url, headers={"User-Agent": "filterlist-provenance/1.0"}) with urllib.request.urlopen(req, timeout=60) as resp: raw = resp.read() text = raw.decode("utf-8", errors="replace") lines = text.split("\n") header = {} for field in HEADER_FIELDS: m = re.search(rf"^!\s*{re.escape(field)}:\s*(.+)$", text[:8000], re.M) header[field] = m.group(1).strip() if m else None counts = {"comment": 0, "cosmetic": 0, "exception": 0, "network": 0} for line in lines: counts[classify(line)] += 1 return { "name": name, "url": url, "fetched_at": datetime.now(timezone.utc).isoformat(timespec="seconds"), "sha256": hashlib.sha256(raw).hexdigest(), "bytes": len(raw), "header": header, "rules": counts, }, raw def main(): ap = argparse.ArgumentParser() ap.add_argument("--save", metavar="DIR", help="also write the raw list files here") args = ap.parse_args() out = [] for name, url in LISTS.items(): try: record, raw = describe(name, url) except Exception as exc: # Fail loud: a list you could not fetch is a hole in your method, # not something to paper over with a stale local copy. print(f"FAILED {name} <{url}>: {exc}", file=sys.stderr) raise out.append(record) if args.save: d = pathlib.Path(args.save) d.mkdir(parents=True, exist_ok=True) (d / f"{name}.txt").write_bytes(raw) # Not every list sets `Version:`; EasyList Cookie List and Peter Lowe's # list only set `Last modified:`. Report whichever exists, and say so. stamp = ( record["header"]["Version"] or record["header"]["TimeUpdated"] or record["header"]["Last modified"] or "(no version or date in header)" ) print( f"{name:22} {stamp:24}" f" network={record['rules']['network']:7} cosmetic={record['rules']['cosmetic']:7}" f" exception={record['rules']['exception']:6} sha256={record['sha256'][:12]}", file=sys.stderr, ) json.dump(out, sys.stdout, indent=2) print(file=sys.stdout) if __name__ == "__main__": main()
Real output, 2026-08-29 (this is the run every rule count on this page comes from):
easylist 202608291320 network= 54748 cosmetic= 24512 exception= 758 sha256=0a7e9bb32f61 easyprivacy 202608291311 network= 55100 cosmetic= 33 exception= 836 sha256=fb65e3df3f1a easylist-cookie 2026-08-29 12:50 UTC network= 1674 cosmetic= 23057 exception= 428 sha256=e087b8c3dc50 adguard-url-tracking 2.0.14.1 network= 2520 cosmetic= 2 exception= 91 sha256=7578d8eb0e3e peter-lowe Sat, 29 Aug 2026 11:35:42 GMT network= 3530 cosmetic= 0 exception= 0 sha256=f66a0e3b3bfb easylist-china 202608291312 network= 11377 cosmetic= 6935 exception= 986 sha256=1fbf4336fdad easylist-germany 202608271302 network= 2149 cosmetic= 3650 exception= 164 sha256=1528a89f4222 liste-fr 202608291312 network= 9892 cosmetic= 3545 exception= 157 sha256=0ac7e76212d1
Applying a List
Post-processing beats blocking at crawl time
Run the crawl allowing everything, then classify. You can re-classify with a different list, or a different version of the same list, without re-crawling — which you cannot do if you blocked at request time. You also avoid changing the page you are measuring: a blocked resource changes what the page loads next, so a blocking crawl and an allowing crawl are not measuring the same web.
Engine maintenance status checked 2026-08-29 against the npm, PyPI and crates.io registries and the GitHub API. This is the section of the page that rots fastest.
| Library | Language | Status, 2026-08-29 | Use it? |
|---|---|---|---|
| brave/adblock-rust | Rust | Active (pushed 2026-08-26, MPL-2.0). The crate is named adblock, not adblock-rust — v0.13.3, published 2026-08-20 | Yes. Brave ships it, so it tracks uBlock-era syntax including $removeparam |
adblock-rs | Node | Active, v0.13.3 published 2026-08-20, tracks the Rust crate 1:1 | Yes, if you are in Node |
| @ghostery/adblocker | TypeScript/Node | Active, v2.18.2 published 2026-08-05 (repo pushed 2026-08-28). Renamed: @cliqz/adblocker is deprecated on npm, last published 2024-10-16 | Yes. Ghostery's own engine |
adblock (PyPI, ArniDagur/python-adblock) | Python | Stale: v0.6.0, uploaded 2022-07-17; repo last pushed 2023-03-28. Wraps an old adblock-rust | Only with a pinned, stated version |
braveblock (PyPI) | Python | Stale: v0.5.1, uploaded 2024-02-14 | Only with a pinned, stated version |
| abp-blocklist-parser | Python | Abandoned: last push 2020-11-02 | No. It predates $removeparam and most modern rule options |
| adblockparser | Python | Archived on GitHub (2019); PyPI v0.7 from 2016-10-17 | No — and nine papers in this corpus used it |
There is still no actively maintained Python binding to a modern filter-list engine, as of 2026-08-29. Both PyPI wrappers around Brave's engine are years behind the Rust crate (0.6.0 and 0.5.1 against 0.13.3), and the two pure-Python parsers are abandoned. If your pipeline is Python and your claim depends on rule semantics, either shell out to the Rust or Node engine, or state the parser version and accept that unsupported rule options are silently not matched. This is a real threat to validity and papers do not usually mention it.
Before you crawl at all: someone may already have. HTTP Archive runs a monthly request-level crawl of millions of pages and publishes it as a public BigQuery dataset, and the Web Almanac's Privacy chapter is that measurement joined against a tracker catalogue. Read the chapter's own method, not this sentence: the 2025 Privacy chapter identifies trackers with the WhoTracks.Me catalogue, and the 2024 one joined WhoTracks.me and AdGuard's CNAME-tracker list — so the two editions do not have the same recall. The Third Parties chapter answers a different question again and categorises with Patrick Hulce's third-party-web repository rather than with any filter list, in both editions.9) Its limits are real and you must state them: it loads the landing page, does not interact, and carries no consent state. But if your question is prevalence or a longitudinal trend rather than behaviour under interaction, your own crawl may be the expensive way to get a worse answer.
If your instrument is a browser extension: Manifest V3 caps the rules
“Install a blocker and see what it blocks” is now constrained by a documented rule budget rather than by engineering. Chrome's declarativeNetRequest limits, from the API reference read on 2026-08-29:10)
GUARANTEED_MINIMUM_STATIC_RULES= 30,000 rules across the enabled static rulesets (MAX_NUMBER_OF_ENABLED_STATIC_RULESETS= 50);MAX_NUMBER_OF_REGEX_RULES= 1,000 regular-expression rules of each type, each under 2 KB once compiled. The documentation's own words: “the total number of regular expression rules of each type cannot exceed 1000”.
EasyList alone is 54,748 network rules and EasyPrivacy 55,100. Neither fits in the 30,000-rule static guarantee, let alone both, so an MV3 extension ships a subset chosen by its authors — which is what uBlock Origin Lite is, and why it is not feature-equivalent to uBlock Origin.11)
Firefox has its own caps and they are not Chrome's. MDN documents the same constant names but records the dynamic and session limits changing at Chrome 120 and Firefox 128 independently, so the values are per-browser and per-version.12) If your measurement compares blockers across browsers, read the constants at runtime and report them — the rule budget is a confound, not a constant.
Lukić and Papadopoulos [11Lukić, Karlo; Papadopoulos, Lazaros (2026): "Privacy vs. Profit: The Impact of Google's Manifest Version 3 (MV3) Update on Ad Blocker Effectiveness", in: Proceedings on Privacy Enhancing Technologies. (Link)] measured whether this degrades blocking and found no significant reduction in ad blocking and a significant increase in anti-tracking between MV2 and MV3 builds of four popular blockers, though MV3 left cosmetic placeholders in 21% of cases where MV2 left none. The blocking survived; whether an MV3 extension is a sound measurement instrument is a different question and it is not settled. If your method depends on the extension seeing every request, post-process a full crawl with the Rust or Node engine instead, where no rule cap applies.
Coverage Holes, Measured
You will be asked this in review, so have the numbers. Two things are being measured here and they are not the same: false negatives (the list does not know about a tracker) and bypasses (the rule exists and matches, and the request happens anyway).
False negatives, by where you point the list
The list is an anglophone desktop-web instrument. Every step away from that costs recall, and the cost has been measured:
| Where | Study | What the lists missed |
|---|---|---|
| Desktop web, behavioural reference | Fouad et al. [3Fouad, Imane; Bielova, Nataliia; Legout, Arnaud; Sarafijanovic-Djukic, Natasa (2020): "Missed by Filter Lists: Detecting Unknown Third-Party Trackers with Invisible Pixels", in: Proceedings on Privacy Enhancing Technologies, pp. 499-518. (DOI)], PETS 2020 | EasyList+EasyPrivacy missed 25.22% and Disconnect 30.34% of the trackers detected by invisible-pixel-seeded behavioural analysis |
| Desktop web, taint-tracking reference | Calzavara et al. [1Calzavara, Stefano; Casarin, Samuele; Squarcina, Marco; Maffei, Matteo (2026): "From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques", in: Proceedings on Privacy Enhancing Technologies. (Link)], PoPETs 2026 | 7,021 requests (≈17% of 40,605) found only by taint tracking |
| Desktop web, JS-behaviour reference | Chen et al. [12Chen, Quan; Snyder, Peter; Livshits, Ben; Kapravelos, Alexandros (2021): "Detecting Filter List Evasion with Event-Loop-Turn Granularity JavaScript Signatures", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)], IEEE S&P 2021 | 3,589 scripts with behaviour the lists blocked elsewhere, on 12.48% of sites |
| Desktop web, packet-metadata reference | Lee et al. [13Lee, Dongkeun; Joo, Minwoo; Lee, Wonjun (2023): "Net-track: Generic Web Tracking Detection Using Packet Metadata", in: Proceedings of the ACM Web Conference. (DOI)], TheWebConf 2023 | 34.5% of the classifier's apparent false positives were real trackers the lists had not found |
| Desktop web, deployable ML | Lee et al. [14Lee, Kiho; Lim, Chaejin; Jin, Beomjin; Kim, Taeyoung; Kim, Hyoungshick (2024): "AdFlush: A Real-World Deployable Machine Learning Solution for Effective Advertisement and Web Tracker Prevention", in: Proceedings of the ACM Web Conference. (DOI)], TheWebConf 2024 | 642 ads and trackers across 108 domains, confirmed and reported upstream |
| Desktop web, differential testing | Shuang et al. [15Shuang, He; Zhao, Lianying; Lie, David (2025): "Duumviri: Detecting Trackers and Mixed Trackers with a Breakage Detector", in: Proceedings of the Network and Distributed System Security Symposium. (Link)], NDSS 2025 | 22 previously unreported trackers (175 occurrences) in one evaluation set |
| Mobile apps | NoMoAds [16Shuba, Anastasia; Markopoulou, Athina; Shafiq, Zubair (2018): "NoMoAds: Effective and Efficient Cross-App Mobile Ad-Blocking", in: Proceedings on Privacy Enhancing Technologies. (DOI)], PETS 2018 | EasyList failed to detect 37% of ad requests in their app dataset |
| Mobile apps | NoMoATS [17Shuba, Anastasia; Markopoulou, Athina (2020): "NoMoATS: Towards Automatic Detection of Mobile Tracking", in: Proceedings on Privacy Enhancing Technologies. (DOI)], PETS 2020 | Of 37,438 requests, 2,963 (7.91%) were advertising/tracking requests no filter list (EasyList, EasyPrivacy, MoaAB) detected |
| Smart TVs | Varmarken et al. [18Varmarken, Janus; Le, Hieu; Shuba, Anastasia; Markopoulou, Athina; Shafiq, Zubair (2020): "The TV is Smart and Full of Trackers: Measuring Smart TV Advertising and Tracking", in: Proceedings on Privacy Enhancing Technologies. (DOI)], PETS 2020 | Four DNS blocklists on smart-TV testbed traffic: the best of them (Firebog) blocked only 22% and 27% of the distinct FQDNs contacted |
| Web3 / long tail | Torres et al. [19Ferreira Torres, Christof; Willi, Fiona; Shinde, Shweta (2023): "Is Your Wallet Snitching On You? An Analysis on the Privacy Implications of Web3", in: 32nd USENIX Security Symposium (USENIX Security 23). (Link)], USENIX Sec 2023 | Five blocklists combined blocked 60 of 108 (56%) of the third parties on Web3 sites |
| Cryptomining | Rüth et al. [20Rüth, Jan; Zimmermann, Torsten; Wolsing, Konrad; Hohlfeld, Oliver (2018): "Digging into Browser-based Crypto Mining", in: Proceedings of the ACM Internet Measurement Conference. (DOI)], IMC 2018 | Up to 82% of mining sites identified by WebAssembly fingerprinting were not detected by block lists |
| Push / Service Workers | Subramani et al. [21Subramani, Karthika; Yuan, Xingzi; Setayeshfar, Omid; Vadrevu, Phani; Lee, Kyu Hyung; Perdisci, Roberto (2020): "When Push Comes to Ads: Measuring the Rise of (Malicious) Push Advertising", in: Proceedings of the ACM Internet Measurement Conference. (DOI)], IMC 2020 | Two popular blockers blocked zero ad-network Service Worker registrations; EasyList caught under 2% of the requests those workers then issued |
Nothing in this table is a criticism of the lists. They are maintained for browsing, by volunteers, on the web people browse. It is a statement about the instrument's sensitivity: if you point it anywhere other than the anglophone desktop web, report your recall or state that you did not measure it.
Bypasses: the rule matches and the request happens anyway
- Local frames [22Ukani, Alisha; Haddadi, Hamed; Snoeren, Alex C.; Snyder, Peter (2025): "Local Frames: Exploiting Inherited Origins to Bypass Content Blockers", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security, pp. 1349-1363. (DOI)], CCS 2025: on the 12,234 of 21,965 crawled sites that use local frames (
about:blank,srcdoc, blob), 73.7% of the URLs those frames requested should have been blocked by EasyList + EasyPrivacy + uBlock Origin lists and were not, because content blockers mishandle inherited origins. Nineteen distinct vulnerabilities across the blockers tested. If you post-process request logs with an engine you will count these as blocked; a live blocking crawl will not. - CNAME cloaking [6Dimova, Yana; Acar, Gunes; Olejnik, Lukasz; Joosen, Wouter; Van Goethem, Tom (2021): "The CNAME of the game: Large-scale analysis of DNS-based tracking evasion", Proceedings on Privacy Enhancing Technologies 2021:394–412. (DOI) (Link)]: a tracker reached through a first-party CNAME defeats hostname matching entirely. The AdGuard CNAME list exists for this and needs your crawl to have recorded DNS resolution.
- Deliberate non-blocking. NoT.js [5Amjad, Abdul Haddi; Munir, Shaoor; Shafiq, Zubair; Gulzar, Muhammad Ali (2024): "Blocking Tracking JavaScript at the Function Granularity", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)] found ten cases in a sample of fifty that EasyList/EasyPrivacy either miss or cannot handle, and reported them to the list authors — who confirmed via GitHub issues that some of them, the mixed scripts, are knowingly not blocked because blocking them breaks pages. So “not on the list” can mean “on the list's do-not-break register”, and you cannot tell which from the list alone.
And the direction people read backwards
AdFlush [14Lee, Kiho; Lim, Chaejin; Jin, Beomjin; Kim, Taeyoung; Kim, Hyoungshick (2024): "AdFlush: A Real-World Deployable Machine Learning Solution for Effective Advertisement and Web Tracker Prevention", in: Proceedings of the ACM Web Conference. (DOI)] and the filter lists it was compared against flagged almost exactly the same volume of traffic — 39.27% versus 39.92% of all requests — and the paper reads that as evidence AdFlush “can effectively serve as a substitute for filter lists”. The same paper reports 642 ads and trackers on 108 domains that the lists had missed. Both are true, and together they are the point: equal marginals are not equal sets. If you compare a classifier against a list, report the confusion matrix, not the two totals.
The List as Ground Truth, and Why That Is Circular
“Blocked ⇒ tracker” is a definition, not a finding. A filter list is a normative artefact: a rule exists because a volunteer decided this resource should not load, weighed against how much blocking it breaks. Scoring a classifier against it measures agreement with that decision, not accuracy about tracking — and reporting the disagreements as error discards exactly the cases that would have been discoveries. Two published results make this concrete rather than philosophical: 16%–19% of the list's matches are estimated false positives [1Calzavara, Stefano; Casarin, Samuele; Squarcina, Marco; Maffei, Matteo (2026): "From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques", in: Proceedings on Privacy Enhancing Technologies. (Link)] — one study, one taint-tracking browser, 7,614 sites — and some true trackers are deliberately absent because blocking them breaks pages [5Amjad, Abdul Haddi; Munir, Shaoor; Shafiq, Zubair; Gulzar, Muhammad Ali (2024): "Blocking Tracking JavaScript at the Function Granularity", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)].
The practice is not confined to request classifiers. 96 papers in this corpus name a filter list as the groundTruthSource for a classification step, across twelve different kinds of object — requests, domains, cookies, scripts, IP addresses, website categories, privacy policies, consent notices, network traffic, even email messages. The list has become the field's general-purpose definition of “advertising or tracking”, far outside what it was written to describe.
The clearest recent examples, each verified against the paper's own text:
- CookieGraph [23Munir, Shaoor; Siby, Sandra; Iqbal, Umar; Englehardt, Steven; Shafiq, Zubair; Troncoso, Carmela (2023): "CookieGraph: Understanding and Detecting First-Party Tracking Cookies", pp. 3490–3504. Association for Computing Machinery, New York, NY, USA. (DOI) (Link)], CCS 2023 labels a cookie by the provenance of the script that set it: “if a script that sets a cookie is not marked by any of the filter lists, we label these cookies as Non-ATS. Conservatively, if any one of the filter lists marks the cookie's setter as ATS, we label the cookie as Unknown”.. It then adds Cookiepedia as a second, independent label source, and treats its self-declared purposes conservatively. That combination — filter-list provenance plus a CMP-maintained label database — is the strongest published approach to cookie labelling, and a real improvement on scoring the list against itself. It is one paper, and it rests on Cookiepedia, which nobody in this corpus has audited.
- NoT.js [5Amjad, Abdul Haddi; Munir, Shaoor; Shafiq, Zubair; Gulzar, Muhammad Ali (2024): "Blocking Tracking JavaScript at the Function Granularity", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)], CCS 2024 labels a JavaScript function by whether the network requests it participates in match EasyList/EasyPrivacy, calling the result “a conservative ground truth” in which mixed-behaviour functions (3.9% of it) are labelled non-tracking.
- SugarCoat [24Smith, Michael; Snyder, Peter; Livshits, Benjamin; Stefan, Deian (2021): "SugarCoat: Programmatically Generating Privacy-Preserving, Web-Compatible Resource Replacements for Content Blocking", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)], CCS 2021 takes both the tracking labels and the breakage signal from list artefacts — rules and exception rules.
- Read Between the Lines [25Ghasemisharif, Mohammad; Polakis, Jason (2023): "Read Between the Lines: Detecting Tracking JavaScript with Bytecode Classification", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)], CCS 2023 classifies tracking JavaScript from bytecode, with EasyList, EasyPrivacy and Fanboy's Enhanced Tracking as the labels.
The learned-classifier roster whose stated ground truth is a filter list runs to sixteen papers, and fourteen of them are a who's-who of the reference baselines: AdGraph, WebGraph, WTAGRAPH, Khaleesi, AdFlush, Duumviri, Beyond the Request, CookieGraph, NoT.js, Net-track, PURL, NoMoAds, the Ad Wars, and Tramèr et al.'s attack on perceptual ad blocking. (The other two are a 2015 website-category classifier and a 2018 host-population classifier whose labels mix hpHosts with PhishTank — in the count because hpHosts is an ad/tracking list, but not tracker detectors.) The roster is printed in full, with each paper's own ground-truth string, on the provenance page.
What to do instead, and what it costs
Nobody has escaped the list entirely, but four routes exist, in rising order of effort:
- Hand-label a sample and report precision against the list. A few hundred requests is an afternoon. 34 of the 167 list-using classification papers (20.4%) did this, and 119 (71.3%) report no validation at all; it is the single cheapest improvement available and reviewers notice its absence.
- Add an independent label source. Cookiepedia for cookies [23Munir, Shaoor; Siby, Sandra; Iqbal, Umar; Englehardt, Steven; Shafiq, Zubair; Troncoso, Carmela (2023): "CookieGraph: Understanding and Detecting First-Party Tracking Cookies", pp. 3490–3504. Association for Computing Machinery, New York, NY, USA. (DOI) (Link)], a CMP declaration, an entity map. Disagreements between two imperfect sources are informative in a way agreement with one is not.
- Use a behavioural or differential detector as the reference, not as the thing being scored: invisible pixels [3Fouad, Imane; Bielova, Nataliia; Legout, Arnaud; Sarafijanovic-Djukic, Natasa (2020): "Missed by Filter Lists: Detecting Unknown Third-Party Trackers with Invisible Pixels", in: Proceedings on Privacy Enhancing Technologies, pp. 499-518. (DOI)], breakage-differential testing [15Shuang, He; Zhao, Lianying; Lie, David (2025): "Duumviri: Detecting Trackers and Mixed Trackers with a Breakage Detector", in: Proceedings of the Network and Distributed System Security Symposium. (Link)], dynamic taint tracking [1Calzavara, Stefano; Casarin, Samuele; Squarcina, Marco; Maffei, Matteo (2026): "From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques", in: Proceedings on Privacy Enhancing Technologies. (Link)]. Each has been done roughly once.
- Report the confusion matrix and inspect the disagreements by hand. Lee et al. [13Lee, Dongkeun; Joo, Minwoo; Lee, Wonjun (2023): "Net-track: Generic Web Tracking Detection Using Packet Metadata", in: Proceedings of the ACM Web Conference. (DOI)] did exactly this and found 34.5% of their apparent errors were the list's, not theirs. That is a result you get for free by not assuming.
Use in Publications
Everything in this section comes from a structured extraction over 5,859 full-text papers from CCS, IMC, NDSS, PETS, USENIX Security, TheWebConf and IEEE S&P, 2010–2026, one record per paper with a verbatim evidence quote per claim. The 2025 and 2026 venue-years are provisional — CCS and IMC 2026 have not been held, and IEEE S&P and WWW 2026 are incompletely selected — so any per-year row reaching them is under-represented by construction. Methodology and limits are at the end of this section.
The population
A paper is in the population if it used or produced something that folds to a filter-list family. Engines (adblockparser, adblock-rust), heuristics that are not lists (Privacy Badger) and off-topic blocklists (spam, malware, IP reputation, censorship, certificate revocation) are excluded by name and counted separately.
| Signal | Papers |
|---|---|
| corpus | 5,859 |
| used or produced a filter list — the population | 198 (3.4% of the corpus) |
… named it in tools[] | 178 |
… named it in a classification[] step | 167 |
| … both | 147 |
… only in tools[] — an instrument, never a labelling step | 31 |
| named a list but only mentioned or compared against it — excluded | 18 |
“Mentioned” is not “used”. The 18 excluded papers are 8.4% of what a raw name search would score as adoption, and the compared ones are the dangerous rows: a paper that beats EasyList did not adopt it.
Which lists
Of the 198 papers that used or produced a filter list. A paper naming several is counted under each, so shares do not sum to 100%. Names are free text and were folded into families; spellings is how many distinct strings the corpus uses, and unfolded is what the single most common exact string alone would have found.
| List family | Papers | Share of 198 | Spellings | Unfolded |
|---|---|---|---|---|
| EasyList | 112 | 56.6% | 28 | 92 |
| EasyPrivacy | 71 | 35.9% | 22 | 58 |
| Disconnect | 48 | 24.2% | 23 | 26 |
| Ghostery / WhoTracks.me | 34 | 17.2% | 9 | 20 |
| hosts-file lists (hpHosts, AdAway, MoaAB, Pi-hole, NoTrack, …) | 27 | 13.6% | 33 | 3 |
| Adblock Plus (the lists shipped with it) | 26 | 13.1% | 8 | 20 |
| uBlock Origin lists | 17 | 8.6% | 11 | 13 |
| DuckDuckGo Tracker Radar | 15 | 7.6% | 9 | 8 |
| unnamed or merely counted (“nine crowd-sourced filter lists”) | 10 | 5.1% | 10 | 1 |
| AdGuard | 8 | 4.0% | 13 | 4 |
| EasyList annoyance / anti-adblock variants | 7 | 3.5% | 8 | 2 |
| anti-adblock scripts and services | 3 | 1.5% | 4 | 1 |
| cryptomining lists (NoCoin, CoinBlockerLists, MinerBlock) | 3 | 1.5% | 4 | 3 |
| Acceptable Ads exception list | 1 | 0.5% | 1 | 1 |
Folding is not cosmetic. Counting exact strings would find 92 EasyList papers instead of 112 (−17.9%), 26 Disconnect papers instead of 48 (−45.8%, because Disconnect appears as Disconnect list, Disconnect.me, Disconnect blacklist, Disconnect Entity List and twenty more), and 3 hosts-file papers instead of 27. Any adoption table built on exact strings is wrong by tens of percent.
What the list is used to label
Of the 167 papers with at least one list-backed classification step. This is the finding that motivated this page: the filter list is not a request classifier, it is the field's general-purpose “is this advertising or tracking” oracle, and it is applied to objects it was never written to describe.
classification.target | Papers | Share of 167 |
|---|---|---|
web-request | 101 | 60.5% |
domain | 53 | 31.7% |
cookie | 8 | 4.8% |
website-category | 7 | 4.2% |
javascript | 5 | 3.0% |
other | 3 | 1.8% |
fingerprinting-script | 3 | 1.8% |
network-traffic | 2 | 1.2% |
consent-notice | 2 | 1.2% |
email-message | 1 | 0.6% |
Grouped by what that does to the instrument:
| Granularity | Papers | Share of 167 |
|---|---|---|
| The list's own unit — a URL pattern evaluated with request context | 101 | 60.5% |
Coarser than the list — a hostname or eTLD+1, so path, resource-type and $third-party options are discarded | 53 | 31.7% |
| Objects a filter list was not written to label — the list supplies provenance, not a rule match | 30 | 18.0% |
These are not a partition and the shares exceed 100%: 17 of the 167 papers apply a list at more than one granularity — typically requests and domains in the same study.
Nearly a third of these 167 papers throw away the list's granularity before using it. That is often deliberate and sometimes unavoidable — a DNS blocklist or a passive traffic capture gives you nothing finer than a hostname — but it changes what the label means, and it is rarely stated. The per-paper roster behind every non-request row is on the provenance page so you can check the claim.
Ground truth
| Question | Papers |
|---|---|
papers whose classification.groundTruthSource names a filter list (whole corpus) | 96 |
| … of the 198 list-using papers | 88 (44.4%) |
| distinct kinds of object those tuples label | 12 |
| … of which the list is named generically (“eight crowdsourced filter lists”) rather than by name | 13 |
papers with a learned classifier (supervised-ml, unsupervised-ml, llm) whose stated ground truth is a filter list | 16 |
| … as a share of the 62 list-using papers that ran any learned classifier | 15 (24.2%)13) |
Validation of the list-backed classification steps, over the 167 papers. Sentinels are printed as themselves and never counted as an answer:
classification.validation | Papers | Share of 167 |
|---|---|---|
not-applicable (sentinel) | 69 | 41.3% |
none-reported (sentinel) | 61 | 36.5% |
| manual validation | 34 | 20.4% |
| comparison to another method | 14 | 8.4% |
The rows overlap — 11 papers carry both a sentinel and a real value, so the two sentinel rows must not be added. The paper-level figure is: 119 of 167 (71.3%) report nothing but sentinels, and 48 (28.7%) report at least one real validation.
The not-applicable row is mostly papers that applied a list as-is and reasonably consider the list itself the definition. That is exactly the assumption Calzavara et al. measured at 16%–19% false positives — on one crawl, with one independent detector, so treat it as the best available estimate rather than a constant.
Which version
| Question | Papers | Share |
|---|---|---|
named a filter list in tools[] | 178 | — |
| attached any version or date | 53 | 29.8% |
attached something that identifies the rules — a list Version: or a commit | 4 | 2.2% |
| silent | 125 | 70.2% |
Read the 29.8% as an order of magnitude in both directions: the extraction fills the version field when the paper puts a version next to the name, so a paper that dates its lists in a crawl paragraph may not be credited — and several of the 53 give an extension version (Ghostery 5.4.1, Adblock Plus 3.7) rather than a list version, which does not identify the rules at all. The 2.2% is the figure that matters and it is not an artefact: a list Version: string is unmistakable, and only four papers have one.
Where and when
| Venue | Corpus papers | Population | Share of venue |
|---|---|---|---|
| PETS | 510 | 55 | 10.8% |
| IMC | 638 | 36 | 5.6% |
| TheWebConf | 843 | 31 | 3.7% |
| IEEE S&P | 767 | 19 | 2.5% |
| CCS | 990 | 23 | 2.3% |
| USENIX Security | 1,410 | 24 | 1.7% |
| NDSS | 701 | 10 | 1.4% |
| Period | Corpus papers | Population | Per 1,000 |
|---|---|---|---|
| 2010–2013 | 511 | 6 | 11.7 |
| 2014–2017 | 769 | 25 | 32.5 |
| 2018–2021 | 1,439 | 58 | 40.3 |
| 2022–2024 | 1,955 | 70 | 35.8 |
| 2025–2026 (provisional) | 1,185 | 39 | 32.9 |
Filter-list use peaked in 2018–2021 and has been flat since, at roughly 3–4% of these seven venues. Nothing in the corpus supports “the field has moved on from filter lists”: machine learning was added alongside, not instead. Among the population, papers carrying any LLM-based classification step appear only in 2024 (2), 2025 (4) and 2026 (1) — real, new, and far too thin to call current practice on the strength of the corpus's most provisional years.
Methodology and limitations of these figures
- How they were produced. One structured record per paper extracted from full text, each tuple carrying a verbatim evidence quote and its section. Every number in this section comes from
report_filter_lists.mjs; the list-name fold isreq_fold.mjs, shared with Requests so the two pages cannot disagree about what “EasyList” means, and the granularity and regional folds arefl_fold.mjs. Every query, the scripts' unedited output, the full fold residue and the per-paper rosters are on the provenance page; corpus-level caveats are on corpus. - The population is a judgement, not an enum. No field in the extraction means “used a filter list”. The membership rule is a regular expression plus a hand-written family table, and both are printed in full on the provenance page so you can disagree with them.
- A paper counts once, never once per tuple, and shares do not sum to 100% because the fields are multi-valued.
- Sentinels are counted as what they are.
not-applicableandnone-reportedare never folded into a stated value; where they are the largest rows, that is the finding. - Free-text names were folded, and the residue is printed rather than dropped: 34 distinct strings matched the candidate regex but no family, and almost all are generic off-topic phrases (
12 IP reputation blacklists,combined public blacklists). Off-topic blocklist families were excluded by name and counted: malware/phishing 10 papers, spam 8, IP reputation 7, content-category 6, censorship 3, certificate revocation 2. - Free-text fields are ~20% stable run-to-run. List names are given as folded families and rankings; the enum fields (
classification.target,classification.validation) are considerably more stable and are given as percentages. - Venue coverage. Seven venues only. EuroS&P, ACSAC, RAID, AsiaCCS, WPES, CHI and SOUPS are absent, and several works this page relies on were published outside them — Snyder et al. at SIGMETRICS in particular. Any count here is a lower bound.
- Overlap with Requests. That page computes a partly overlapping population (its “S1” signal) and reports 197 papers where this page reports 198, with per-list counts differing by one or two. The two scripts define membership slightly differently — this page counts a list named anywhere in
tools[]orclassification[], that page additionally intersects with its request-classification task fold. Neither is wrong; the difference is a live example of why a population definition belongs in the provenance, not in a sentence.
What to Report
- The list, its version and its commit.
EasyList Version 202608291255, commit 722b6a02— not “EasyList”. Archive the.txtwith your artefact. 70% of papers give nothing; 98% give nothing that identifies the rules. - The engine and its version, separately from the list.
adblock0.13.3 andadblockparser0.7 do not match the same rules, and the second silently ignores options it does not know. - Which rule kinds you evaluated. Network only, or cosmetic too? Did you evaluate exception rules? Nearly a third of EasyList is cosmetic and answers a different question.
- The unit you applied it at, and if it is coarser than a request URL, say what that discards.
- Your regional lists, or the explicit statement that you used the anglophone core and that non-English results are a lower bound.
- Validation on your own sample. Hand-label a few hundred and report precision against the list. Four papers in five do not.
- If a list supplied your labels: the label noise. “Filter lists” is an answer with a published error rate now [1Calzavara, Stefano; Casarin, Samuele; Squarcina, Marco; Maffei, Matteo (2026): "From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques", in: Proceedings on Privacy Enhancing Technologies. (Link)] — quote it, and report the confusion matrix rather than two totals.
- Whether you blocked at crawl time or post-processed, because a blocking crawl changes the page it measures.
Open Questions
- The 16%–19% false-positive estimate is one study. [1Calzavara, Stefano; Casarin, Samuele; Squarcina, Marco; Maffei, Matteo (2026): "From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques", in: Proceedings on Privacy Enhancing Technologies. (Link)] used one taint-tracking browser on 7,614 sites. A very large amount of this page leans on it. It should be replicated with a different independent detector before it becomes folklore.
- Regional lists have two papers in seven venues across seventeen years. [7Sjösten, Alexander; Snyder, Peter; Pastor, Antonio; Papadopoulos, Panagiotis; Livshits, Benjamin (2020): "Filter List Generation for Underserved Regions", in: Proceedings of the ACM Web Conference. (DOI)] and [4Böttger, Christian; Demir, Nurullah; Hörnemann, Jan; Acharya, Bhupendra; Pohlmann, Norbert; Holz, Thorsten; Grosse-Kampmann, Matteo; Urban, Tobias (2025): "Understanding Regional Filter Lists: Efficacy and Impact", in: Proceedings on Privacy Enhancing Technologies, pp. 309-325. (DOI)]. Nobody has measured how much a per-country tracking comparison changes when the matching regional list is loaded — which means a large body of comparative geographic tracking work rests on an instrument of unmeasured, varying sensitivity.
- No learned tracker detector in this corpus escapes the list. Of the 16 papers whose stated ground truth is a filter list, every one that is a tracker detector — AdGraph, WebGraph, WTAGRAPH, Khaleesi, AdFlush, Duumviri, CookieGraph, NoT.js, Net-track, Beyond the Request — takes its labels from one. This is a statement about the 16, not about all learned classifiers in the corpus: 47 of the 62 list-using papers that ran a learned classifier state some other ground truth, and nobody has audited what those 47 are classifying or how. The two nearest misses to an independent label source — differential breakage testing [15Shuang, He; Zhao, Lianying; Lie, David (2025): "Duumviri: Detecting Trackers and Mixed Trackers with a Breakage Detector", in: Proceedings of the Network and Distributed System Security Symposium. (Link)] and taint tracking [1Calzavara, Stefano; Casarin, Samuele; Squarcina, Marco; Maffei, Matteo (2026): "From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques", in: Proceedings on Privacy Enhancing Technologies. (Link)] — have each been done once.
- Python still has no maintained filter-list engine. Someone should revive
python-adblockagainstadblock0.13.x, or the field should state loudly that Python pipelines must shell out. - Nobody has published which rules the shipped MV3 blockers drop to fit the 30,000-rule static cap, or what that omits from a measurement made with one.
- The “deliberate non-blocking” set has never been enumerated. [5Amjad, Abdul Haddi; Munir, Shaoor; Shafiq, Zubair; Gulzar, Muhammad Ali (2024): "Blocking Tracking JavaScript at the Function Granularity", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)] found ten unhandled cases in a sample of fifty and learned from the maintainers that some were deliberate. A list of rules that could exist and are withheld for breakage reasons would be a direct measurement of the gap between “tracker” and “blocked”, and the maintainers' issue trackers are public.
- Cookiepedia is load-bearing and unaudited. It is a OneTrust product built on self-declared purposes, and [23Munir, Shaoor; Siby, Sandra; Iqbal, Umar; Englehardt, Steven; Shafiq, Zubair; Troncoso, Carmela (2023): "CookieGraph: Understanding and Detecting First-Party Tracking Cookies", pp. 3490–3504. Association for Computing Machinery, New York, NY, USA. (DOI) (Link)] is the paper that made it a standard cookie-label source. Nobody in this corpus has measured its accuracy independently.
Related Pages
- Classifying web requests — what to do with the labels: the request-unit ladder, the ML lineage (AdGraph, WebGraph, Khaleesi, AdFlush), link decoration and cookie-notice detection.
- Comparison of crawling libraries — which of them record the initiator chain, resource type and redirect chain a rule needs.
- Tracker Radar Collector — the crawler behind the Tracker Radar dataset, which is a list of a different kind.
- webXray and domain-to-company ownership — once a request is flagged, whose is it, and why the entity maps disagree.
- Analysing and classifying JavaScript — the script- and function-level end, where list labels are propagated through call stacks.
- Classifying cookies — where the “a cookie set by a blocked resource is an advertising cookie” method belongs.
- Granting consent to websites — the cookie-notice lists (EasyList Cookie List, autoconsent, Consent-O-Matic) in their own context.
- Website classification — DNS and category blocklists, and the measured reason not to use a categorisation service to find trackers.
- Provenance of this page's figures — every query, the raw script output, the folds and their residue, the external checks and what was rejected.
References
- [1]
- Calzavara, Stefano; Casarin, Samuele; Squarcina, Marco; Maffei, Matteo (2026): "From Syntactic Matching to Taint Tracking and Back: A Comparative Study of Web Tracking Detection Techniques", in: Proceedings on Privacy Enhancing Technologies. (Link)
- [2]
- Snyder, Peter; Vastel, Antoine; Livshits, Ben (2020): "Who Filters the Filters: Understanding the Growth, Usefulness and Efficiency of Crowdsourced Ad Blocking", Proc. ACM Meas. Anal. Comput. Syst. 4(2). (DOI) (Link)
- [3]
- Fouad, Imane; Bielova, Nataliia; Legout, Arnaud; Sarafijanovic-Djukic, Natasa (2020): "Missed by Filter Lists: Detecting Unknown Third-Party Trackers with Invisible Pixels", in: Proceedings on Privacy Enhancing Technologies, pp. 499-518. (DOI)
- [4]
- Böttger, Christian; Demir, Nurullah; Hörnemann, Jan; Acharya, Bhupendra; Pohlmann, Norbert; Holz, Thorsten; Grosse-Kampmann, Matteo; Urban, Tobias (2025): "Understanding Regional Filter Lists: Efficacy and Impact", in: Proceedings on Privacy Enhancing Technologies, pp. 309-325. (DOI)
- [5]
- Amjad, Abdul Haddi; Munir, Shaoor; Shafiq, Zubair; Gulzar, Muhammad Ali (2024): "Blocking Tracking JavaScript at the Function Granularity", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)
- [6]
- Dimova, Yana; Acar, Gunes; Olejnik, Lukasz; Joosen, Wouter; Van Goethem, Tom (2021): "The CNAME of the game: Large-scale analysis of DNS-based tracking evasion", Proceedings on Privacy Enhancing Technologies 2021:394–412. (DOI) (Link)
- [7]
- Sjösten, Alexander; Snyder, Peter; Pastor, Antonio; Papadopoulos, Panagiotis; Livshits, Benjamin (2020): "Filter List Generation for Underserved Regions", in: Proceedings of the ACM Web Conference. (DOI)
- [8]
- Matte, Célestin; Bielova, Nataliia; Santos, Cristiana Teixeira (2020): "Do Cookie Banners Respect my Choice? Measuring Legal Compliance of Banners from IAB Europe's Transparency and Consent Framework", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)
- [9]
- Demir, Nurullah; Hörnemann, Jan; Große-Kampmann, Matteo; Urban, Tobias; Pohlmann, Norbert; Holz, Thorsten; Wressnegger, Christian (2023): "On the Similarity of Web Measurements Under Different Experimental Setups", in: Proceedings of the ACM Internet Measurement Conference, pp. 356-369. ACM DOI 10.1145/3618257.3624795 is listed by DBLP but was not registered with the DOI resolver as of 2026-08-12; the DOI above resolves to the authors' institutional record of the same paper (DOI)
- [10]
- Wang, Xinzhe; Zhuang, Zeyang; Meng, Wei; Cheng, James (2024): "Detecting and Understanding Self-Deleting JavaScript Code", in: Proceedings of the ACM Web Conference. (DOI)
- [11]
- Lukić, Karlo; Papadopoulos, Lazaros (2026): "Privacy vs. Profit: The Impact of Google's Manifest Version 3 (MV3) Update on Ad Blocker Effectiveness", in: Proceedings on Privacy Enhancing Technologies. (Link)
- [12]
- Chen, Quan; Snyder, Peter; Livshits, Ben; Kapravelos, Alexandros (2021): "Detecting Filter List Evasion with Event-Loop-Turn Granularity JavaScript Signatures", in: Proceedings of the IEEE Symposium on Security and Privacy. (DOI)
- [13]
- Lee, Dongkeun; Joo, Minwoo; Lee, Wonjun (2023): "Net-track: Generic Web Tracking Detection Using Packet Metadata", in: Proceedings of the ACM Web Conference. (DOI)
- [14]
- Lee, Kiho; Lim, Chaejin; Jin, Beomjin; Kim, Taeyoung; Kim, Hyoungshick (2024): "AdFlush: A Real-World Deployable Machine Learning Solution for Effective Advertisement and Web Tracker Prevention", in: Proceedings of the ACM Web Conference. (DOI)
- [15]
- Shuang, He; Zhao, Lianying; Lie, David (2025): "Duumviri: Detecting Trackers and Mixed Trackers with a Breakage Detector", in: Proceedings of the Network and Distributed System Security Symposium. (Link)
- [16]
- Shuba, Anastasia; Markopoulou, Athina; Shafiq, Zubair (2018): "NoMoAds: Effective and Efficient Cross-App Mobile Ad-Blocking", in: Proceedings on Privacy Enhancing Technologies. (DOI)
- [17]
- Shuba, Anastasia; Markopoulou, Athina (2020): "NoMoATS: Towards Automatic Detection of Mobile Tracking", in: Proceedings on Privacy Enhancing Technologies. (DOI)
- [18]
- Varmarken, Janus; Le, Hieu; Shuba, Anastasia; Markopoulou, Athina; Shafiq, Zubair (2020): "The TV is Smart and Full of Trackers: Measuring Smart TV Advertising and Tracking", in: Proceedings on Privacy Enhancing Technologies. (DOI)
- [19]
- Ferreira Torres, Christof; Willi, Fiona; Shinde, Shweta (2023): "Is Your Wallet Snitching On You? An Analysis on the Privacy Implications of Web3", in: 32nd USENIX Security Symposium (USENIX Security 23). (Link)
- [20]
- Rüth, Jan; Zimmermann, Torsten; Wolsing, Konrad; Hohlfeld, Oliver (2018): "Digging into Browser-based Crypto Mining", in: Proceedings of the ACM Internet Measurement Conference. (DOI)
- [21]
- Subramani, Karthika; Yuan, Xingzi; Setayeshfar, Omid; Vadrevu, Phani; Lee, Kyu Hyung; Perdisci, Roberto (2020): "When Push Comes to Ads: Measuring the Rise of (Malicious) Push Advertising", in: Proceedings of the ACM Internet Measurement Conference. (DOI)
- [22]
- Ukani, Alisha; Haddadi, Hamed; Snoeren, Alex C.; Snyder, Peter (2025): "Local Frames: Exploiting Inherited Origins to Bypass Content Blockers", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security, pp. 1349-1363. (DOI)
- [23]
- Munir, Shaoor; Siby, Sandra; Iqbal, Umar; Englehardt, Steven; Shafiq, Zubair; Troncoso, Carmela (2023): "CookieGraph: Understanding and Detecting First-Party Tracking Cookies", pp. 3490–3504. Association for Computing Machinery, New York, NY, USA. (DOI) (Link)
- [24]
- Smith, Michael; Snyder, Peter; Livshits, Benjamin; Stefan, Deian (2021): "SugarCoat: Programmatically Generating Privacy-Preserving, Web-Compatible Resource Replacements for Content Blocking", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)
- [25]
- Ghasemisharif, Mohammad; Polakis, Jason (2023): "Read Between the Lines: Detecting Tracking JavaScript with Bytecode Classification", in: Proceedings of the ACM SIGSAC Conference on Computer and Communications Security. (DOI)
src/request.rs in brave/adblock-rust, checked 2026-08-29: the constructor takes the request URL, the source URL, the request type and the method, and derives third_party by comparing the two domains.Link-header pagination on /contributors?per_page=1&anon=0 and /commits?per_page=1, plus search/issues?q=repo:easylist/easylist+type:issue+state:closed. The commit count is given loosely on purpose — it moves during a working day. Raw output on the provenance page.NOASSERTION; the repository's own LICENSE file, fetched 2026-08-29, states “Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International”.gorhill/uBlock remains actively maintained (pushed 2026-08-25) and works fully on Firefox, which still supports MV2. The MV3 replacement is uBlock Origin Lite (pushed 2026-08-26). Chrome's own Manifest V2 deprecation timeline gives 2026-08-31 as the date remaining MV2 extensions are removed from the Chrome Web Store — two days after this page was written, so re-check it.MAX_NUMBER_OF_STATIC_RULESETS but states no numeric value for it (fetched 2026-08-29 via Apple's own documentation JSON, because the HTML page is script-rendered). So no Safari cap is stated here — read the constant at runtime there too.