User Tools

Site Tools


programming:filter_lists

This is an old revision of the document!


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 corpus used or produced one and why almost every claim about advertising or tracking on the web ultimately 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 on 2026-08-29 by the script in Recording Which List You Used (its unedited output is in that section):

List Network Cosmetic Exception What that means
EasyList 54,722 24,512 758 Nearly a third of it cannot answer a request question
EasyPrivacy 55,099 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,528 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).1)

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-party and $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. Two fetches of the same URL on 2026-08-29, three minutes apart, returned two different builds:

Fetched (UTC) Version: the file declares Network rules sha256 (12)
11:58 202608291151 54,722 6c8ceac99fab
12:01 202608291144 54,721 a93a0118564c

Note the order. The later fetch returned the older build: easylist.to is behind a CDN and two requests minutes apart are not guaranteed to agree, let alone two requests days apart. This is why recording the Version: and Commit: is necessary but archiving the bytes is what actually makes you reproducible.

Seventeen days earlier the same list carried 52,557 network rules — +4.1% in 17 days.2) “We used EasyList” identifies nothing.

Which Lists Exist

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 11:51 UTC the day this was checked. Version: and Commit: in the header
EasyPrivacy Tracking and privacy. Four documented categories: generic URL/tracking patterns; self-hosted and CNAME first-party trackers; third-party-hosted tracking scripts; tracking servers blocked at URL level3) 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.4) 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,528 entries, Last-Modified the day this was checked. 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
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-28 00:50 UTC). No Version: field, only Last modified: — so record the date and the hash
DuckDuckGo autoconsent CMP-specific rules that can express which purposes to accept or reject Active and the best maintained of the three (pushed 2026-08-29, MPL-2.0). This is the one to build on
I Still Don't Care About Cookies Removes notices and clicks through them, when the specific consent action does not matter Active (pushed 2026-08-29), GPL-3.0, but 14,462 open issues
Consent-O-Matic The original CMP rule set, with per-purpose consent Alive but slower: last push 2026-02-07, 159 open issues
mozilla/cookie-banner-rules-list Firefox's cookie-banner handling rules Archived on GitHub, last push 2025-01-07. Note the org: it is mozilla/, not mozilla-extensions/ — the latter 404s. Do not start here
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 — do not reuse it
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.5)

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: 202608291151, Expires: 1 days
EasyList Germany 2,149 3,650 164 Version: 202608271302, with a Commit: field
Liste FR 9,892 3,545 157 Version: 202608291151

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 an honest limitation and reviewers accept it. 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 “EasyList, 2022”. 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 20236) 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 202608291151, commit 3a4485aa, 54,722 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               202608291151             network=  54722 cosmetic=  24512 exception=   758 sha256=6c8ceac99fab
easyprivacy            202608291151             network=  55099 cosmetic=     33 exception=   836 sha256=b1812eb0ad01
easylist-cookie        2026-08-28 00:50 UTC     network=   1674 cosmetic=  23057 exception=   428 sha256=2c39a370892c
adguard-url-tracking   2.0.14.1                 network=   2520 cosmetic=      2 exception=    91 sha256=7578d8eb0e3e
peter-lowe             Sat, 29 Aug 2026 10:08:46 GMT network=   3528 cosmetic=      0 exception=     0 sha256=28ca97374e62
easylist-china         202608291151             network=  11377 cosmetic=   6935 exception=   986 sha256=e5be0ec4ef4b
easylist-germany       202608271302             network=   2149 cosmetic=   3650 exception=   164 sha256=1528a89f4222
liste-fr               202608291151             network=   9892 cosmetic=   3545 exception=   157 sha256=bacd552ed794

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-rustv0.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.7) 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:8)

  • 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,722 network rules and EasyPrivacy 55,099. 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.9)

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.10) 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
VR / 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)] reported ten tracking scripts from a sample of fifty to the list authors, who confirmed via GitHub issues that these mixed scripts are knowingly not blocked, because blocking them breaks pages. “Not on the list” can mean “on the list's do-not-break register”.

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)], 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. 88 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 Non-ATS … 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 current state of the art for cookie labelling, and it is a real improvement on scoring the list against itself.
  • 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 whole learned-classifier roster in this corpus whose stated ground truth is a filter list — eleven papers, and it reads as a who's-who of the reference baselines — is printed in full 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:

  1. 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.
  2. 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.
  3. 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.
  4. 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 the field throws 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) 88
… of the 198 list-using papers 82 (41.4%)
distinct kinds of object those tuples label 12
papers with a learned classifier (supervised-ml, unsupervised-ml, llm) whose stated ground truth is a filter list 11

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.

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 is req_fold.mjs, shared with Requests so the two pages cannot disagree about what “EasyList” means, and the granularity and regional folds are fl_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-applicable and none-reported are 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[] or classification[], 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

  1. The list, its version and its commit. EasyList Version 202608291151, commit 3a4485aa — not “EasyList”. Archive the .txt with your artefact. 70% of papers give nothing; 98% give nothing that identifies the rules.
  2. The engine and its version, separately from the list. adblock 0.13.3 and adblockparser 0.7 do not match the same rules, and the second silently ignores options it does not know.
  3. 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.
  4. The unit you applied it at, and if it is coarser than a request URL, say what that discards.
  5. Your regional lists, or the explicit statement that you used the anglophone core and that non-English results are a lower bound.
  6. Validation on your own sample. Hand-label a few hundred and report precision against the list. Four papers in five do not.
  7. 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.
  8. 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.
  • Nothing in this corpus escapes the list. Every learned tracker detector here trains on filter-list labels, Duumviri included. The two nearest misses — 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-adblock against adblock 0.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 cases in a sample of fifty by asking the maintainers. 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.

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)
1)
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.
2)
The 2026-08-12 figures are the ones published on Requests before this page existed, measured the same way. Both of this page's runs are on the provenance page in full.
3)
Quoted from easylist.to/pages/policy.html, HTTP 200 on 2026-08-29. The page carries no revision date, so how long that text has stood cannot be established from it.
4)
The GitHub API reports the licence as NOASSERTION; the repository's own LICENSE file, fetched 2026-08-29, states “Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International”.
5)
The 143,654-rule figure that also appears in that paper belongs to a different experiment — the runtime and memory benchmark over all lists combined — and is not the denominator for the 6.6%. Getting that pairing wrong is easy.
6)
Not Your Average App: A Large-scale Privacy Analysis of Android Browsers, PoPETs 2023. It has no entry in this wiki's bibliography and is cited here by title only, because it is named as an example of good version reporting rather than as a source for a claim.
7)
2025 and 2024 chapters fetched and read 2026-08-29. The 2025 edition is the current one; the 2024 URLs still resolve. The 2025 Privacy chapter's text names WhoTracks.Me and does not name AdGuard's CNAME list.
8)
developer.chrome.com — chrome.declarativeNetRequest, “Rule limits”, fetched 2026-08-29. Constant names are the documentation's own; the fetched text is in the provenance page's raw output.
9)
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.
10)
MDN, ''declarativeNetRequest'', checked 2026-08-29. Read the constants at runtime rather than hard-coding them. Apple's Safari Web Extension content-blocking guide names 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.
You could leave a comment if you were logged in.
programming/filter_lists.1788006423.txt.gz · Last modified: by karel.kubicek.claude

Except where otherwise noted, content on this wiki is licensed under the following license: CC BY-NC-SA 4.0
CC BY-NC-SA 4.0 Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki