User Tools

Site Tools


provenance:privacy:cookies

This is an old revision of the document!


Provenance: Classifying Cookies

Working notes behind Classifying Cookies: every query with its denominator, the folds with their residues, the quotes that were checked, the external sources that were verified and the ones that were rejected, and the judgement calls. Corpus-level caveats — how the corpus was built, which venue-years are provisional, how stable each extracted field is — are on Corpus and are not restated here.

This is a working log, not prose. It is for someone checking a number.

1. The run

Date 2026-09-10
Corpus data/extract/run1/extractions.jsonl, 5,859 papers, 7 venues (CCS, IMC, NDSS, PoPETs, USENIX Security, TheWebConf, IEEE S&P), 2010–2026
Full text data/fulltext/<year>/<venue>/<slug>/paper.cols.txt, 5,869 readable files
Page before 20,196 bytes, no corpus figure, no “Use in Publications”, no methodology section, no provenance page
Page after 68,264 bytes
Scripts written scripts/report_cookies.mjs (§3–§9 below), scripts/cookiepedia_coverage.py (§7)
Scripts re-used scripts/report_llm_currency.mjs for the per-target LLM table, so this page and Website classification cannot disagree
Bibliography one entry added: cahn2016_cookies. No key collision, no DOI collision (§10)
Model Claude Opus 5 for the writing and the queries; Sonnet and Fable sub-agents for review (§12)

Frozen prior work, deliberately not reused. Three dossiers in /workspace/drain/bench-{a,b,c} were written against this page as an effort benchmark on the 4,322-paper corpus. Their structure informed this page (the four-question split and the “which methods are current” table are descendants of bench-b's and bench-c's classification sections). None of their figures was carried over: every number on the page was re-derived against the 5,859-paper run, and the denominators moved — the old corpus gave 90 cookie-measuring papers and 40 cookie-classifying papers, this one gives 117 and 53.

2. Scope: why this page and not a broader one

The item this run was given asked explicitly whether the page should broaden past “Classifying Cookies”. Decision: no. Recorded here because a reasonable person would have decided otherwise.

The argument for broadening is that the page id is privacy:cookies and a reader landing there expects cookies. The argument against, which won, is that four neighbouring pages already own the adjacent material in more depth than a broadened page could give it, and every one of them was read before deciding:

Material Already on Evidence it is covered there
Non-cookie client-side stores, and what a crawler's readout actually captures Browser storage Measured six-store × three-readout-method table; its own opening says “What you do with the cookies themselves is Cookies
Identifier heuristics — length, lifetime, tokenisation, entropy — and their supersession Cookie syncing Reproduces the eleven-row heuristic comparison from [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 has a “What is genuinely superseded” section covering exactly the length/expiry-to-entropy move
Third-party-cookie deprecation, its reversal, CHIPS, partitioning Privacy sandbox, Browser protection Dated timeline with primary sources through 2025-10-17
Consent state at crawl time Consent, Interaction Consent-action decision tree and verification

So the page keeps the narrow title and adds an explicit scope table pointing at each. The two places where the boundary is soft, and what was done:

  • Identifier detection. 16 of the 53 papers do it, so it cannot be absent from this page. Resolution: this page reports who does it and how the family moved over time and links to the neighbour for the heuristics themselves. No heuristic table is duplicated.
  • The party question. 2 of 53 papers state a rule. Kept here, in one paragraph, because it is a feature of the classifiers this page is about.

3. Populations and denominators

Two sources, never combined into one figure.

Tag Source Answers
[E] extractions.jsonl, 5,859 papers “how many papers reported doing X”
[F] paper.cols.txt, 5,869 readable files “how many papers mention X”

3.1 The page population

[E]  classification[].target == "cookie"                            -> 53 papers, 79 tuples   <-- THE page population
[E]  detection[].phenomenon matches /cookie/i                       -> 113 papers
[E]  ...minus three phenomena that are not HTTP cookies             -> excluded by name, listed below
[E]  union (classify a cookie OR a cookie detection tuple)          -> 117 papers  (2.0% of 5,859)
[E]  of the 53, ran a crawl                                         -> 49  (92.5%)
[E]  of the 53, have a crawlConfig object                           -> 49
     denominator for every classification comparison: 4,439 papers that classified anything
     denominator for every crawl comparison:          1,080 crawling papers with a crawlConfig

Excluded by name from the wider set, so the exclusion can be argued line by line rather than being buried in a regex: DNS cookie usage (a DNS protocol nonce), SYN-cookie feedback (TCP), Bloom-cookie communication overhead (a replacement primitive, not an HTTP cookie).

Why an enum and not a keyword sweep. classification.target is a closed enum and is among the more stable fields in the schema; detection.phenomenon is free text with ~20% run-to-run agreement on exact strings. A full-text regex population was considered and rejected: on the sibling page Cookie syncing the same approach needed a hand-adjudicated candidate list of over a hundred papers, and the resulting set is explicitly one person's judgement. The enum gives a set that a corpus refresh reproduces.

What that costs, stated on the page. A paper that classifies cookies as an incidental step inside a study about something else can have that step filed under target: other with a targetDetail, and would be missing from the 53. The population is a floor. The gap between 53 and 117 is mostly papers that count or track cookies without labelling them, but not entirely.

3.2 Every other denominator used on the page

Figure on the page Denominator Why that one
Question split (purpose 18, identifier 16, tracking 11, security 5, party 2, other 12) 53 Papers, multi-valued; a paper answering two questions is in two rows
Label-source families 53 Same
Bucketed family table 7 / 7 / 17 / 10 / 12 per bucket Printed as its own row in the table so no column is read against the wrong base
Taxonomy fold (ICC 11 of 29) 29, the papers that name a scheme at all Using 53 would count the 24 papers that named nothing as having named something else
Ground truth 56.6%, validation 32.1% 53, against 4,439 Both columns printed side by side
Crawl-config table 49 (papers with a crawlConfig object), against 1,080 crawlConfig is nullable; 53 and 1,120 would understate both
consentAction split 49 Same
Venue shares Papers in each venue (510, 843, 990, 638, 1,410, 701, 767) A count of 17 at PoPETs and 2 at IEEE S&P is meaningless without the venue sizes
Year shares Papers that classified anything that year Controls for the corpus roughly quintupling across the window
LLM per-target table Papers classifying that target (53 for cookie, 102 for privacy-policy, …) Not 5,859, and not 177
Full-text probe rows 5,869 readable files Stated in the output next to every row

4. The fold, and why it throws instead of leaving a residue

resourceName on a cookie classification tuple is free text: 61 distinct strings across 79 tuples, of which 31 begin with the word “custom”. Aggregating by exact string gives a largest row of 14 (Cookiepedia) and a long tail of ones.

The fold is a hand-keyed map in report_cookies.mjs (the RESOURCE constant) from the exact string to two values: a label-source family and the question the classifier answers. The script throws if a tuple's resourceName is not in the map. That is deliberate and is the opposite of the usual residue convention:

  • A pattern-based fold with a printed residue lets a corpus refresh silently drop a paper into the residue bucket, where nobody looks. This map cannot: the next run fails loudly and names the string.
  • The cost is that the residue is zero by construction, which proves nothing about whether the judgements are right. The compensating artifact is §2.2 of the report output, which prints every tuple with the family and question it landed in, grouped by family. That listing is the thing to check.

4.1 Judgement calls in the map, listed so they can be rejected

  • CookieGraph and WebGraph are filed under question tracking, not purpose, because their label is binary ATS-vs-not. CookieBlock is purpose (four ICC categories). Papers that compare all three are comparing classifiers that answer different questions; the page says so.
  • The five syncing detectors that the extractor filed as cookie classification (custom cookie-synchronization rules, custom Cookie Synchronization heuristics, cookie-syncing heuristic (custom), cookie-syncing script (adapted), custom cross-domain attribution and exfiltration pipeline) are filed as question other. They decide “did this value travel”, which is the Cookie syncing page's question. They are kept visible in the family listing rather than dropped.
  • custom regular expressions (TheWebConf 2022, Google publisher IDs) is filed as identifier. It extracts publisher IDs from cookie values, which is identifier detection with a known target rather than a generic predicate. Defensible either way.
  • zxcvbn is filed as an identifier-heuristic family even though it is a named third-party library rather than a custom rule, because the family is about what the label means, not about who wrote the code.
  • functional tree (FT) (TheWebConf 2014) is own-supervised-ml / security: it is a trained model, and it classifies authentication cookies.
  • Evidon Global Opt-out, DAA Protect My Choice, and Google Keep My Opt-Outs is its own family (opt-out-registry) with question other, rather than being folded into the filter-list family. Opt-out registries and tracker blocklists are different artifacts with different maintainers.
  • custom ad-blocker name search lists (IMC 2016) is own-rule / other: it searches for ad-blocker cookie names, which is neither tracking provenance nor a purpose.

4.2 The taxonomy fold, which does leave a residue

Pattern-based, first match wins, over the 29 papers that name a scheme on a cookie tuple.

Family Papers Share of 29
ICC (UK) four purposes, or a restatement 11 37.9%
Identifier vs non-identifier 7 24.1%
Advertising-and-tracking vs not 4 13.8%
First vs third party 2 6.9%
Lifetime buckets 1 3.4%
Security attributes 1 3.4%
Four GDPR-framed purposes 1 3.4%
Cookiepedia categories 1 3.4%

Unmapped residue: 7 tuples, printed in full (also in §5 of the report output):

2020 PETS   :: tracking cookie criteria
2020 WWW    :: first-party, advertising, analytics, content, social, and other
2024 PETS   :: functional, marketing, and other cookie categories
2025 IMC    :: exfiltration, overwriting, and deletion
2025 PETS   :: set after accepted banner, then sent before banner rejection
2025 USENIX :: trackers, location, IP address, language, unlikely personal information
2025 USENIX :: Ignored Cookie Rejection, Undeclared Cookies, Wrong Cookie Category

The ICC merge is a judgement and both counts are published. Strict — the string names the ICC or the International Chamber of Commerce — is 8 papers. Folded, including the four that write the four categories out without naming the scheme, is 11. The page quotes 11 and says the strict count in the same sentence. Every contributing string is printed in §5 of the report output. The row this run is least confident about is TheWebConf 2016's Cookiepedia categories: strictly necessary, performance, functionality, targeting/advertising, unknown — Cookiepedia is OneTrust's implementation of the ICC scheme plus “unknown”, so it folds, but a reader who wanted the strict count would remove it.

Unfolded, the largest exact-string row is 2 papers. Folded it is 11 — an 82% undercount if exact strings are counted. Same failure mode as the vantage 280 → 498 example in the site's own brief.

5. Quote spot-checks

report_cookies.mjs §11 matches the evidence.quote behind every figure the page states as a finding against paper.cols.txt, whitespace- and case-insensitively, falling back to the longest run of 8 consecutive words (the grading the dataset itself uses).

Result: 18 figures checked — 13 exact, 5 via an 8-word run, 0 not found.

Beyond the automated pass, four claims were read out of the source by hand, and two of them changed what the page says:

  1. [2Bollinger, Dino; Kubicek, Karel; Cotrini, Carlos; Basin, David (2022): "Automating Cookie Consent and GDPR Violation Detection", in: 31st USENIX Security Symposium (USENIX Security 22), pp. 2893-2910. USENIX Association, Boston, MA. (Link)]'s Cookiepedia accuracy. The extraction and a first draft both had a single number. The paper states it twice and inconsistently: §4.4 prose says “Cookiepedia achieves a mean balanced accuracy (i.e., macro-recall) of 83.4%”, while Table 3, the §4.5 summary and the abstract all say 84.7%. The page quotes the table and flags the discrepancy in a footnote rather than picking silently.
  2. Cookiepedia's coverage, 79.2%. Not in the extraction at all; read out of Table 3 by hand (“Cookie coverage: 79.2%” against XGBoost's “Cookie coverage: 100%”). This became the page's central methodological point and would have been missed by a purely extraction-driven pass.
  3. [3Munir, 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)]'s 89.86%. The extraction's prevalence reads “89.86% of the 20K websites”. The paper's own crawl is 20,000 sites but it is a stratified sample of the Tranco top million, and the 89.86% comes from a separate deployment on a 20% sample of the top million — which is why the paper's abstract says “top-million”. The page says top-million. This was previously got wrong on a sibling page and is recorded here so it is not got wrong again.
  4. [4Lin, Maxwell; Lin, Shihan; Wu, Helen; Wang, Karen; Yang, Xiaowei (2024): "Browsing without Third-Party Cookies: What Do You See?", in: Proceedings of the ACM Internet Measurement Conference. (DOI)]'s 28.50% unclassified. Read out of Table 1 with its caption (“The total, mean, and median of cookie counts in each category identified by Cookie-Script across 255 websites”), because the extraction had the percentage without the instrument or the population.

6. What the ''[F]'' full-text probes say, and what they do not

Denominator 5,869 readable files. A name match is a mention — it counts reference-list entries and related-work sentences — and is never added to an [E] count. Generic words (entropy, LLM names) are only counted within 150 characters of the word “cookie”, because unqualified they match password and DNS papers.

Probe Papers Read individually?
Cookiepedia 19 no
CookieGraph 20 no
CookieBlock 16 no
Cookie Script / Cookie-Script 11 yes — see below
cookiedatabase.org 2 yes
Open Cookie Database 0 n/a
cookiesearch 0 n/a
International Chamber of Commerce 13 no
zxcvbn near “cookie” 2 yes
entropy near “cookie” 35 no
an LLM name near “cookie” 5 yes
  • The Cookie Script probe over-matches and the page does not use its count. Of the 11 matches, several are the string appearing in a CMP inventory table (NDSS 2019), a table column header reading “Cookie Script Org.” (CCS 2023 CookieGraph), or a dark-patterns interview (PoPETs 2022). The page's claim of 4 papers using Cookie-Script as a label source comes from the [E] side, not from this probe.
  • The LLM-near-cookie probe returns 5 and only 1 is real. Two are reference-list entries (“Olejnik, Acar, Claude Castelluccia” — a person's first name, and a GPT-4o citation next to a CookieGraph citation), one is a deceptive-patterns paper using Gemini on screenshots, one is a GDPR right-of-access paper, and one is a web-agent benchmark whose task categories happen to include cookie banners. Only [5Chen, Baiqi; Lyu, Jiawei; Wu, Tingmin; Chhetri, Mohan Baruwal; Bai, Guangdong (2025): "Semantics-Aware Cookie Purpose Compliance", in: Proceedings of the ACM Web Conference. (DOI)] classifies cookies with an LLM. This is why the page's LLM claim rests on the [E] enum (classification.method == “llm” with target == “cookie”), not on the probe.
  • Both zxcvbn hits were read in context and both are genuine: IEEE S&P 2022 pre-filters cookies “unlikely to be identifiable” with zxcvbn, and USENIX Security 2025 “leverages the zxcvbn library for measuring the entropy of the cookie values (to discover tracking UIDs)”. The page reports 2 and 35 side by side precisely so nobody reads the library name as the method's reach.
  • The two zero rows are the page's most load-bearing negative results and they are negative results from a probe, which the site's own rules say to distrust. They are reported as “zero mentions in these seven venues” and never as “nobody uses it”. Positive control: the same probe finds 19 papers for Cookiepedia and 20 for CookieGraph in the same sweep, so the sweep is not silently failing.

7. External and industry sources

Every load-bearing external claim was read at a primary source on 2026-09-10. No SEO listicle, vendor comparison page or blog summary reached the page.

Claim on the page Primary source, and how it was checked
Cookiepedia holds 42,020,489 cookies; benchmark split 1% / 5% / 3% / 58% / 32% unknown cookiepedia.co.uk front page, read directly. Labelled on the page as a vendor self-report
Cookiepedia rejects plain curl cookiepedia.co.uk/cookies/user_id returns 403 to curl with a desktop User-Agent while the site root returns 200
The CookieGraph Cookiepedia name table: 45,785 names, 39.3% categorised, 35.1% Error, 25.6% Unknown Computed from the released artifact by scripts/cookiepedia_coverage.py (§7.1). Reproducible in one curl
The CookieGraph cookiepedia.csv is 917,551 rows of CMP-declared labels in the CookieBlock consent_data schema, not Cookiepedia classifications Downloaded and counted; header is ,id,browser_id,visit_id,name,domain,cat_id,cat_name,purpose,expiry,type_name,type_id. Confirmed against labelling_scripts/cookiepedia.py, which merges it with tranco.csv into a declared_label
Its cat_name takes 1,158 distinct values Counted over the same file
cookie_categories_updated.csv in the CookieGraph repo is a saved wget log, not a CSV Both files fetched: 3,260 bytes beginning –2023-03-02 20:52:33– https://raw.githubusercontent.com/ versus 1,656,432 bytes with header ,cookie_key,category
Open Cookie Database: 2,266 cookies, last commit 2026-08-21, actively maintained The CSV itself (2,267 lines with header) and the GitHub API (pushed_at 2026-08-21T07:57:05Z, archived false, 311 stars)
cookiedatabase.org publishes no cookie count; 501 service Data Passports cookiedatabase.org/wp-json/wp/v2/service?per_page=1 returns x-wp-total: 501. No cookie post type exists in /wp-json/wp/v2/types
cookiesearch.org is run by CookieYes, “100,000+ cookies”, six categories cookiesearch.org front page and footer, read directly
Cookie-Script is a CMP with a name-keyed category database using the ICC four plus “unclassified” [4Lin, Maxwell; Lin, Shihan; Wu, Helen; Wang, Karen; Yang, Xiaowei (2024): "Browsing without Third-Party Cookies: What Do You See?", in: Proceedings of the ACM Internet Measurement Conference. (DOI)] §2 describes exactly this; the vendor site confirms the scanner exists
CookieBlock is gone from the Chrome Web Store Three independent checks, §7.2
CookieBlock is Manifest V2 manifest.json on dibollinger/CookieBlock declares “manifest_version”: 2
Chrome disabled MV2 everywhere with Chrome 138 on 2025-07-24, removed in 139 developer.chrome.com/docs/extensions/develop/migrate/mv2-deprecation-timeline, quoted verbatim on the page
CookieBlock is still public on Firefox: v1.1.0, updated 2022-08-04, 1,980 daily users AMO API addons.mozilla.org/api/v5/addons/addon/cookieblock/: status: public
CookieBlock is still listed on Edge at v1.1.0 Edge product-details API, lastUpdateDate 2022-08-04. Flagged on the page as unverified for actual function, because Edge is Chromium
Firefox still distributes MV2 Mozilla Extension Workshop migration guide, “Distribute Manifest V2 and V3 extensions”
The offline classifier's input format and its two caveats CookieBlock-Consent-Classifier README, quoted
Third-party cookies not discontinued, 2025-04-22 Privacy Sandbox blog post, already on the page and re-checked 2026-09-10

7.1 The coverage script and its output

Committed as scripts/cookiepedia_coverage.py. Real, unedited output:

cookiepedia_coverage-output.txt
source: https://raw.githubusercontent.com/cookiegraph/CookieGraph/main/Feature%20Extraction%20and%20Classifier/code/labelling_scripts/cookies_categories_updated.csv
distinct cookie NAMES looked up in Cookiepedia: 45785   <-- denominator
 
category returned               names    share
----------------------------------------------
Error                           16093    35.1%
Unknown                         11701    25.6%
Performance                      5540    12.1%
Targeting/Advertising            4961    10.8%
Functionality                    3874     8.5%
Strictly Necessary               3616     7.9%
 
returned one of Cookiepedia's four categories: 17991 of 45785 = 39.3%
returned no usable category:                   27794 of 45785 = 60.7%
 
non-answer values, printed in full so none is silently folded away: ['Error', 'Unknown']
cookiepedia_coverage.py
#!/usr/bin/env python3
"""How much of a cookie-name lookup does Cookiepedia actually answer?
 
The question a purpose-classification paper has to answer before it quotes a
category distribution: what fraction of the cookies it looked up came back with
a category at all. Cookiepedia publishes a self-reported benchmark on its front
page; this script measures the same thing from an independent, released
artifact -- the Cookiepedia name-to-category table that CookieGraph
{shaoor2023cookiegraph} ships in its repository.
 
Two files, both from the CookieGraph artifact:
 
  cookies_categories_updated.csv  45,785 rows, one per cookie NAME, with the
                                  category Cookiepedia returned for that name.
                                  This is the lookup-coverage measurement.
  cookiepedia.csv                 917,551 rows, one per observed cookie, with
                                  the CMP-DECLARED category (the CookieBlock
                                  consent-crawler `consent_data` schema:
                                  cat_id 0-3 = the ICC UK four). Despite the
                                  filename these are website operators' own
                                  declarations, not Cookiepedia classifications.
 
Run:  python3 scripts/cookiepedia_coverage.py
Output committed as scripts/cookiepedia_coverage-output.txt.
"""
 
import collections
import csv
import io
import sys
import urllib.request
 
BASE = (
    "https://raw.githubusercontent.com/cookiegraph/CookieGraph/main/"
    "Feature%20Extraction%20and%20Classifier/code/labelling_scripts/"
)
UA = {"User-Agent": "measuretheweb-wiki-bot (contact karel.kubicek@vaultjs.com)"}
 
# Cookiepedia's own four categories. Everything else in the released table is a
# non-answer, and the two non-answers are DIFFERENT: "Unknown" is Cookiepedia
# saying it has the name and cannot categorise it; "Error" is the lookup itself
# failing. Collapsing them would hide which of the two dominates.
REAL = {"Strictly Necessary", "Performance", "Functionality", "Targeting/Advertising"}
 
 
def fetch(name):
    req = urllib.request.Request(BASE + name, headers=UA)
    with urllib.request.urlopen(req, timeout=180) as r:
        return r.read().decode("utf8", errors="replace")
 
 
def main():
    text = fetch("cookies_categories_updated.csv")
    reader = csv.reader(io.StringIO(text))
    header = next(reader)
    if header != ["", "cookie_key", "category"]:
        raise SystemExit(f"unexpected header {header!r}: the artifact changed, re-read it")
 
    counts = collections.Counter()
    n = 0
    for row in reader:
        n += 1
        counts[row[2]] += 1
 
    print(f"source: {BASE}cookies_categories_updated.csv")
    print(f"distinct cookie NAMES looked up in Cookiepedia: {n}   <-- denominator\n")
    print(f"{'category returned':28} {'names':>8} {'share':>8}")
    print("-" * 46)
    for cat, c in counts.most_common():
        print(f"{cat:28} {c:8d} {100 * c / n:7.1f}%")
 
    answered = sum(c for cat, c in counts.items() if cat in REAL)
    print(
        f"\nreturned one of Cookiepedia's four categories: {answered} of {n} "
        f"= {100 * answered / n:.1f}%"
    )
    print(
        f"returned no usable category:                   {n - answered} of {n} "
        f"= {100 * (n - answered) / n:.1f}%"
    )
    unseen = set(counts) - REAL
    print(f"\nnon-answer values, printed in full so none is silently folded away: {sorted(unseen)}")
 
 
if __name__ == "__main__":
    sys.exit(main())

7.2 The CookieBlock removal, in full

This is the page's biggest single correction — the previous version's step-by-step crawler recipe began “Install the CookieBlock extension in Chrome” — so it was checked three ways, with controls.

  1. The store page. Fetched with Playwright's own Chromium (a plain curl gets a JS shell, and the Swiss vantage gets a Google consent interstitial that has to be cleared with a SOCS cookie first). Final URL chromewebstore.google.com/detail/fbhiolckidkciamgcobkokpelckgnnol/error, title “Item not available”, body “This item is not available”.
  2. The CRX endpoint, with a positive and a negative control. clients2.google.com/service/update2/crx?response=redirect&prodversion=151.0&acceptformat=crx2,crx3&x=id%3D<id>%26uc:
ddkjiahejlhfcafbddmgiahcphecmpfh  (uBlock Origin Lite, live)   crx: 200, 9,635,198 bytes
fbhiolckidkciamgcobkokpelckgnnol  (CookieBlock)                crx: 204, 0 bytes
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa  (invented id)                crx: 404, status="error-unknownApplication"
  1. The update check. status=“ok” with status=“noupdate” for CookieBlock — Google knows the id and will not serve a package, which is what an unpublished item looks like and is distinguishable from the invented id's error-unknownApplication.

What is claimed on the page, and what is not. The page says CookieBlock is not installable from the Chrome Web Store and that Chrome disabled MV2 in Chrome 138. It does not claim Google removed it because of MV2 — that is a plausible inference from the two verified facts and is left as one. It also does not claim the Edge listing is broken, only that Edge is Chromium and the listing was not functionally tested.

7.3 Sources considered and rejected

  • cookie-script.com/cookie-database, the URL a search suggests for the Cookie-Script database — 404. The vendor's public entry point is the scanner, not a browsable database, so the page describes it as “a name-keyed category database exposed through its cookie scanner” and cites [4Lin, Maxwell; Lin, Shihan; Wu, Helen; Wang, Karen; Yang, Xiaowei (2024): "Browsing without Third-Party Cookies: What Do You See?", in: Proceedings of the ACM Internet Measurement Conference. (DOI)] for the category scheme rather than a vendor page.
  • cookiedatabase.org's “15.5k cookies”, which the previous version of this page carried. Not verifiable anywhere on the current site; the WordPress API has no cookie post type. Removed rather than refreshed, with a sentence on the page saying it was removed and why. Refreshing an unverifiable number to a new unverifiable number is how a stale figure survives a rewrite.
  • Any comparison-of-cookie-databases article. Several exist; all are CMP vendor marketing. Nothing from them is on the page. The coverage table is built from four measurements in peer-reviewed papers plus one reproducible computation plus one clearly-labelled vendor self-report.
  • A GitHub search for a maintained CookieBlock successor. Run (cookieblock in:name, sorted by push date) and returned nothing relevant: the top hits are unrelated hobby extensions with 0–1 stars. dibollinger/CookieBlock at 226 stars, last pushed 2023-12-08, is still the project. Recorded because “the maintained code may live under a renamed scope” is a real failure mode and it was checked, not assumed.

8. Currency: how each status was decided

The page's “Which Methods Are Current” table carries a status per family. The rule applied: a superseded judgement needs a named, dated source that supersedes the thing it retires; a current judgement needs presence in the 2025–2026 slice and an argument, because that slice is provisional.

Family Status What it rests on
Purpose database lookup current, the default 8 of the 10 papers in 2023–2024 and 5 of 12 in 2025–2026
Own hand-written rule current, largest family, mostly unreusable 20 of 53; 31 of 61 distinct resourceName strings begin “custom”
Identifier heuristic current, but the predicate changed Family present 2014→2026 including 3 papers in 2025–2026; the supersession of length/expiry thresholds by entropy is argued on the sibling page from [6Randall, Audrey; Snyder, Peter; Ukani, Alisha; Snoeren, Alex C.; Voelker, Geoffrey M.; Savage, Stefan; Schulman, Aaron (2022): "Measuring UID smuggling in the wild", in: Proceedings of the ACM Internet Measurement Conference. (DOI)] and [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)], not from a corpus count
Filter list provenance current and growing 8 papers, 3 of them 2025. Small numbers, said so on the page
Published classifier reused current, newest family 0 before 2023, then 3 and 2. Mechanically explained: the classifiers did not exist
Own supervised model stopped 3 papers, most recent 2023. Stated as “nobody has trained a new one since”, which is a claim about these seven venues only
LLM not established practice 1 paper of 53 (1.9%), 2025 only

8.1 The LLM claim, and the retraction it repairs

The brief for this run flagged that IP classification once asserted “LLM methods are now routine” for cookie classification, and that this was retracted. This run re-derived the figure independently and confirms the retraction: 1 of 53.

report_cookies.mjs §7 recomputes the per-target LLM table from scratch and it agrees with report_llm_currency.mjs row for row. Both are in the committed outputs. The page publishes the table so the comparison — privacy-policy 11.8%, cookie 1.9% — is visible rather than asserted, and links to which_task_though so the four pages tell one story.

The honest framing, recorded because it was a judgement: the corpus-wide LLM curve is steep (2 papers in 2023, 27 in 2024, 77 in 2025, 71 in a partial 2026), so “cookies will get there” is a reasonable prediction. It is not on the page, because a prediction is not a finding.

9. What could not be established

  • Whether the 53 is missing papers filed under target: other. The wider 117-paper set was inspected for obvious misses but not exhaustively adjudicated paper by paper, which is what the sibling syncing page did. This is the single biggest weakness of the population and it is stated on the page.
  • Whether Cookiepedia's accuracy has changed since 2022. Nobody has re-measured it. The page's accuracy figures are all from one paper on one dataset, said so at the point of use, and listed as the first open question.
  • Whether the Edge CookieBlock listing still functions. The listing exists at v1.1.0; whether current Edge runs an MV2 extension was not tested (it would need an Edge build and a profile). The page says “unverified” rather than guessing.
  • cookiedatabase.org's size. No public endpoint. See §7.3.
  • What fraction of the corpus's cookie papers report coverage. The page argues coverage is the number to report and gives four papers that do. It does not give “N of 53 report coverage”, because coverage is not a schema field and establishing it would need all 53 papers read by hand. A TODO worth closing: it would turn a rhetorical point into a measurement.
  • Whether no-interaction at 44.9% means what it says. A prior audit found this value unsupported by the paper in a large minority of cases across the whole corpus. It was not re-audited for these 49 papers. The page marks it as an upper bound and derives its stronger claim (“at most 9 of 49 report more than one consent state”) from the values that are not sentinels, which does not depend on the audit.
  • Anything about the six absent venues. SOUPS and CHI in particular: the usable-privacy half of this literature reaches the corpus only when it happens to appear at PoPETs.

10. Bibliography

One entry added, generated by node scripts/bibgen.mjs WWW/2016/an-empirical-study-of-web-cookies from the corpus index (real DOI, real authors):

cahn2016_cookies  --  Cahn, Alfeld, Barford, Muthukrishnan
                      "An Empirical Study of Web Cookies", TheWebConf 2016
                      doi 10.1145/2872427.2882991

Checked before saving: the key does not exist in literature:bibliography (0 matches), the DOI does not exist (0 matches), and scripts/bib_dedup_scan.py reports no new A/B/C/D candidate pair involving it. The one pre-existing [C] pair the scan reports (bratton2019_replication / sumner2014_exaggeration) is unrelated to this run and untouched.

Every other citekey on the page already existed. Twenty distinct keys resolve; the rendered page shows 128 bibtex_citekey spans, which is 64 markers — the plugin emits two spans per marker — and 20 references.

11. The report script and its output

scripts/report_cookies.mjs, run against data/extract/run1 on 2026-09-10. Real, unedited output. The script throws rather than continuing if a cookie classification tuple's resourceName is not in the hand-keyed map (§4).

report_cookies-output.txt
==============================================================================
1. POPULATIONS
==============================================================================
Population                                                                 Papers  Share of 5,859
-------------------------------------------------------------------------  ------  --------------
corpus (7 venues, 2010-2026)                                               5859    100%
classified or labelled something                                           4439    75.8%
ran an automated web crawl                                                 1120    19.1%
>=1 classification tuple with target == "cookie"  <-- the page population  53      0.9%
measures something about cookies (classify OR a cookie detection tuple)    117     2.0%
 
  The page's headline denominator is 53, NOT 5,859 and NOT 1,120.
  53 of 4439 papers that classified anything = 1.2%.
  49 of the 53 ran a crawl.
  Excluded by name from the wider set (not HTTP cookies): DNS cookie usage; SYN-cookie feedback; Bloom-cookie communication overhead
 
==============================================================================
1.1 THE 53 PAPERS, BY YEAR AND VENUE
==============================================================================
Year   Cookie-classifying papers  Papers classifying anything  Share  Corpus that year
-----  -------------------------  ---------------------------  -----  ----------------
2010   0                          77                           0.0%   119
2011   1                          83                           1.2%   116
2012   0                          108                          0.0%   151
2013   0                          96                           0.0%   125
2014   3                          126                          2.4%   166
2015   3                          140                          2.1%   190
2016   3                          144                          2.1%   182
2017   1                          185                          0.5%   231
2018   1                          192                          0.5%   254
2019   2                          293                          0.7%   402
2020   6                          315                          1.9%   404
2021   4                          296                          1.4%   379
2022   7                          412                          1.7%   546
2023   2                          503                          0.4%   719
2024   8                          529                          1.5%   690
2025*  11                         607                          1.8%   770
2026*  1                          333                          0.3%   415
* 2025-2026 are provisional venue-years: CCS 2026 and IMC 2026 have not been held,
  and IEEE S&P / WWW 2026 are incompletely selected. Those rows are floors.
Venue    Cookie-classifying papers  Papers in venue  Share of venue
-------  -------------------------  ---------------  --------------
PETS     17                         510              3.3%
WWW      13                         843              1.5%
CCS      8                          990              0.8%
IMC      5                          638              0.8%
USENIX   5                          1410             0.4%
NDSS     3                          701              0.4%
IEEE-SP  2                          767              0.3%
 
==============================================================================
1.2 THE 53 PAPERS, LISTED
==============================================================================
  2011  CCS       fortifying-web-based-applications-automatically
  2014  CCS       the-web-never-forgets-persistent-tracking-mechanisms-in-the-wild
  2014  CCS       your-online-interests-pwned-a-pollution-attack-against-targeted-advertising
  2014  WWW       quite-a-mess-in-my-cookie-jar-leveraging-machine-learning-to-protect-web-authent
  2015  IMC       affiliate-crookies-characterizing-affiliate-marketing-abuse
  2015  NDSS      upgrading-https-in-mid-air-an-empirical-study-of-strict-transport-security-and-k
  2015  WWW       cookies-that-give-you-away-the-surveillance-implications-of-web-tracking
  2016  CCS       online-tracking-a-1-million-site-measurement-and-analysis
  2016  IMC       ad-blockers-global-prevalence-and-impact
  2016  WWW       an-empirical-study-of-web-cookies
  2017  PETS      cross-device-tracking-measurement-and-disclosures
  2018  WWW       the-cost-of-digital-advertisement-comparing-user-and-advertiser-views
  2019  IEEE-SP   postcards-from-the-post-http-world-amplification-of-https-vulnerabilities-in-the
  2019  PETS      4-years-of-eu-cookie-law-results-and-lessons-learned
  2020  PETS      a-comparative-measurement-study-of-web-tracking-on-mobile-and-desktop-environmen
  2020  PETS      in-depth-evaluation-of-redirect-tracking-and-link-usage
  2020  PETS      inferring-tracker-advertiser-relationships-in-the-online-advertising-ecosystem-u
  2020  PETS      missed-by-filter-lists-detecting-unknown-third-party-trackers-with-invisible-pix
  2020  WWW       beyond-the-front-page-measuring-third-party-dynamics-in-the-field
  2020  WWW       stop-tracking-me-bro-differential-tracking-of-user-demographics-on-hyper-partisa
  2021  NDSS      reining-in-the-webs-inconsistencies-with-site-policy
  2021  USENIX    can-i-take-your-subdomain-exploring-same-site-attacks-in-the-modern-web
  2021  WWW       cookie-swap-party-abusing-first-party-cookies-for-web-tracking
  2021  WWW       user-tracking-in-the-post-cookie-era-how-websites-bypass-gdpr-consent-to-track-u
  2022  CCS       do-opt-outs-really-opt-me-out
  2022  IEEE-SP   journey-to-the-center-of-the-cookie-ecosystem-unraveling-actors-roles-and-relati
  2022  PETS      my-cookie-is-a-phoenix-detection-measurement-and-lawfulness-of-cookie-respawning
  2022  USENIX    automating-cookie-consent-and-gdpr-violation-detection
  2022  WWW       et-tu-brute-privacy-analysis-of-government-websites-and-mobile-apps
  2022  WWW       leveraging-googles-publisher-specific-ids-to-detect-website-administration
  2022  WWW       measuring-the-privacy-vs-compatibility-trade-off-in-preventing-third-party-state
  2023  CCS       cookiegraph-understanding-and-detecting-first-party-tracking-cookies
  2023  IMC       thou-shalt-not-reject-analyzing-accept-or-pay-cookie-banners-on-the-web
  2024  CCS       blocking-tracking-javascript-at-the-function-granularity
  2024  IMC       browsing-without-third-party-cookies-what-do-you-see
  2024  PETS      supporting-informed-choices-about-browser-cookies-the-impact-of-personalised-coo
  2024  PETS      the-devil-is-in-the-details-detection-measurement-and-lawfulness-of-server-side
  2024  PETS      a-large-scale-study-of-cookie-banner-interaction-tools-and-their-impact-on-users
  2024  USENIX    automated-large-scale-analysis-of-cookie-notice-compliance
  2024  USENIX    purl-safe-and-effective-sanitization-of-link-decoration
  2024  WWW       a-study-of-gdpr-compliance-under-the-transparency-and-consent-framework
  2025  CCS       layered-overlapping-and-inconsistent-a-large-scale-analysis-of-the-multiple-priv
  2025  IMC       cookieguard-characterizing-and-isolating-the-first-party-cookie-jar
  2025  NDSS      duumviri-detecting-trackers-and-mixed-trackers-with-a-breakage-detector
  2025  PETS      johnny-can-t-revoke-consent-either-measuring-compliance-of-consent-revocation-on
  2025  PETS      intractable-cookie-crumbs-unveiling-the-nexus-of-stateful-banner-interaction-and
  2025  PETS      empirically-measuring-data-localization-in-the-eu
  2025  PETS      tracking-without-borders-studying-the-role-of-webviews-in-bridging-mobile-and-we
  2025  PETS      unmasking-the-shadows-a-cross-country-study-of-online-tracking-in-illegal-movie
  2025  PETS      understanding-regional-filter-lists-efficacy-and-impact
  2025  USENIX    navigating-cookie-consent-violations-across-the-globe
  2025  WWW       semantics-aware-cookie-purpose-compliance
  2026  PETS      from-syntactic-matching-to-taint-tracking-and-back-a-comparative-study-of-web-tr
 
==============================================================================
2. PASS B — FOLD OF resourceName, WITH ITS RESIDUE
==============================================================================
 
79 cookie classification tuples across 53 papers, 61 distinct resourceName strings, all mapped (residue 0 by construction —
the script throws instead of silently dropping one). The listing in section 2.2 is what to
check: a zero residue means the map is complete, not that every judgement in it is right.
 
==============================================================================
2.1 LABEL-SOURCE FAMILY  (papers, of 53 that classify a cookie)
==============================================================================
Family                                                                    Papers  Share of 53  Tuples
------------------------------------------------------------------------  ------  -----------  ------
Other hand-written rule                                                   20      37.7%        21
Cookie purpose database (Cookiepedia, Cookie-Script, cookiedatabase.org)  17      32.1%        19
Identifier heuristic over the cookie value                                15      28.3%        15
Filter list / tracker database (provenance of the setter)                 8       15.1%        8
A published cookie classifier, reused off the shelf                       5       9.4%         6
Own supervised model trained for the paper                                3       5.7%         3
Hand labelling by the authors                                             2       3.8%         2
First/third-party rule over the domain                                    2       3.8%         2
Opt-out tool registry                                                     1       1.9%         1
Large language model                                                      1       1.9%         2
Multi-valued: a paper using Cookiepedia AND its own heuristic is in both rows.
 
==============================================================================
2.1b THE QUESTION BEING ANSWERED  (papers, of 53)
==============================================================================
Question                                                                    Papers  Share of 53  Tuples
--------------------------------------------------------------------------  ------  -----------  ------
Purpose: which category (necessary / functional / analytics / advertising)  18      34.0%        28
Tracking: does this cookie belong to a tracker                              11      20.8%        12
Identifier: does the value carry a per-user ID                              16      30.2%        16
Party: first or third party                                                 2       3.8%         2
Security role: authentication or session cookie, attribute correctness      5       9.4%         7
Something else (named in the residue listing)                               12      22.6%        14
 
==============================================================================
2.2 EVERY TUPLE, GROUPED BY FAMILY — the listing to argue with
==============================================================================
 
--- filter-list: Filter list / tracker database (provenance of the setter)
  2014 CCS      q=tracking   m=curated-database   used      "Ghostery"
  2019 PETS     q=tracking   m=blocklist          used      "Ghostery and Disconnect intersection"
  2020 WWW      q=tracking   m=curated-database   used      "Disconnect.me"
  2022 WWW      q=tracking   m=blocklist          used      "EasyList/EasyPrivacy"
  2023 IMC      q=tracking   m=blocklist          used      "justdomains blocklist"
  2025 PETS     q=tracking   m=blocklist          used      "justdomains"
  2025 CCS      q=tracking   m=blocklist          used      "EasyList"
  2025 PETS     q=tracking   m=blocklist          used      "justdomains blocklist"
 
--- identifier-heuristic: Identifier heuristic over the cookie value
  2014 CCS      q=identifier m=heuristic-rules    produced  "custom persistent-identifier detection rules"
  2015 WWW      q=identifier m=heuristic-rules    produced  "custom identifier-cookie detection algorithm"
  2016 CCS      q=identifier m=heuristic-rules    produced  "custom ID-cookie heuristic"
  2019 IEEE-SP  q=identifier m=heuristic-rules    used      "heuristic proposed in previous work"
  2020 PETS     q=identifier m=heuristic-rules    produced  "custom ID-cookie criteria"
  2020 PETS     q=identifier m=heuristic-rules    produced  "BehaviorTrack"
  2021 WWW      q=identifier m=heuristic-rules    produced  "custom tracking-ID detection algorithm"
  2021 WWW      q=identifier m=heuristic-rules    produced  "custom unique-ID parser"
  2022 CCS      q=identifier m=heuristic-rules    produced  "unique-ID cookie heuristics (custom)"
  2022 WWW      q=identifier m=heuristic-rules    produced  "potentially identifying cookie flow heuristic (custom)"
  2022 IEEE-SP  q=identifier m=heuristic-rules    used      "zxcvbn"
  2024 PETS     q=identifier m=heuristic-rules    produced  "custom ID-detection algorithm"
  2025 IMC      q=identifier m=heuristic-rules    produced  "custom identifier detection pipeline"
  2025 PETS     q=identifier m=heuristic-rules    produced  "custom ID-cookie heuristics"
  2026 PETS     q=identifier m=heuristic-rules    produced  "custom identifier-detection heuristic"
 
--- llm: Large language model
  2025 WWW      q=purpose    m=llm                produced  "GPT-3.5-turbo (custom fine-tuned model)"
  2025 WWW      q=purpose    m=llm                used      "GPT-3.5"
 
--- manual: Hand labelling by the authors
  2014 WWW      q=security   m=manual-labelling   produced  "custom gold-set labeling procedure"
  2025 WWW      q=purpose    m=manual-labelling   used      "three independent authors"
 
--- opt-out-registry: Opt-out tool registry
  2022 CCS      q=other      m=curated-database   used      "Evidon Global Opt-out, DAA Protect My Choice, and Google Keep My Opt-Outs"
 
--- own-rule: Other hand-written rule
  2011 CCS      q=security   m=heuristic-rules    produced  "custom Zan credential-cookie classifier"
  2014 WWW      q=security   m=heuristic-rules    used      "hand-coded rules for SessionShield, Serene, CookiExt, and Zan"
  2014 CCS      q=other      m=heuristic-rules    produced  "custom cookie-synchronization rules"
  2015 IMC      q=other      m=regex-or-signature used      "custom affiliate-cookie parser (AffTracker)"
  2015 NDSS     q=security   m=heuristic-rules    produced  "custom cookie-scope checks"
  2016 IMC      q=other      m=heuristic-rules    used      "custom ad-blocker name search lists"
  2017 PETS     q=other      m=regex-or-signature used      "cookie-syncing script (adapted)"
  2018 WWW      q=other      m=heuristic-rules    produced  "custom Cookie Synchronization heuristics"
  2020 PETS     q=tracking   m=heuristic-rules    produced  "custom cookie classification algorithm"
  2020 PETS     q=other      m=heuristic-rules    used      "cookie-syncing heuristic (custom)"
  2020 WWW      q=other      m=heuristic-rules    produced  "custom"
  2021 NDSS     q=security   m=heuristic-rules    produced  "custom cookie inconsistency checks"
  2021 USENIX   q=security   m=heuristic-rules    used      "random session-cookie heuristic"
  2022 CCS      q=other      m=heuristic-rules    produced  "matching patterns (custom)"
  2022 USENIX   q=purpose    m=heuristic-rules    produced  "custom keyword mapping"
  2022 WWW      q=identifier m=regex-or-signature produced  "custom regular expressions"
  2025 IMC      q=other      m=heuristic-rules    produced  "custom cross-domain attribution and exfiltration pipeline"
  2025 PETS     q=other      m=heuristic-rules    produced  "custom intractable-cookie definition"
  2025 USENIX   q=other      m=heuristic-rules    produced  "custom personal-information detector"
  2025 USENIX   q=other      m=heuristic-rules    produced  "ConsentChk rule-based violation classifier"
  2025 WWW      q=other      m=heuristic-rules    produced  "custom segmentation rules"
 
--- own-supervised-ml: Own supervised model trained for the paper
  2014 WWW      q=security   m=supervised-ml      produced  "functional tree (FT)"
  2022 USENIX   q=purpose    m=supervised-ml      produced  "XGBoost (custom)"
  2023 CCS      q=tracking   m=supervised-ml      produced  "random forest (custom)"
 
--- party-rule: First/third-party rule over the domain
  2016 WWW      q=party      m=heuristic-rules    produced  "custom host-domain comparison"
  2025 PETS     q=party      m=heuristic-rules    used      "Public Suffix List"
 
--- published-classifier: A published cookie classifier, reused off the shelf
  2023 CCS      q=purpose    m=other              compared  "CookieBlock"
  2023 CCS      q=tracking   m=graph-analysis     compared  "WebGraph"
  2024 CCS      q=tracking   m=graph-analysis     used      "CookieGraph"
  2024 USENIX   q=purpose    m=supervised-ml      used      "CookieBlock"
  2025 PETS     q=purpose    m=curated-database   used      "CookieBlock"
  2025 WWW      q=purpose    m=supervised-ml      compared  "CookieBlock"
 
--- purpose-database: Cookie purpose database (Cookiepedia, Cookie-Script, cookiedatabase.org)
  2016 WWW      q=purpose    m=curated-database   used      "Cookiepedia"
  2020 WWW      q=purpose    m=curated-database   used      "Cookiepedia"
  2022 PETS     q=purpose    m=curated-database   used      "Cookiepedia"
  2022 USENIX   q=purpose    m=curated-database   compared  "Cookiepedia"
  2023 CCS      q=purpose    m=curated-database   used      "Cookiepedia"
  2024 IMC      q=purpose    m=curated-database   used      "Cookie-Script"
  2024 PETS     q=purpose    m=third-party-service used      "Cookie-Script"
  2024 PETS     q=purpose    m=curated-database   used      "Cookiepedia"
  2024 USENIX   q=purpose    m=curated-database   used      "Cookiepedia"
  2024 USENIX   q=purpose    m=curated-database   used      "Cookiedatabase.org"
  2024 PETS     q=purpose    m=curated-database   used      "Cookiepedia"
  2024 USENIX   q=purpose    m=curated-database   used      "Cookiepedia"
  2024 WWW      q=purpose    m=curated-database   used      "Cookiepedia"
  2025 NDSS     q=purpose    m=curated-database   used      "Cookiepedia"
  2025 PETS     q=purpose    m=curated-database   used      "Cookie Database"
  2025 USENIX   q=purpose    m=curated-database   used      "Cookiepedia"
  2025 WWW      q=purpose    m=curated-database   compared  "Cookiepedia"
  2025 WWW      q=purpose    m=curated-database   compared  "Cookie Script"
  2025 PETS     q=purpose    m=third-party-service used      "Cookiepedia"
 
==============================================================================
3. DATING THE METHODS — label-source family by year
==============================================================================
Family                                                                    Papers  First  Most recent  Years it appears in
------------------------------------------------------------------------  ------  -----  -----------  -------------------------------------------------
Other hand-written rule                                                   20      2011   2025         2011 2014 2015 2016 2017 2018 2020 2021 2022 2025
Cookie purpose database (Cookiepedia, Cookie-Script, cookiedatabase.org)  17      2016   2025         2016 2020 2022 2023 2024 2025
Identifier heuristic over the cookie value                                15      2014   2026         2014 2015 2016 2019 2020 2021 2022 2024 2025 2026
Filter list / tracker database (provenance of the setter)                 8       2014   2025         2014 2019 2020 2022 2023 2025
A published cookie classifier, reused off the shelf                       5       2023   2025         2023 2024 2025
Own supervised model trained for the paper                                3       2014   2023         2014 2022 2023
Hand labelling by the authors                                             2       2014   2025         2014 2025
First/third-party rule over the domain                                    2       2016   2025         2016 2025
Large language model                                                      1       2025   2025         2025
Opt-out tool registry                                                     1       2022   2022         2022
 
==============================================================================
3.1 THE SAME SPLIT IN FOUR-YEAR BUCKETS
==============================================================================
Family                                                                    2010-2015  2016-2019  2020-2022  2023-2024  2025-2026*
------------------------------------------------------------------------  ---------  ---------  ---------  ---------  ----------
Other hand-written rule                                                   5          3          8          0          4
Cookie purpose database (Cookiepedia, Cookie-Script, cookiedatabase.org)  0          1          3          8          5
Identifier heuristic over the cookie value                                2          2          7          1          3
Filter list / tracker database (provenance of the setter)                 1          1          2          1          3
A published cookie classifier, reused off the shelf                       0          0          0          3          2
Own supervised model trained for the paper                                1          0          1          1          0
Hand labelling by the authors                                             1          0          0          0          1
First/third-party rule over the domain                                    0          1          0          0          1
Large language model                                                      0          0          0          0          1
Opt-out tool registry                                                     0          0          1          0          0
(denominator) cookie-classifying papers in bucket  7  7  17  10  12
-------------------------------------------------  -  -  --  --  --
 
==============================================================================
4. THE PURPOSE-CLASSIFICATION SUBSET, PAPER BY PAPER
==============================================================================
18 papers answer the purpose question, of 53 that classify a cookie.
 
  2023 CCS      cookiegraph-understanding-and-detecting-first-party-tracking-cookies
      Cookiepedia [used]; CookieBlock [compared]
  2024 IMC      browsing-without-third-party-cookies-what-do-you-see
      Cookie-Script [used]
  2025 NDSS     duumviri-detecting-trackers-and-mixed-trackers-with-a-breakage-detector
      Cookiepedia [used]
  2022 PETS     my-cookie-is-a-phoenix-detection-measurement-and-lawfulness-of-cookie-respawning
      Cookiepedia [used]
  2024 PETS     a-large-scale-study-of-cookie-banner-interaction-tools-and-their-impact-on-users
      Cookiepedia [used]
  2024 PETS     supporting-informed-choices-about-browser-cookies-the-impact-of-personalised-coo
      Cookie-Script [used]
  2024 PETS     the-devil-is-in-the-details-detection-measurement-and-lawfulness-of-server-side
      Cookiepedia [used]
  2025 PETS     empirically-measuring-data-localization-in-the-eu
      Cookie Database [used]
  2025 PETS     johnny-can-t-revoke-consent-either-measuring-compliance-of-consent-revocation-on
      CookieBlock [used]
  2025 PETS     understanding-regional-filter-lists-efficacy-and-impact
      Cookiepedia [used]
  2022 USENIX   automating-cookie-consent-and-gdpr-violation-detection
      custom keyword mapping [produced]; XGBoost (custom) [produced]; Cookiepedia [compared]
  2024 USENIX   automated-large-scale-analysis-of-cookie-notice-compliance
      CookieBlock [used]; Cookiepedia [used]; Cookiedatabase.org [used]
  2024 USENIX   purl-safe-and-effective-sanitization-of-link-decoration
      Cookiepedia [used]
  2025 USENIX   navigating-cookie-consent-violations-across-the-globe
      Cookiepedia [used]
  2016 WWW      an-empirical-study-of-web-cookies
      Cookiepedia [used]
  2020 WWW      beyond-the-front-page-measuring-third-party-dynamics-in-the-field
      Cookiepedia [used]
  2024 WWW      a-study-of-gdpr-compliance-under-the-transparency-and-consent-framework
      Cookiepedia [used]
  2025 WWW      semantics-aware-cookie-purpose-compliance
      GPT-3.5-turbo (custom fine-tuned model) [produced]; three independent authors [used]; Cookiepedia [compared]; Cookie Script [compared]; CookieBlock [compared]; GPT-3.5 [used]
 
==============================================================================
5. TAXONOMY — which category scheme, folded
==============================================================================
29 of 53 papers name a category scheme on at least one cookie tuple (54.7%).
The denominator below is 29, not 53.
 
Scheme (folded)                                                              Papers  Share of 29
---------------------------------------------------------------------------  ------  -----------
ICC (UK) four purposes, or a restatement of them                             11      37.9%
Identifier vs non-identifier                                                 7       24.1%
Advertising-and-tracking vs not                                              4       13.8%
First vs third party                                                         2       6.9%
Lifetime buckets                                                             1       3.4%
Security attributes                                                          1       3.4%
Four GDPR-framed purposes (necessary / preference / statistics / marketing)  1       3.4%
Cookiepedia categories (= the ICC four plus "unknown")                       1       3.4%
 
UNMAPPED RESIDUE (7 tuples) — printed in full:
  2020 PETS :: tracking cookie criteria
  2020 WWW :: first-party, advertising, analytics, content, social, and other
  2024 PETS :: functional, marketing, and other cookie categories
  2025 IMC :: exfiltration, overwriting, and deletion
  2025 PETS :: set after accepted banner, then sent before banner rejection
  2025 USENIX :: trackers, location, IP address, language, unlikely personal information
  2025 USENIX :: Ignored Cookie Rejection, Undeclared Cookies, Wrong Cookie Category
 
Strict count, exact string naming the ICC or its author: 8 papers.
Folded count including the restatements: 11 papers.
Both are printed because the merge is a judgement. Every contributing string:
  2016 WWW      "Cookiepedia categories: strictly necessary, performance, functionality, targeting/advertising, unknown"
  2020 WWW      "ICC UK four cookie purposes"
  2022 PETS     "ICC UK four purposes: Strictly Necessary, Performance, Functionality, Targeting"
  2022 USENIX   "ICC UK four purposes plus unclassified and other"
  2022 USENIX   "ICC UK four purposes"
  2022 USENIX   "ICC UK four purposes"
  2023 CCS      "strictly necessary, functional, analytics, advertising/tracking"
  2024 IMC      "ICC UK four categories plus unclassified"
  2024 PETS     "ICC UK four cookie purposes"
  2024 USENIX   "UK ICC: necessary, functional, analytics, advertising"
  2024 PETS     "International Chamber of Commerce UK four cookie categories"
  2024 USENIX   "strictly necessary, functional, analytics, advertising/tracking"
  2024 WWW      "UK International Chamber of Commerce: strictly necessary, functionality, performance, targeting/advertising"
 
==============================================================================
6. GROUND TRUTH AND VALIDATION — where the field goes quiet
==============================================================================
Field                                                        Cookie papers stating it  of 53  Whole classified corpus  of 4439
-----------------------------------------------------------  ------------------------  -----  -----------------------  -------
names a ground-truth source                                  30                        56.6%  3234                     72.9%
reports any validation (not none-reported / not-applicable)  17                        32.1%  3111                     70.1%
 
==============================================================================
6.1 VALIDATION, PER VALUE (cookie tuples; enum, so publishable as a percentage)
==============================================================================
validation                  Papers  Share of 53
--------------------------  ------  -----------
none-reported               27      50.9%
not-applicable              16      30.2%
manual-validation           13      24.5%
comparison-to-other-method  4       7.5%
cross-validation            3       5.7%
held-out-test-set           3       5.7%
 
==============================================================================
6.2 METHOD ENUM, PER VALUE (cookie tuples), against the classified corpus
==============================================================================
classification.method  Cookie papers  of 53  Corpus papers  of 4439
---------------------  -------------  -----  -------------  -------
heuristic-rules        30             56.6%  2183           49.2%
curated-database       19             35.8%  649            14.6%
blocklist              6              11.3%  189            4.3%
supervised-ml          5              9.4%   1087           24.5%
regex-or-signature     3              5.7%   310            7.0%
manual-labelling       2              3.8%   1381           31.1%
third-party-service    2              3.8%   643            14.5%
graph-analysis         2              3.8%   154            3.5%
other                  1              1.9%   394            8.9%
llm                    1              1.9%   177            4.0%
dynamic-analysis       0              0.0%   300            6.8%
unsupervised-ml        0              0.0%   320            7.2%
static-analysis        0              0.0%   472            10.6%
 
==============================================================================
7. LLM CLASSIFICATION OF COOKIES — the currency check
==============================================================================
Classification target  Papers classifying it  of which use an LLM  Share
---------------------  ---------------------  -------------------  -----
other                  2594                   116                  4.5%
user-generated-text    419                    32                   7.6%
vulnerability          883                    14                   1.6%
privacy-policy         102                    12                   11.8%
mobile-app             282                    6                    2.1%
website-category       424                    5                    1.2%
domain                 351                    3                    0.9%
network-traffic        383                    2                    0.5%
consent-notice         39                     2                    5.1%
ip-address             295                    1                    0.3%
web-request            262                    1                    0.4%
email-message          54                     1                    1.9%
cookie                 53                     1                    1.9%
dark-pattern           13                     1                    7.7%
malware                160                    0                    0.0%
sdk-or-library         77                     0                    0.0%
javascript             44                     0                    0.0%
fingerprinting-script  32                     0                    0.0%
website-popularity     16                     0                    0.0%
 
The cookie row is the one privacy:cookies and design:website_classification must agree on.
  LLM + cookie: WWW/2025/semantics-aware-cookie-purpose-compliance
 
==============================================================================
8. HOW THE COOKIE PAPERS CRAWL
==============================================================================
49 of the 53 cookie papers have a crawlConfig object; 1080 of the 1120 crawling papers do.
 
crawlConfig field  Cookie papers stating it  of 49  All crawling papers  of 1080
-----------------  ------------------------  -----  -------------------  -------
consentAction      32                        65.3%  349                  32.3%
statefulness       36                        73.5%  219                  20.3%
interactionDepth   47                        95.9%  841                  77.9%
browsers           40                        81.6%  529                  49.0%
headless           10                        20.4%  140                  13.0%
authentication     42                        85.7%  779                  72.1%
 
==============================================================================
8.1 consentAction, per value (cookie papers with a crawlConfig)
==============================================================================
consentAction                           Papers  Share of 49
--------------------------------------  ------  -----------
no-interaction                          22      44.9%
not-stated  (sentinel — not an answer)  17      34.7%
accept-and-reject                       7       14.3%
reject-all                              2       4.1%
accept-all                              1       2.0%
 
==============================================================================
9. PASS C — full-text probes for what the schema cannot see
==============================================================================
readable paper.cols.txt files: 5869   <-- denominator for every row below
Probe                                      Papers matching  Share of 5869
-----------------------------------------  ---------------  -------------
Cookiepedia (name)                         19               0.3%
CookieBlock (name)                         16               0.3%
CookieGraph (name)                         20               0.3%
"Cookie Script" / Cookie-Script            11               0.2%
cookiedatabase.org                         2                0.0%
Open Cookie Database                       0                0.0%
cookiesearch.org                           0                0.0%
ICC / International Chamber of Commerce    13               0.2%
zxcvbn, within 150 chars of "cookie"       2                0.0%
entropy, within 150 chars of "cookie"      35               0.6%
an LLM name, within 150 chars of "cookie"  5                0.1%
 
  A name match is a MENTION, not a use: it counts reference-list entries and
  related-work sentences. It is never added to a PASS A count. The rows worth
  reading individually are the small ones:
 
--- zxcvbn, within 150 chars of "cookie"  (2)
  IEEE-SP/2022/journey-to-the-center-of-the-cookie-ecosystem-unraveling-actors-roles-and-relati
      ...entifier cookies and therefore, construct the cookie tree only for those. We pre-filter all cookies that are unlikely to be identifiable by using the zxcvbn technique proposed in a recent work [26]. B. Mapping Domains to...
  USENIX/2025/navigating-cookie-consent-violations-across-the-globe
      ...ex patterns (e.g., IP address, GPS location, and common tracker formats), as well as decoding Base64-encoded cookies. The detector also leverages the zxcvbn [69] library for measuring the entropy of the cookie values (to...
 
--- an LLM name, within 150 chars of "cookie"  (5)
  CCS/2025/automatically-detecting-online-deceptive-patterns
      ...ominent than the other, leading to an AutoBot to inform developers of potential deceptive patterns on incorrect classification of "nudge". Similarly, Gemini 2.5 Pro incor- their sites, integrating directly into developer...
  IMC/2025/from-voice-to-ads-auditing-commercial-smart-speakers-for-targeted-advertising-ba
      ...first-party tracking cookies. In Proceedings of the 2023 ACM SIGSAC Conference on Computer and Communications Security. 3490-3504. [79] OpenAI. 2023. GPT-4o. https://platform.openai.com/docs/models#gpt-4o. [80] Pi-hole. ...
  WWW/2025/semantics-aware-cookie-purpose-compliance
      ...er features such as expiration time. Coover decomposes the cookie value into primitive segments representing minimal semantic units, and fine-tunes a GPT-3.5 model to automatically interpret their value-inferred semantic...
  IEEE-SP/2026/setting-the-course-but-forgetting-to-steer-analyzing-compliance-with-gdprs-right
      ...Amit Zac, Carlos Cotrini, and David Basin. Automated large-scale analysis of cookie notice compliance. In USENIX Security, 2024. [8] Google DeepMind. Gemini 2.0: A multimodal ai model. https:// deepmind.google/technologi...
  PETS/2026/websp-eval-evaluating-web-agents-on-website-security-and-privacy-tasks
      ...Safety & Content Moderation (25 out of 31). Similar to performance breakdown on websites, here too we notice that specific models perform better than Gemini-3-Pro on some task categories. For example, Claude-Sonnet-4.5 a...
 
--- "Cookie Script" / Cookie-Script  (11)
  NDSS/2019/we-value-your-privacy-now-take-some-cookies-measuring-the-gdprs-impact-on-web-privacy
      ...(name match)...
  CCS/2021/sugarcoat-programmatically-generating-privacy-preserving-web-compatible-resource
      ...(name match)...
  IEEE-SP/2022/the-state-of-the-samesite-studying-the-usage-effectiveness-and-adequacy-of-sames
      ...(name match)...
  PETS/2022/on-dark-patterns-and-manipulation-of-website-publishers-by-cmps
      ...(name match)...
  USENIX/2022/automating-cookie-consent-and-gdpr-violation-detection
      ...(name match)...
  CCS/2023/cookiegraph-understanding-and-detecting-first-party-tracking-cookies
      ...(name match)...
  IMC/2024/browsing-without-third-party-cookies-what-do-you-see
      ...(name match)...
  PETS/2024/supporting-informed-choices-about-browser-cookies-the-impact-of-personalised-coo
      ...(name match)...
  CCS/2025/layered-overlapping-and-inconsistent-a-large-scale-analysis-of-the-multiple-priv
      ...(name match)...
  IMC/2025/cookieguard-characterizing-and-isolating-the-first-party-cookie-jar
      ...(name match)...
  WWW/2025/semantics-aware-cookie-purpose-compliance
      ...(name match)...
 
--- cookiedatabase.org  (2)
  USENIX/2024/automated-large-scale-analysis-of-cookie-notice-compliance
      ...(name match)...
  PETS/2025/empirically-measuring-data-localization-in-the-eu
      ...(name match)...
 
--- Open Cookie Database  (0)
 
--- cookiesearch.org  (0)
 
==============================================================================
10. MEASURED RESULTS — detection[].prevalence on cookie phenomena
==============================================================================
210 prevalence strings across 107 of the 117 cookie-measuring papers.
metric/prevalence names the unit, often not the population: every figure the page
publishes has had its denominator read out of the paper by hand (section 11).
 
  2010 CCS      cookie stealing
      48 same-origin, 38 same-domain, and 17 whitelist violations
  2010 WWW      Cookie overestimation
      991 cookies for 171 participants, producing 5.8x inflation
  2010 WWW      Cookie clearing
      43% admitted clearing cookies at least once a week or more often
  2010 IEEE-SP  DOM-cookie interplay
      81% read document.cookie; 76% wrote cookie values; 46% changed cookie domains
  2010 IEEE-SP  HttpOnly cookie access via XMLHttpRequest
      0.30% manipulated cookie headers in XMLHttpRequest responses
  2011 CCS      HttpOnly credential-cookie adoption
      Zan applied HttpOnly automatically to 110 of 136 websites; it correctly identified authentication cookies for 103.
  2011 IMC      cookie replay attacks
      One cookie appeared across 666,429 different 24-bit IP subnets and 236 publisher accounts
  2012 NDSS     Cookie churn
      47.86% of first-day cookie IDs never returned within the month
  2012 NDSS     Returning users behind churned cookies
      88.03% corresponded to returning users
  2012 NDSS     Cookie-forwarding attack
      Over 75,000 Hotmail accounts were associated with the suspicious source IP
  2014 WWW      authentication-cookie identification
      103 of 327 cookies
  2014 WWW      authentication-cookie detector performance
      Existing detectors produced 8–55 false negatives and 37–105 false positives.
  2014 WWW      machine-learned cookie classification
      FT achieved 81% sensitivity and 85% specificity.
  2014 CCS      Flash-cookie HTTP respawning
      33 Flash cookies respawned 355 cookies on 107 first-party domains
  2014 CCS      IndexedDB evercookie
      20 out of 100,000 sites used IndexedDB; one matched a Flash cookie
  2014 CCS      cookie synchronization
      Disabling third-party cookies reduced synced IDs and parties by nearly a factor of two
  2014 CCS      respawned-ID cookie syncing
      At least 11% of a user's history could be tracked over time
  2015 USENIX   TLS secure-cookie recovery
      More than 94% with 9 · 227 ciphertexts and 223 candidates.
  2015 USENIX   TLS cookie recovery in practice
      A 16-byte cookie was recovered after 52 hours and 6.2 · 227 ciphertexts.
  2015 USENIX   Shared-domain cookie injection
      12 of 13 tested shared domains; 72KB cookies successfully triggered DoS
  2015 USENIX   Secure cookies over HTTP
      152 of 48,039 responding domains (0.32%)
  2015 USENIX   Duplicate-name cookies
      570 of 48,039 responding domains (1.19%)
  2015 USENIX   Browser cookie implementation flaws
      All major browsers exhibited at least some documented inconsistencies or vulnerabilities
  2015 USENIX   Real-world cookie injection attacks
      Included Google, Amazon, eBay, Apple, Bank of America, BitBucket, and open-source applications
  2015 USENIX   Secure-cookie extension compatibility
      One broken case among Alexa top 40 websites
  2015 WWW      cookie-based traffic clustering
      62.4±3.2% after 200 sites for AOL profiles; 72.9±1% for Alexa profiles
  2015 IMC      affiliate cookie stuffing
      12,033 affiliate cookies from 11.7K domains
  2015 IMC      cookie-stuffing prevalence
      over 475K domains visited
  2015 NDSS     HSTS cookie exposure
      23.8% (182/765) preloaded; 47.8% (2,460/5,099) dynamic
  2015 NDSS     Pinned cookie exposure
      75 cookies on 5 pinned domains; 63 (84.0%) lacked secure
  2015 WWW      cookie stealing
      Attack worked for both Twitter and Facebook in Layar
  2016 CCS      ID cookies
      32 sites contained ID cookies when third-party cookies were blocked.
  2016 CCS      cookie syncing
      45 of the top 50 and 85 of the top 100 third parties synced cookies with at least one other party.
  2016 USENIX   cookie-based tracking
      the first cookie-based tracker in the dataset appeared in 1996
  2016 USENIX   Cookie matching
      forward matching 69%, backward matching 55% before clustering
  2016 USENIX   Heuristic cookie-matching detection failures
      31% of cookie-matching partners were missed; 4.1% of chains were completely missed
  2016 WWW      first- and third-party cookie prevalence
      68.0% (63.42%) of cookies were third-party; 94.6% (94.38%) of successfully visited sites set cookies.
  2016 WWW      cookie attribute characteristics
      99.64% (99.76%) of cookies lacked the Secure flag.
  2016 WWW      maximal-permission cookies
      80.6% (79.73%) of harvested cookies had maximal permissions.
  2016 WWW      cookie information leakage
      Google, Twitter, Yahoo, YouTube, and Rubiconproject showed different leakage rates across synthetic user profiles.
  2016 IEEE-SP  HTTP cookie hijacking exposure
      282,459 accounts exposing cookies during 30 days
  2016 IEEE-SP  Campus HTTP cookie exposure
      282,459 vulnerable accounts; 29,908,099 HTTP requests to audited domains
  2016 IEEE-SP  Browser-component cookie exposure
      Every Firefox extension tested exposed the required cookies.
  2016 IEEE-SP  Mobile-app cookie exposure
      Both platforms had official apps using unencrypted connections.
  2017 PETS     Cookie syncing
      106 domains transmitted cookie IDs to 210 different domains
  2017 PETS     Cross-device reuse of cookie values
      No third parties were detected using the same cookie values across multiple devices
  2018 USENIX   Facebook cookie exposure
      5,729 unique vulnerable cookies over four months
  2018 USENIX   third-party cookie-policy bypasses
      virtually every browser and extension policy could be bypassed
  2018 USENIX   same-site cookie bypasses
      incorrect behaviors were detected for Chrome, Opera and Edge
  2018 WWW      Cookie Synchronization
      97% of regular users were exposed at least once
  2019 IEEE-SP  cookie access
      8 Chrome extensions
  2019 IEEE-SP  session cookie confidentiality
      412 websites (10.2%)
  2019 IEEE-SP  session cookie integrity
      543 websites (13.5%)
  2019 IMC      third-party HTTP cookies
      72% of the corpus contained third-party cookies
  2019 IMC      cookie synchronization
      2,867 websites, covering 58% of the top-100 popular sites
  2019 IMC      cookie consent banners
      4.41% in the EU and 3.76% in the USA
  2019 NDSS     cookie-consent notices
      62.1% in May 2018, up from 46.1% in January
  2019 NDSS     cookies
      about 5.4 third-party cookies on average
  2019 NDSS     cookie-consent library prevalence
      15.4% in July 2018
  2019 PETS     Third-party cookie installation
      74% of websites install third-party cookies
  2019 PETS     Profiling-cookie installation
      49% of popular websites
  2019 PETS     Consent-related cookie installation
      80.5% install profiling cookies before consent
  2019 PETS     Longitudinal cookie-law violations
      57% in January 2015 and 56% in November 2018
  2019 WWW      Cookie synchronization
      97% of regular web users were exposed to CSync
  2019 WWW      Cookie synchronization
      263,635 synchronization events involving 22,329 unique synced userIDs
  2019 WWW      Cookie identifier leakage
      The median userID was leaked to 3.5 different domains
  2020 CCS      authentication-cookie exposure over HTTP
      12,014 domains (48.43%) initially; 10,921 remained vulnerable after HSTS analysis
  2020 CCS      JavaScript cookie stealing exposure
      5,680 domains (22.9%) lacked httpOnly protection; 5,099 also embedded third-party scripts
  2020 CCS      personal-data leakage after cookie hijacking
      9,324 domains according to the abstract; Table 3 reports 9,122 (78%)
  2020 CCS      authentication-cookie combinations
      1.21 authentication cookies and 1.1 combinations on average
  2020 PETS     HTTP cookie tracking
      5,574 different trackers: 695 mobile-specific, 1,536 desktop-specific, and 3,343 shared
  2020 PETS     client-side cookie syncing
      4 of 15 inferred relationships detected by client-side cookie syncing
  2020 PETS     identifier cookies
      5,295 cookie instances (0.87%) had an identifier cookie as key
  2020 PETS     first-to-third-party cookie syncing
      67.96% of visited domains
  2020 USENIX   Invalid cookie computation
      Four implementations incorrectly computed cookie values
  2020 WWW      subsite cookie usage
      Subsites set 36% more cookies: 78 versus 55 on landing pages.
  2020 WWW      cookie purposes
      99% of classified cookies were used for tracking or targeted advertising.
  2020 WWW      undesired cookies
      around 95% of domains created undesired cookies
  2020 WWW      first-party cookie bypass
      87% resulted in at least one new domain being added to the whitelist
  2020 WWW      third-party cookie tracking
      right-leaning websites tracked users with up to 25% more cookies
  2020 WWW      cookie synchronization
      right-leaning websites facilitated up to 50% more synchronizations
  2020 IEEE-SP  TCF cookie banners
      1,426 of 22,949 websites (6.2%)
  2020 IEEE-SP  Shared-cookie consent reuse
      62 of 1,426 websites (4.3%) returned the same consent string
  2021 NDSS     cookie security-attribute inconsistency
      1,546 (4%) cookies from 642 (9%) sites
  2021 NDSS     cookie leakage through HSTS inconsistencies
      1,783 sites, or 33% of sites activating HSTS
  2021 PETS     Cookie notices and consent prompts
      5% overall error rate in manual checking
  2021 PETS     Cookie leaks in HTTP headers
      95% of sites with an identified CNAME tracker had one or more cookie leaks.
  2021 PETS     Cookie leaks in POST bodies
      166 cookies on 94 distinct sites were sent in POST bodies.
  2021 PETS     Cookie leaks in request URLs
      1,899 cookie leaks on 1,295 distinct sites.
  2021 PETS     cookie syncing
      8 Cookie_sync predicates for the Top 50 domains.
  2021 USENIX   cookie confidentiality and integrity
      3,390 (14%) confidentiality-affected and 24,689 (99%) integrity-affected session cookies
  2021 WWW      external first-party cookies
      9,772 of 10,000 websites (97.72%)
  2021 WWW      tracking-ID cookies
      4,212 of 13,323 (31.61%)
  2021 WWW      tainted cookie leakage
      3,256 of 4,212 (77.30%)
  2021 WWW      cross-domain cookie sharing
      5,635 of 9,772 websites (57.66%)
  2021 WWW      fingerprinting-generated cookies
      3 cookies highly indicative of fingerprinting
  2022 CCS      opt-out cookies
      84% F1, 97% precision, and 74% recall on the test set
  2022 CCS      Cookie security-attribute modification
      31 extensions modified the security properties of cookies
  2022 NDSS     cookie manipulation
      736 vulnerabilities
  2022 PETS     cookie syncing
      7 advertisers engaged in cookie syncing; 4 synced with an Alphabet-owned tracker.
  2022 PETS     Cookie-notice practices
      Only 14 websites presented Accept without highlighting it; three allowed rejection as easily as acceptance.
  2022 PETS     cookie respawning with browser fingerprinting
      1,150 of 30,000 websites (3.83%)
  2022 PETS     third-party tracking in Cookie Script report
      41 third-party requests and 6 cookies were deposited without prior consent
  2022 USENIX   Incorrect cookie purposes
      36.4% had at least one incorrectly assigned cookie purpose
  2022 USENIX   Unclassified or undeclared cookies
      85.8% had at least one cookie with a missing declaration or missing purpose
  2022 USENIX   Cookie expiration discrepancies
      9.1% showed at least one discrepancy
  2022 USENIX   Cookies before consent
      69.7% of examined websites
  2022 USENIX   Cookies despite negative consent
      21.3% of 29,398 websites
  2022 USENIX   Multiple cookie labels
      2.3% of examined websites
  2022 USENIX   Cookie-purpose majority outliers
      30.9% contained at least one outlier assignment
  2022 USENIX   cookie syncing
      More than half of request chains in most configurations participated in cookie syncing.
  2022 USENIX   Cross-browser cookie synchronization
      256 random bits transmitted without error
  2022 USENIX   cookie security inconsistencies
      16 intra-test; 167 inter-test inconsistencies
  2022 WWW      persistent tracking cookies
      13% (19,566) contained YouTube cookies expiring in 9999
  2022 IEEE-SP  Session-cookie leakage
      Recovered an HttpOnly session cookie after Chrome developer tools copied it into renderer memory.
  2022 IEEE-SP  SameSite cookie adoption
      18.94% of sites adopted one of the three valid policies by March 2021
  2022 IEEE-SP  Cookie persistence after login
      48% accepted cookies 40 days after the initial login
  2022 IEEE-SP  cookie creation
      137,997,677 cookies
  2022 IEEE-SP  identifier cookies
      48% (66.7M) classified as identifiers
  2022 IEEE-SP  cookie sharing
      8.97M events over 387K websites
  2022 IEEE-SP  cookie collisions
      184,377 collision events
  2022 IEEE-SP  cookie ghostwriting
      28M ghosted cookies versus 7.6M primary first-party cookies
  2022 IEEE-SP  risky cookie actors
      9% of safe websites included a dangerous domain
  2023 CCS      First-party tracking cookies
      89.86% of the 20K websites
  2023 CCS      Third-party ghostwriting of first-party cookies
      96.61% were set by third-party embedded scripts
  2023 CCS      Fingerprinting scripts setting cookies
      1,908 out of 20K sites
  2023 CCS      CookieGraph classification
      90.18% accuracy, 90.07% precision, and 92.09% recall
  2023 IMC      cookie measurement variance
      42% of cookies appear in only one profile
  2023 PETS     Persistent-session cookie-like storage
      Mobile Opera and Samsung Internet retained sessions after cookie and site-data deletion.
  2023 USENIX   Cookie-stealing resistance
      10 of 46 blocking sites blocked access after cookie copying
  2023 IMC      cookiewall prevalence
      280 of 45,222 websites (0.6%)
  2023 IMC      cookiewall detection
      98.2% precision; 100% precision and recall on 1,000 sampled websites
  2023 IMC      tracking cookies
      Cookiewalls sent 43 versus 1 tracking cookie; 42 times more
  2023 IMC      Cookie syncing
      41 advertisers synced cookies with Amazon and 247 other third parties
  2023 USENIX   cookie notice detection
      986 of 2000 domains identified as having cookie notices; 16 false negatives and 2 false positives
  2023 USENIX   end-to-end cookie enforcement
      93.7% (937/1000 websites)
  2023 USENIX   cookie notices at scale
      52.7% of 85,473 analyzed websites
  2023 USENIX   multiple-view cookie notices
      35.4% had multiple views; 64.6% had a single-view notice
  2023 PETS     third-party cookies without consent
      7.34% of sites with at least one privacy issue
  2023 PETS     third-party cookies before consent
      7.57% of sites with at least one privacy issue
  2023 USENIX   cookie churn
      merge misses detected in only 29 groups
  2023 PETS     Cookie-banner prevalence
      2,220 websites (35.74%) had a cookie banner.
  2023 USENIX   cookie-prefix and nameless-cookie adoption
      More than 70% of top-1K origins used Secure cookies; 133 origins used __Host- in 2022 versus 77 in 2021.
  2023 IEEE-SP  Cookie rejection handling
      52.38% detected rejection; 40.48% traced to the correct UI element; 7.14% neither
  2023 IEEE-SP  cookie acceptance inference
      749 additional sites vulnerable, reaching 34% overall
  2024 IMC      Cookie-notice tracking-cookie violations
      100 (39%) of 255 websites continued using tracking cookies after rejection
  2024 IMC      Third-party-cookie rendering effects
      More than 90% of domains exhibited less than a 10% screenshot difference
  2024 CCS      First-party tracking cookies
      150 of 14,867 ghost first-party cookies
  2024 CCS      Third-party-cookie re-identification
      Analysts using third-party cookies always succeeded on average.
  2024 PETS     website breakage from cookie misclassification
      18 of 40 participants required a prompt
  2024 PETS     CookieBlock mental-model accuracy
      Before: 15 inaccurate, 11 partially accurate, 14 accurate; After: 14, 12, and 12
  2024 PETS     Cookie-category comprehension
      7% correctly identified the original functional-cookie definition; 67% identified anonymous analytics.
  2024 PETS     USP String cookie storage
      358 of 10,000 publishers (3.6%) stored a USP String in a cookie
  2024 PETS     cookie acceptance
      PPA mean 76, PA mean 99, and control mean 173 accepted cookies
  2024 PETS     cookie-banner usability
      PPA mean 83, PA mean 72, and control mean 63 SUS scores
  2024 PETS     cookie-banner dark nudges
      Four out of seven pages used dark nudges
  2024 PETS     identifier-cookie tracking
      474 of 996 cloaked domains (47.59%)
  2024 PETS     cookie-purpose distribution
      35%
  2024 USENIX   Cookie notice detection
      100.0% precision and 86.9% recall
  2024 USENIX   Cookie consent violations
      72.2% of successfully crawled websites contained at least one privacy violation
  2024 USENIX   Undeclared cookie purposes
      26.1% of 48,843 websites
  2024 USENIX   cookie consent banner presence
      37% (1511) of the total dataset included a cookie consent notice
  2024 USENIX   cookie changes after rejection
      Only 7 local and 2 remote websites rejected cookies successfully on all tested websites
  2024 USENIX   cookie-banner text complexity
      Italian banners were most complex and UK banners least complex
  2024 PETS     Cookie setting and persistence
      415k cookies per profile on average
  2024 PETS     Cookie-purpose categories
      57% of all cookies classified; 38% of distinct cookies
  2024 PETS     Cookie-banner interaction
      Extensions interacted with 12 banners on average, or 65%
  2024 PETS     First-party cookie effects
      fbp did not improve effectiveness; fbc increased effectiveness from 20% to 23%
  2024 PETS     Client-side cookie syncing
      Cookie syncing persisted after opt-out across CMPs and jurisdictions.
  2024 USENIX   Plaintext cookie storage
      only two apps encrypted cookies; 66 stored sensitive information
  2024 USENIX   Cookie-consent decisions
      17% on the control banner; 34% for highlighted decline; 47% for consequences
  2024 USENIX   Cookie knowledge and privacy preferences
      62% knew browsing history was collected; 61% knew cookies personalize ads.
  2024 WWW      Tracking cookies after consent rejection
      Compliant, non-empty-TC domains averaged 1.28 tracking cookies; all domains averaged 1.11.
  2024 USENIX   Cookie and Mixed Content flaws
      Five invariants had at least one violation
  2024 WWW      Private-mode cookie storage
      17 browsers, 34.7%
  2024 WWW      Third-party cookie persistence
      4 browsers, 8.2%
  2024 WWW      Cookie sharing across modes
      16 browsers, 32.7%
  2025 IMC      cross-domain cookie exfiltration
      55.7% of websites; 5.9% of 82,000 unique cookie pairs
  2025 IMC      cross-domain cookie overwriting
      31.5% of websites; 2.72% of unique cookie pairs
  2025 IMC      cross-domain cookie deletion
      6.3% of websites; 1.8% of unique cookie pairs
  2025 IMC      CookieGuard access-control effectiveness
      82.2% overwriting, 86.2% deletion, and 83.2% exfiltration reductions
  2025 IMC      CookieGuard runtime overhead
      average overhead of 0.3 seconds across 8,171 paired sites
  2025 PETS     AA cookies after revocation
      57.5% (69/120) retained AA cookies after revocation
  2025 PETS     intractable cookie transmission
      around 50% of websites; approximately 45%–55% across runs
  2025 PETS     cookie persistence
      nearly 60% of cookies have expiration exceeding 10 days
  2025 PETS     cookie synchronization
      76 of 2,545 unique intractable cookies, or 3%
  2025 PETS     partitioned-cookie adoption
      40 of 3,177 tracking cookies, or 1.3%; 26 had accompanying non-partitioned cookies
  2025 PETS     tracking cookies
      236 websites loaded 9,885 cookies containing 1,153 unique identifiers
  2025 WWW      trackers and third-party cookies
      Developed sites averaged approximately nine trackers; developing sites averaged six
  2025 WWW      Set-Cookie misconfiguration
      Over 98% set the Path directive to '/,' making cookies accessible across all directories.
  2025 WWW      Third-party cookie accesses
      89.84% of all cookie accesses
  2025 WWW      Host-created cookies accessed by third parties
      20.14% of all cookies accessed by third-party scripts
  2025 USENIX   cookie consent violations
      96.18% in the EU to 97.72% in the US
  2025 USENIX   ignored cookie rejection
      43.12% of cookies ignored consent rejections
  2025 USENIX   undeclared cookies
      47.35% of personal information cookies
  2025 USENIX   wrong cookie category
      3.13% of websites
  2025 USENIX   personal information in cookies
      roughly 75% likely involve personal information
  2025 WWW      potential cookie purpose violation
      44.1% of websites suffer from potential purpose violation
  2025 WWW      potentially non-compliant cookies
      3,759 of 10,846 observed cookies (34.7%)
  2025 WWW      unclaimed cookie usage
      511 cookies among 289 websites
  2025 WWW      missing cookie declarations
      25.4% of websites fail to provide cookie declarations
  2025 WWW      cookie-purpose classification
      F1 score of 0.95
  2025 CCS      Third-party cookies
      1,454 banks (70.1%) allowed third-party cookies; 1,252 (60.4%) had marketing cookies
  2025 PETS     Cookies and impression pixels
      39.3% of WebViews ran JavaScript setting at least one cookie or impression pixel
  2025 PETS     Cookie synchronization and ID bridging
      Cookie synchronization involved 1,190 SLDs, with 44% associated with ATSes
  2025 PETS     Third-party tracking cookies
      less than 51% across all locations
  2025 PETS     cookie setting
      20,526,074 distinct cookies; 22% of all cookies
  2025 WWW      cookie restoration
      378 restoration instances across 90 unique cookie-key and host pairs.
  2025 USENIX   Credential versus session-cookie sharing
      87.9% credentials and 12.1% session cookies
  2026 PETS     gclid cookie persistence
      64 of 76 advertisers stored gclid as a first-party cookie
 
==============================================================================
11. QUOTE SPOT-CHECK — every figure the page states, against paper.cols.txt
==============================================================================
  8-word run  2023 CCS :: First-party tracking cookies
      prevalence: 89.86% of the 20K websites
      quote: We find that 89.86% of sites deploy at least one first-party ATS cookie.
  8-word run  2023 CCS :: Third-party ghostwriting of first-party cookies
      prevalence: 96.61% were set by third-party embedded scripts
      quote: The vast majority (96.61%) of the first-party ATS cookies are set by third-party embedded scripts served from a total of 2,099 unique domains.
  8-word run  2023 CCS :: CookieGraph classification
      prevalence: 90.18% accuracy, 90.07% precision, and 92.09% recall
      quote: The classifier has 90.07% precision and 92.09% recall, with an overall accuracy of 90.18%.
  EXACT       2022 USENIX :: Incorrect cookie purposes
      prevalence: 36.4% had at least one incorrectly assigned cookie purpose
      quote: In 36.4%, we found at least one cookie with an incorrectly assigned purpose
  EXACT       2022 USENIX :: Unclassified or undeclared cookies
      prevalence: 85.8% had at least one cookie with a missing declaration or missing purpose
      quote: in 85.8%, there was at least one cookie with a missing declaration or missing purpose.
  EXACT       2022 USENIX :: Cookie-purpose majority outliers
      prevalence: 30.9% contained at least one outlier assignment
      quote: We find that 30.9% of websites contain at least one third-party cookie with a purpose that disagrees with a corresponding two-thirds majority.
  EXACT       2025 WWW :: cookie-purpose classification
      prevalence: F1 score of 0.95
      quote: Coover demonstrates a superior performance, achieving an F1 score of 0.95
  EXACT       2025 WWW :: potential cookie purpose violation
      prevalence: 44.1% of websites suffer from potential purpose violation
      quote: It finds that 44.1% of the websites potential suffer from purpose noncompliance issues.
  EXACT       2025 WWW :: missing cookie declarations
      prevalence: 25.4% of websites fail to provide cookie declarations
      quote: Around 25.4% of websites fail to provide the cookie declaration for users.
  EXACT       2024 IMC :: Cookie-notice tracking-cookie violations
      prevalence: 100 (39%) of 255 websites continued using tracking cookies after rejection
      quote: we found that 100 (39%) of them do not respect the user's choice and continue to use tracking cookies even after the user opts out
  EXACT       2024 PETS :: Cookie-purpose categories
      prevalence: 57% of all cookies classified; 38% of distinct cookies
      quote: Using Cookiepedia, we could classify 57% of all cookies and 38% of all distinct cookies in our dataset
  EXACT       2024 USENIX :: Undeclared cookie purposes
      prevalence: 26.1% of 48,843 websites
      quote: We found that 26.1% of the 48,843 websites with cookie notices use AA cookies without declaring AA purposes in the initial text of the cookie notice.
  EXACT       2025 USENIX :: wrong cookie category
      prevalence: 3.13% of websites
      quote: We also detected contradictory cookie banners on 3.13% of websites (Wrong Cookie Category Violation).
  EXACT       2025 USENIX :: personal information in cookies
      prevalence: roughly 75% likely involve personal information
      quote: Roughly 75% of all cookies found in our measurement likely involve personal information.
  8-word run  2025 PETS :: partitioned-cookie adoption
      prevalence: 40 of 3,177 tracking cookies, or 1.3%; 26 had accompanying non-partitioned cookies
      quote: among 3,177 unique tracking cookies, only 40 (1.3%) are partitioned, of which 26 are accompanied by non-partitioned tracking cookies
  EXACT       2025 WWW :: Third-party cookie accesses
      prevalence: 89.84% of all cookie accesses
      quote: In total, 89.84%, 90.98%, and 72.49% of all cookies, localstorage, and IndexedDB accesses (both read and write), respectively, are done by third-party JS.
  8-word run  2024 PETS :: Cookie-category comprehension
      prevalence: 7% correctly identified the original functional-cookie definition; 67% identified anonymous analytics.
      quote: Only 7% of participants were able to correctly identify the definition for the original term "functional" cookies. ... 67% selected the correct definition for the candidate term "anonymous analytics"
  EXACT       2022 IEEE-SP :: identifier cookies
      prevalence: 48% (66.7M) classified as identifiers
      quote: we classify 48% (66.7M) as identifiers with the zxcvbn technique described in Section III-A.
 
  18 figures checked: 13 exact, 5 via an 8-word run, 0 not found.
 
==============================================================================
DONE
==============================================================================
report_cookies.mjs
#!/usr/bin/env node
// Report script for the wiki page privacy:cookies ("Classifying Cookies").
//
//   node scripts/report_cookies.mjs            # full audit trail
//   node scripts/report_cookies.mjs --wiki     # the tables the page carries
//
// Every figure prints its own denominator. Counts are of PAPERS, never tuples.
// Sentinels (not-stated / none-mentioned / not-applicable) are never counted as
// answers. Free-text names are folded before aggregating and every fold prints
// its unmapped residue.
//
// Three passes:
//
//   PASS A  structured extraction, data/extract/run1/extractions.jsonl.
//           The page's core population is `classification[].target == "cookie"`,
//           which is an enum and therefore stable. The wider "measures
//           something about cookies" set adds detection[].phenomenon matches
//           and is used only for context and for the measured-results table.
//
//   PASS B  a hand-keyed map from the free-text `resourceName` of every cookie
//           classification tuple to (a) the FAMILY of label source and (b) the
//           QUESTION the classifier answers. The script THROWS if a tuple's
//           resourceName is not in the map, so a corpus refresh cannot silently
//           drop a paper out of a family. This is the split the page publishes;
//           it is produced here, not written by hand into the prose.
//
//   PASS C  full text, data/fulltext/<year>/<venue>/<slug>/paper.cols.txt.
//           Whitespace collapsed and end-of-line hyphenation joined first: a
//           PDF line break inside "Cookie-\npedia" otherwise undercounts.
//           Used for the label sources that are not in the schema at all
//           (Open Cookie Database, cookiesearch.org) and for the entropy and
//           LLM probes, and to spot-check evidence quotes.
 
import fs from 'node:fs';
import path from 'node:path';
import { dataRoot, loadExtractions, isSentinel, table, wikiTable, pct } from './lib.mjs';
 
const WIKI = process.argv.includes('--wiki');
const ROOT = dataRoot();
const FT = path.join(ROOT, 'fulltext');
const h = (s) => console.log('\n' + '='.repeat(78) + '\n' + s + '\n' + '='.repeat(78));
const T = (head, rows) => console.log(WIKI ? wikiTable(head, rows) : table(head, rows));
const key = (p) => `${p.venue}/${p.year}/${p.slug}`;
 
const rows = loadExtractions();
 
// ---------------------------------------------------------------------------
// PASS B — the hand-keyed map. Keyed on the exact resourceName string of a
// cookie-target classification tuple.
//
// family:   what kind of thing does the labelling.
// question: WHAT is being decided about the cookie. The literature routinely
//           conflates four different questions under "cookie classification",
//           and mixing them is how a page ends up saying the field classifies
//           cookie purposes when a third of it is detecting identifiers.
//
//   purpose     which of N purpose categories (necessary / functional /
//               analytics / advertising, or the CMP's own scheme)
//   tracking    binary: does this cookie belong to a tracker, decided from the
//               provenance of the resource that set it (filter list, tracker DB)
//   identifier  binary: does the VALUE carry a per-user identifier
//   party       first vs third party, eTLD+1, who ghostwrote it
//   security    authentication/session role, or correctness of the attributes
//   other       anything else, named individually below
// ---------------------------------------------------------------------------
const RESOURCE = {
  // --- purpose: the commercial and community cookie databases
  'Cookiepedia': ['purpose-database', 'purpose'],
  'Cookie-Script': ['purpose-database', 'purpose'],
  'Cookie Script': ['purpose-database', 'purpose'],
  'Cookiedatabase.org': ['purpose-database', 'purpose'],
  'Cookie Database': ['purpose-database', 'purpose'],
  // --- purpose: published cookie classifiers, reused off the shelf
  'CookieBlock': ['published-classifier', 'purpose'],
  'CookieGraph': ['published-classifier', 'tracking'],
  'WebGraph': ['published-classifier', 'tracking'],
  // --- purpose: the paper trains its own supervised model
  'XGBoost (custom)': ['own-supervised-ml', 'purpose'],
  'random forest (custom)': ['own-supervised-ml', 'tracking'],
  'functional tree (FT)': ['own-supervised-ml', 'security'],
  // --- purpose: LLM
  'GPT-3.5-turbo (custom fine-tuned model)': ['llm', 'purpose'],
  'GPT-3.5': ['llm', 'purpose'],
  // --- purpose: humans
  'three independent authors': ['manual', 'purpose'],
  'custom gold-set labeling procedure': ['manual', 'security'],
  'custom keyword mapping': ['own-rule', 'purpose'],
  // --- tracking: filter lists and tracker databases (provenance of the setter)
  'EasyList': ['filter-list', 'tracking'],
  'EasyList/EasyPrivacy': ['filter-list', 'tracking'],
  'justdomains': ['filter-list', 'tracking'],
  'justdomains blocklist': ['filter-list', 'tracking'],
  'Ghostery': ['filter-list', 'tracking'],
  'Ghostery and Disconnect intersection': ['filter-list', 'tracking'],
  'Disconnect.me': ['filter-list', 'tracking'],
  'custom ad-blocker name search lists': ['own-rule', 'other'],
  'Evidon Global Opt-out, DAA Protect My Choice, and Google Keep My Opt-Outs':
    ['opt-out-registry', 'other'],
  // --- identifier: value-based heuristics
  'zxcvbn': ['identifier-heuristic', 'identifier'],
  'custom ID-cookie heuristic': ['identifier-heuristic', 'identifier'],
  'custom ID-cookie heuristics': ['identifier-heuristic', 'identifier'],
  'custom ID-cookie criteria': ['identifier-heuristic', 'identifier'],
  'custom ID-detection algorithm': ['identifier-heuristic', 'identifier'],
  'custom identifier-cookie detection algorithm': ['identifier-heuristic', 'identifier'],
  'custom identifier-detection heuristic': ['identifier-heuristic', 'identifier'],
  'custom identifier detection pipeline': ['identifier-heuristic', 'identifier'],
  'custom unique-ID parser': ['identifier-heuristic', 'identifier'],
  'unique-ID cookie heuristics (custom)': ['identifier-heuristic', 'identifier'],
  'custom tracking-ID detection algorithm': ['identifier-heuristic', 'identifier'],
  'custom persistent-identifier detection rules': ['identifier-heuristic', 'identifier'],
  'potentially identifying cookie flow heuristic (custom)': ['identifier-heuristic', 'identifier'],
  'BehaviorTrack': ['identifier-heuristic', 'identifier'],
  'custom personal-information detector': ['own-rule', 'other'],
  'custom regular expressions': ['own-rule', 'identifier'],
  'matching patterns (custom)': ['own-rule', 'other'],
  'custom affiliate-cookie parser (AffTracker)': ['own-rule', 'other'],
  'heuristic proposed in previous work': ['identifier-heuristic', 'identifier'],
  // --- syncing detectors that the extractor filed as cookie classification.
  // They decide "did this value travel", which is the cookie_syncing page's
  // question, not this page's. Kept visible rather than dropped.
  'custom cookie-synchronization rules': ['own-rule', 'other'],
  'custom Cookie Synchronization heuristics': ['own-rule', 'other'],
  'cookie-syncing heuristic (custom)': ['own-rule', 'other'],
  'cookie-syncing script (adapted)': ['own-rule', 'other'],
  'custom cross-domain attribution and exfiltration pipeline': ['own-rule', 'other'],
  // --- party / scope
  'Public Suffix List': ['party-rule', 'party'],
  'custom host-domain comparison': ['party-rule', 'party'],
  // --- security role and attribute correctness
  'custom Zan credential-cookie classifier': ['own-rule', 'security'],
  'hand-coded rules for SessionShield, Serene, CookiExt, and Zan': ['own-rule', 'security'],
  'random session-cookie heuristic': ['own-rule', 'security'],
  'custom cookie-scope checks': ['own-rule', 'security'],
  'custom cookie inconsistency checks': ['own-rule', 'security'],
  // --- other, each named so it is visible rather than absorbed
  'custom': ['own-rule', 'other'],                              // lifetime buckets
  'custom cookie classification algorithm': ['own-rule', 'tracking'],
  'custom intractable-cookie definition': ['own-rule', 'other'],
  'custom segmentation rules': ['own-rule', 'other'],           // input to the LLM
  'ConsentChk rule-based violation classifier': ['own-rule', 'other'],
};
 
const FAMILY_LABEL = {
  'purpose-database': 'Cookie purpose database (Cookiepedia, Cookie-Script, cookiedatabase.org)',
  'published-classifier': 'A published cookie classifier, reused off the shelf',
  'own-supervised-ml': 'Own supervised model trained for the paper',
  llm: 'Large language model',
  manual: 'Hand labelling by the authors',
  'filter-list': 'Filter list / tracker database (provenance of the setter)',
  'opt-out-registry': 'Opt-out tool registry',
  'identifier-heuristic': 'Identifier heuristic over the cookie value',
  'party-rule': 'First/third-party rule over the domain',
  'own-rule': 'Other hand-written rule',
};
const QUESTION_LABEL = {
  purpose: 'Purpose: which category (necessary / functional / analytics / advertising)',
  tracking: 'Tracking: does this cookie belong to a tracker',
  identifier: 'Identifier: does the value carry a per-user ID',
  party: 'Party: first or third party',
  security: 'Security role: authentication or session cookie, attribute correctness',
  other: 'Something else (named in the residue listing)',
};
 
// ---------------------------------------------------------------------------
// PASS A — populations
// ---------------------------------------------------------------------------
const cookieTuples = (p) => (p.classification ?? []).filter((c) => c.target === 'cookie');
const CLASSIFY = rows.filter((p) => cookieTuples(p).length > 0);
 
// The wider set: anything whose detection[].phenomenon names a cookie. Three of
// those are not HTTP cookies at all, and are excluded by name rather than by a
// regex, so the exclusion is arguable line by line.
const NOT_A_WEB_COOKIE = new Set([
  'DNS cookie usage',
  'SYN-cookie feedback',
  'Bloom-cookie communication overhead',
]);
const detCookie = (p) =>
  (p.detection ?? []).filter(
    (d) => /cookie/i.test(d.phenomenon) && !NOT_A_WEB_COOKIE.has(d.phenomenon)
  );
const MEASURES = rows.filter((p) => detCookie(p).length > 0 || cookieTuples(p).length > 0);
 
const CRAWLED = rows.filter(
  (p) => p.crawlConfig !== null || p.studyTypes.includes('automated-web-crawl')
);
const CLASSIFIED = rows.filter((p) => (p.classification ?? []).length > 0);
 
h('1. POPULATIONS');
T(
  ['Population', 'Papers', 'Share of 5,859'],
  [
    ['corpus (7 venues, 2010-2026)', rows.length, '100%'],
    ['classified or labelled something', CLASSIFIED.length, pct(CLASSIFIED.length, rows.length)],
    ['ran an automated web crawl', CRAWLED.length, pct(CRAWLED.length, rows.length)],
    ['>=1 classification tuple with target == "cookie"  <-- the page population',
      CLASSIFY.length, pct(CLASSIFY.length, rows.length)],
    ['measures something about cookies (classify OR a cookie detection tuple)',
      MEASURES.length, pct(MEASURES.length, rows.length)],
  ]
);
console.log(`
  The page's headline denominator is ${CLASSIFY.length}, NOT 5,859 and NOT 1,120.
  ${CLASSIFY.length} of ${CLASSIFIED.length} papers that classified anything = ${pct(CLASSIFY.length, CLASSIFIED.length)}.
  ${CLASSIFY.filter((p) => CRAWLED.includes(p)).length} of the ${CLASSIFY.length} ran a crawl.
  Excluded by name from the wider set (not HTTP cookies): ${[...NOT_A_WEB_COOKIE].join('; ')}`);
 
h('1.1 THE ' + CLASSIFY.length + ' PAPERS, BY YEAR AND VENUE');
const years = [...new Set(rows.map((p) => p.year))].sort();
T(
  ['Year', 'Cookie-classifying papers', 'Papers classifying anything', 'Share', 'Corpus that year'],
  years.map((y) => {
    const c = CLASSIFY.filter((p) => p.year === y).length;
    const d = CLASSIFIED.filter((p) => p.year === y).length;
    return [y + (y >= 2025 ? '*' : ''), c, d, pct(c, d), rows.filter((p) => p.year === y).length];
  })
);
console.log('* 2025-2026 are provisional venue-years: CCS 2026 and IMC 2026 have not been held,\n  and IEEE S&P / WWW 2026 are incompletely selected. Those rows are floors.');
 
const venues = [...new Set(rows.map((p) => p.venue))].sort();
T(
  ['Venue', 'Cookie-classifying papers', 'Papers in venue', 'Share of venue'],
  venues
    .map((v) => {
      const c = CLASSIFY.filter((p) => p.venue === v).length;
      return [v, c, rows.filter((p) => p.venue === v).length, pct(c, rows.filter((p) => p.venue === v).length)];
    })
    .sort((a, b) => b[1] - a[1])
);
 
h('1.2 THE ' + CLASSIFY.length + ' PAPERS, LISTED');
for (const p of [...CLASSIFY].sort((a, b) => a.year - b.year || a.venue.localeCompare(b.venue))) {
  console.log(`  ${p.year}  ${p.venue.padEnd(8)}  ${p.slug}`);
}
 
// ---------------------------------------------------------------------------
h('2. PASS B — FOLD OF resourceName, WITH ITS RESIDUE');
// ---------------------------------------------------------------------------
const allTuples = [];
const unmapped = new Set();
for (const p of CLASSIFY) {
  for (const c of cookieTuples(p)) {
    const m = RESOURCE[c.resourceName];
    if (!m) unmapped.add(`${key(p)} :: ${c.resourceName}`);
    else allTuples.push({ p, c, family: m[0], question: m[1] });
  }
}
if (unmapped.size) {
  console.error(`\nUNMAPPED resourceName values (${unmapped.size}):`);
  for (const u of unmapped) console.error('  ' + u);
  throw new Error(
    `${unmapped.size} cookie classification tuple(s) have a resourceName not in the ` +
      `hand-keyed RESOURCE map. Add them rather than letting the paper fall out of every family.`
  );
}
const distinct = new Set(allTuples.map((t) => t.c.resourceName));
console.log(
  `\n${allTuples.length} cookie classification tuples across ${CLASSIFY.length} papers, ` +
    `${distinct.size} distinct resourceName strings, all mapped (residue 0 by construction —\n` +
    `the script throws instead of silently dropping one). The listing in section 2.2 is what to\n` +
    `check: a zero residue means the map is complete, not that every judgement in it is right.`
);
 
const byPaper = (pred) => new Set(allTuples.filter(pred).map((t) => key(t.p))).size;
 
h('2.1 LABEL-SOURCE FAMILY  (papers, of ' + CLASSIFY.length + ' that classify a cookie)');
const fams = [...new Set(allTuples.map((t) => t.family))];
T(
  ['Family', 'Papers', 'Share of ' + CLASSIFY.length, 'Tuples'],
  fams
    .map((f) => [
      FAMILY_LABEL[f],
      byPaper((t) => t.family === f),
      pct(byPaper((t) => t.family === f), CLASSIFY.length),
      allTuples.filter((t) => t.family === f).length,
    ])
    .sort((a, b) => b[1] - a[1])
);
console.log('Multi-valued: a paper using Cookiepedia AND its own heuristic is in both rows.');
 
h('2.1b THE QUESTION BEING ANSWERED  (papers, of ' + CLASSIFY.length + ')');
const qs = ['purpose', 'tracking', 'identifier', 'party', 'security', 'other'];
T(
  ['Question', 'Papers', 'Share of ' + CLASSIFY.length, 'Tuples'],
  qs.map((q) => [
    QUESTION_LABEL[q],
    byPaper((t) => t.question === q),
    pct(byPaper((t) => t.question === q), CLASSIFY.length),
    allTuples.filter((t) => t.question === q).length,
  ])
);
 
h('2.2 EVERY TUPLE, GROUPED BY FAMILY — the listing to argue with');
for (const f of fams.sort()) {
  console.log(`\n--- ${f}: ${FAMILY_LABEL[f]}`);
  for (const t of allTuples
    .filter((x) => x.family === f)
    .sort((a, b) => a.p.year - b.p.year)) {
    console.log(
      `  ${t.p.year} ${t.p.venue.padEnd(8)} q=${t.question.padEnd(10)} ` +
        `m=${t.c.method.padEnd(18)} ${t.c.usedOrMentioned.padEnd(9)} "${t.c.resourceName}"`
    );
  }
}
 
// ---------------------------------------------------------------------------
h('3. DATING THE METHODS — label-source family by year');
// ---------------------------------------------------------------------------
// This is the table the page's currency claims rest on. Papers, per year, per
// family. `first`/`last` are the first and last year the family appears at all.
const famYear = fams.map((f) => {
  const ps = allTuples.filter((t) => t.family === f);
  const ys = [...new Set(ps.map((t) => t.p.year))].sort();
  return { f, ys, n: byPaper((t) => t.family === f) };
});
T(
  ['Family', 'Papers', 'First', 'Most recent', 'Years it appears in'],
  famYear
    .map((r) => [FAMILY_LABEL[r.f], r.n, r.ys[0], r.ys[r.ys.length - 1], r.ys.join(' ')])
    .sort((a, b) => b[1] - a[1])
);
 
h('3.1 THE SAME SPLIT IN FOUR-YEAR BUCKETS');
const BUCKETS = [
  ['2010-2015', (y) => y <= 2015],
  ['2016-2019', (y) => y >= 2016 && y <= 2019],
  ['2020-2022', (y) => y >= 2020 && y <= 2022],
  ['2023-2024', (y) => y >= 2023 && y <= 2024],
  ['2025-2026*', (y) => y >= 2025],
];
T(
  ['Family', ...BUCKETS.map((b) => b[0])],
  fams
    .map((f) => [
      FAMILY_LABEL[f],
      ...BUCKETS.map(([, pred]) => byPaper((t) => t.family === f && pred(t.p.year))),
    ])
    .sort((a, b) => b.slice(1).reduce((x, y) => x + y, 0) - a.slice(1).reduce((x, y) => x + y, 0))
);
T(
  ['(denominator) cookie-classifying papers in bucket', ...BUCKETS.map(([, pred]) => CLASSIFY.filter((p) => pred(p.year)).length)],
  []
);
 
// ---------------------------------------------------------------------------
h('4. THE PURPOSE-CLASSIFICATION SUBSET, PAPER BY PAPER');
// ---------------------------------------------------------------------------
const PURPOSE = [...new Set(allTuples.filter((t) => t.question === 'purpose').map((t) => key(t.p)))];
console.log(`${PURPOSE.length} papers answer the purpose question, of ${CLASSIFY.length} that classify a cookie.\n`);
for (const k of PURPOSE.sort()) {
  const ts = allTuples.filter((t) => key(t.p) === k);
  const p = ts[0].p;
  const srcs = ts.filter((t) => t.question === 'purpose').map((t) => `${t.c.resourceName} [${t.c.usedOrMentioned}]`);
  console.log(`  ${p.year} ${p.venue.padEnd(8)} ${p.slug}\n      ${srcs.join('; ')}`);
}
 
// ---------------------------------------------------------------------------
h('5. TAXONOMY — which category scheme, folded');
// ---------------------------------------------------------------------------
// `classification.taxonomy` is free text and nullable. The denominator is the
// papers that NAME a scheme on a cookie tuple, never all 53: reporting
// "ICC UK: 12 of 53" would count the papers that named nothing as having named
// something else.
const TAX_FOLD = [
  [/ICC|International Chamber of Commerce|strictly necessary|Strictly Necessary|necessary, functional, analytics|functionality, performance/i,
    'ICC (UK) four purposes, or a restatement of them'],
  [/GDPR-defined purposes|necessary, preference, statistics/i, 'Four GDPR-framed purposes (necessary / preference / statistics / marketing)'],
  [/Cookiepedia (categories|purposes)/i, 'Cookiepedia categories (= the ICC four plus "unknown")'],
  [/identifier|ID cook|tracking ID|high-entropy/i, 'Identifier vs non-identifier'],
  [/first-party versus third-party|first party|third-party/i, 'First vs third party'],
  [/HttpOnly|Secure|SameSite/i, 'Security attributes'],
  [/lifetime|Session, Short, Persistent/i, 'Lifetime buckets'],
  [/ATS versus Non-ATS|advertising-related|Advertising or Analytics|advertising-tracker/i, 'Advertising-and-tracking vs not'],
];
const taxTuples = allTuples.filter((t) => !isSentinel(t.c.taxonomy));
const taxPapers = new Set(taxTuples.map((t) => key(t.p)));
const taxCounts = new Map();
const taxResidue = [];
for (const t of taxTuples) {
  const m = TAX_FOLD.find(([re]) => re.test(t.c.taxonomy));
  if (!m) {
    taxResidue.push(`${t.p.year} ${t.p.venue} :: ${t.c.taxonomy}`);
    continue;
  }
  if (!taxCounts.has(m[1])) taxCounts.set(m[1], new Set());
  taxCounts.get(m[1]).add(key(t.p));
}
console.log(
  `${taxPapers.size} of ${CLASSIFY.length} papers name a category scheme on at least one cookie tuple ` +
    `(${pct(taxPapers.size, CLASSIFY.length)}).\nThe denominator below is ${taxPapers.size}, not ${CLASSIFY.length}.\n`
);
T(
  ['Scheme (folded)', 'Papers', 'Share of ' + taxPapers.size],
  [...taxCounts.entries()]
    .map(([k, v]) => [k, v.size, pct(v.size, taxPapers.size)])
    .sort((a, b) => b[1] - a[1])
);
console.log(`\nUNMAPPED RESIDUE (${taxResidue.length} tuples) — printed in full:`);
for (const r of taxResidue) console.log('  ' + r);
console.log(`\nStrict count, exact string naming the ICC or its author: ` +
  `${new Set(taxTuples.filter((t) => /ICC|International Chamber of Commerce/i.test(t.c.taxonomy)).map((t) => key(t.p))).size} papers.` +
  `\nFolded count including the restatements: ${(taxCounts.get('ICC (UK) four purposes, or a restatement of them') ?? new Set()).size} papers.` +
  `\nBoth are printed because the merge is a judgement. Every contributing string:`);
for (const t of taxTuples.filter((t) => /ICC|International Chamber of Commerce|strictly necessary|Strictly Necessary|necessary, functional, analytics|functionality, performance/i.test(t.c.taxonomy)))
  console.log(`  ${t.p.year} ${t.p.venue.padEnd(8)} "${t.c.taxonomy}"`);
 
// ---------------------------------------------------------------------------
h('6. GROUND TRUTH AND VALIDATION — where the field goes quiet');
// ---------------------------------------------------------------------------
const statedGT = new Set(allTuples.filter((t) => !isSentinel(t.c.groundTruthSource)).map((t) => key(t.p)));
const statedVal = new Set(
  allTuples.filter((t) => !isSentinel(t.c.validation) && t.c.validation !== 'none-reported').map((t) => key(t.p))
);
// Corpus comparison, same fields, over every paper that classified anything.
const allClsTuples = CLASSIFIED.flatMap((p) => (p.classification ?? []).map((c) => ({ p, c })));
const cGT = new Set(allClsTuples.filter((t) => !isSentinel(t.c.groundTruthSource)).map((t) => key(t.p)));
const cVal = new Set(
  allClsTuples.filter((t) => !isSentinel(t.c.validation) && t.c.validation !== 'none-reported').map((t) => key(t.p))
);
T(
  ['Field', 'Cookie papers stating it', 'of ' + CLASSIFY.length, 'Whole classified corpus', 'of ' + CLASSIFIED.length],
  [
    ['names a ground-truth source', statedGT.size, pct(statedGT.size, CLASSIFY.length), cGT.size, pct(cGT.size, CLASSIFIED.length)],
    ['reports any validation (not none-reported / not-applicable)', statedVal.size, pct(statedVal.size, CLASSIFY.length), cVal.size, pct(cVal.size, CLASSIFIED.length)],
  ]
);
h('6.1 VALIDATION, PER VALUE (cookie tuples; enum, so publishable as a percentage)');
const vals = [...new Set(allTuples.map((t) => t.c.validation))];
T(
  ['validation', 'Papers', 'Share of ' + CLASSIFY.length],
  vals
    .map((v) => [v, byPaper((t) => t.c.validation === v), pct(byPaper((t) => t.c.validation === v), CLASSIFY.length)])
    .sort((a, b) => b[1] - a[1])
);
h('6.2 METHOD ENUM, PER VALUE (cookie tuples), against the classified corpus');
const methods = [...new Set(allClsTuples.map((t) => t.c.method))];
T(
  ['classification.method', 'Cookie papers', 'of ' + CLASSIFY.length, 'Corpus papers', 'of ' + CLASSIFIED.length],
  methods
    .map((m) => {
      const a = byPaper((t) => t.c.method === m);
      const b = new Set(allClsTuples.filter((t) => t.c.method === m).map((t) => key(t.p))).size;
      return [m, a, pct(a, CLASSIFY.length), b, pct(b, CLASSIFIED.length)];
    })
    .sort((a, b) => b[1] - a[1])
);
 
// ---------------------------------------------------------------------------
h('7. LLM CLASSIFICATION OF COOKIES — the currency check');
// ---------------------------------------------------------------------------
// Cross-checks scripts/report_llm_currency.mjs, which computes the same figure
// for every target. If these two disagree, one of them is wrong.
const llmAnyByTarget = new Map();
const anyByTarget = new Map();
for (const p of CLASSIFIED) {
  for (const c of p.classification) {
    const t = c.target === 'other' ? 'other' : c.target;
    if (!anyByTarget.has(t)) anyByTarget.set(t, new Set());
    anyByTarget.get(t).add(key(p));
    if (c.method === 'llm') {
      if (!llmAnyByTarget.has(t)) llmAnyByTarget.set(t, new Set());
      llmAnyByTarget.get(t).add(key(p));
    }
  }
}
T(
  ['Classification target', 'Papers classifying it', 'of which use an LLM', 'Share'],
  [...anyByTarget.entries()]
    .map(([t, s]) => [t, s.size, (llmAnyByTarget.get(t) ?? new Set()).size, pct((llmAnyByTarget.get(t) ?? new Set()).size, s.size)])
    .sort((a, b) => b[2] - a[2] || b[1] - a[1])
);
console.log('\nThe cookie row is the one privacy:cookies and design:website_classification must agree on.');
for (const k of llmAnyByTarget.get('cookie') ?? []) console.log('  LLM + cookie: ' + k);
 
// ---------------------------------------------------------------------------
h('8. HOW THE COOKIE PAPERS CRAWL');
// ---------------------------------------------------------------------------
const cc = (set) => set.filter((p) => p.crawlConfig !== null);
const ccCookie = cc(CLASSIFY);
const ccAll = cc(CRAWLED);
const ccField = (set, f) => {
  const stated = set.filter((p) => !isSentinel(p.crawlConfig[f]));
  return [stated.length, pct(stated.length, set.length)];
};
console.log(`${ccCookie.length} of the ${CLASSIFY.length} cookie papers have a crawlConfig object; ${ccAll.length} of the ${CRAWLED.length} crawling papers do.\n`);
T(
  ['crawlConfig field', 'Cookie papers stating it', 'of ' + ccCookie.length, 'All crawling papers', 'of ' + ccAll.length],
  ['consentAction', 'statefulness', 'interactionDepth', 'browsers', 'headless', 'authentication'].map((f) => {
    const a = f === 'browsers'
      ? [ccCookie.filter((p) => (p.crawlConfig.browsers ?? []).some((b) => !isSentinel(b))).length]
      : ccField(ccCookie, f);
    const b = f === 'browsers'
      ? [ccAll.filter((p) => (p.crawlConfig.browsers ?? []).some((x) => !isSentinel(x))).length]
      : ccField(ccAll, f);
    return [f, a[0], pct(a[0], ccCookie.length), b[0], pct(b[0], ccAll.length)];
  })
);
h('8.1 consentAction, per value (cookie papers with a crawlConfig)');
const caVals = [...new Set(ccCookie.map((p) => p.crawlConfig.consentAction))];
T(
  ['consentAction', 'Papers', 'Share of ' + ccCookie.length],
  caVals.map((v) => {
    const n = ccCookie.filter((p) => p.crawlConfig.consentAction === v).length;
    return [v + (isSentinel(v) ? '  (sentinel — not an answer)' : ''), n, pct(n, ccCookie.length)];
  }).sort((a, b) => b[1] - a[1])
);
 
// ---------------------------------------------------------------------------
h('9. PASS C — full-text probes for what the schema cannot see');
// ---------------------------------------------------------------------------
const files = [];
for (const y of fs.readdirSync(FT).sort()) {
  const yd = path.join(FT, y);
  if (!fs.statSync(yd).isDirectory()) continue;
  for (const v of fs.readdirSync(yd).sort()) {
    const vd = path.join(yd, v);
    if (!fs.statSync(vd).isDirectory()) continue;
    for (const s of fs.readdirSync(vd).sort()) {
      const f = path.join(vd, s, 'paper.cols.txt');
      if (fs.existsSync(f)) files.push({ year: +y, venue: v, slug: s, f });
    }
  }
}
console.log(`readable paper.cols.txt files: ${files.length}   <-- denominator for every row below`);
 
// A generic word is only counted within 150 characters of "cookie": a bare
// /entropy/ matches password and DNS papers, and reporting it unqualified
// would make entropy look like a mainstream cookie method.
const nearCookie = (t, re, w = 150) => {
  for (const m of t.matchAll(re)) {
    const c = t.slice(Math.max(0, m.index - w), m.index + w);
    if (/cookie/i.test(c)) return c;
  }
  return null;
};
// The figures the page publishes as findings, each with the tuple it comes from
// (used by section 11). Declared here because the streaming probe below keeps
// only these papers' text in memory.
const CHECK = [
  ['CCS/2023/cookiegraph-understanding-and-detecting-first-party-tracking-cookies', 'First-party tracking cookies'],
  ['CCS/2023/cookiegraph-understanding-and-detecting-first-party-tracking-cookies', 'Third-party ghostwriting of first-party cookies'],
  ['CCS/2023/cookiegraph-understanding-and-detecting-first-party-tracking-cookies', 'CookieGraph classification'],
  ['USENIX/2022/automating-cookie-consent-and-gdpr-violation-detection', 'Incorrect cookie purposes'],
  ['USENIX/2022/automating-cookie-consent-and-gdpr-violation-detection', 'Unclassified or undeclared cookies'],
  ['USENIX/2022/automating-cookie-consent-and-gdpr-violation-detection', 'Cookie-purpose majority outliers'],
  ['WWW/2025/semantics-aware-cookie-purpose-compliance', 'cookie-purpose classification'],
  ['WWW/2025/semantics-aware-cookie-purpose-compliance', 'potential cookie purpose violation'],
  ['WWW/2025/semantics-aware-cookie-purpose-compliance', 'missing cookie declarations'],
  ['IMC/2024/browsing-without-third-party-cookies-what-do-you-see', 'Cookie-notice tracking-cookie violations'],
  ['PETS/2024/a-large-scale-study-of-cookie-banner-interaction-tools-and-their-impact-on-users', 'Cookie-purpose categories'],
  ['USENIX/2024/automated-large-scale-analysis-of-cookie-notice-compliance', 'Undeclared cookie purposes'],
  ['USENIX/2025/navigating-cookie-consent-violations-across-the-globe', 'wrong cookie category'],
  ['USENIX/2025/navigating-cookie-consent-violations-across-the-globe', 'personal information in cookies'],
  ['PETS/2025/intractable-cookie-crumbs-unveiling-the-nexus-of-stateful-banner-interaction-and', 'partitioned-cookie adoption'],
  ['WWW/2025/least-privilege-access-for-persistent-storage-mechanisms-in-web-browsers', 'Third-party cookie accesses'],
  ['PETS/2024/crumbling-cookie-categories-deconstructing-common-cookie-categories-to-create-ca', 'Cookie-category comprehension'],
  ['IEEE-SP/2022/journey-to-the-center-of-the-cookie-ecosystem-unraveling-actors-roles-and-relati', 'identifier cookies'],
];
const QUOTE_CHECK_KEYS = new Set(CHECK.map(([k]) => k));
 
const PROBES = {
  'Cookiepedia (name)': [/cookiepedia/gi, false],
  'CookieBlock (name)': [/cookieblock/gi, false],
  'CookieGraph (name)': [/cookiegraph/gi, false],
  '"Cookie Script" / Cookie-Script': [/cookie[\s-]?script/gi, false],
  'cookiedatabase.org': [/cookiedatabase\.org/gi, false],
  'Open Cookie Database': [/open[\s-]?cookie[\s-]?database/gi, false],
  'cookiesearch.org': [/cookiesearch/gi, false],
  'ICC / International Chamber of Commerce': [/international chamber of commerce/gi, false],
  'zxcvbn, within 150 chars of "cookie"': [/zxcvbn/gi, true],
  'entropy, within 150 chars of "cookie"': [/\bentrop/gi, true],
  'an LLM name, within 150 chars of "cookie"': [/\b(?:GPT-[0-9o]|ChatGPT|LLaMA|Llama|Gemini|Claude-|large language model)/g, true],
};
// Streamed: 5,869 full texts do not fit in memory at once. Only the papers the
// quote check needs are retained (`texts`), the rest are read, probed, dropped.
const probeHits = Object.fromEntries(Object.keys(PROBES).map((k) => [k, []]));
const texts = new Map();
for (const it of files) {
  const k = `${it.venue}/${it.year}/${it.slug}`;
  const t = fs.readFileSync(it.f, 'utf8').replace(/-\n/g, '').replace(/\s+/g, ' ');
  for (const [name, [re, needNear]] of Object.entries(PROBES)) {
    re.lastIndex = 0;
    const hit = needNear ? nearCookie(t, re) : (re.test(t) ? '(name match)' : null);
    if (hit) probeHits[name].push([k, hit]);
  }
  if (QUOTE_CHECK_KEYS.has(k)) texts.set(k, t);
}
T(
  ['Probe', 'Papers matching', 'Share of ' + files.length],
  Object.entries(probeHits).map(([n, v]) => [n, v.length, pct(v.length, files.length)])
);
console.log(`
  A name match is a MENTION, not a use: it counts reference-list entries and
  related-work sentences. It is never added to a PASS A count. The rows worth
  reading individually are the small ones:`);
for (const n of ['zxcvbn, within 150 chars of "cookie"', 'an LLM name, within 150 chars of "cookie"', '"Cookie Script" / Cookie-Script', 'cookiedatabase.org', 'Open Cookie Database', 'cookiesearch.org']) {
  console.log(`\n--- ${n}  (${probeHits[n].length})`);
  for (const [k, c] of probeHits[n]) console.log(`  ${k}\n      ...${c.slice(0, 220)}...`);
}
 
// ---------------------------------------------------------------------------
h('10. MEASURED RESULTS — detection[].prevalence on cookie phenomena');
// ---------------------------------------------------------------------------
const prevRows = [];
for (const p of MEASURES) {
  for (const d of detCookie(p)) {
    if (d.prevalence === null) continue;
    prevRows.push({ p, d });
  }
}
console.log(
  `${prevRows.length} prevalence strings across ` +
    `${new Set(prevRows.map((r) => key(r.p))).size} of the ${MEASURES.length} cookie-measuring papers.\n` +
    `metric/prevalence names the unit, often not the population: every figure the page\n` +
    `publishes has had its denominator read out of the paper by hand (section 11).\n`
);
for (const r of prevRows.sort((a, b) => a.p.year - b.p.year)) {
  console.log(`  ${r.p.year} ${r.p.venue.padEnd(8)} ${r.d.phenomenon}\n      ${r.d.prevalence}`);
}
 
// ---------------------------------------------------------------------------
h('11. QUOTE SPOT-CHECK — every figure the page states, against paper.cols.txt');
// ---------------------------------------------------------------------------
// The figures the page publishes as findings, each with the tuple it comes from.
// Matching is whitespace- and case-insensitive, falling back to the longest run
// of 8 consecutive words — the grading the dataset itself uses.
const norm = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
let exact = 0, run8 = 0, missing = 0;
for (const [k, phen] of CHECK) {
  const p = rows.find((r) => key(r) === k);
  if (!p) { console.log(`  MISSING PAPER  ${k}`); missing++; continue; }
  const d = (p.detection ?? []).find((x) => x.phenomenon === phen);
  if (!d) { console.log(`  MISSING TUPLE  ${k} :: ${phen}`); missing++; continue; }
  const text = texts.get(k);
  if (!text) { console.log(`  NO FULLTEXT    ${k}`); missing++; continue; }
  const q = norm(d.evidence.quote);
  const t = norm(text);
  let verdict;
  if (t.includes(q)) { verdict = 'EXACT'; exact++; }
  else {
    const w = q.split(' ');
    let best = 0;
    for (let i = 0; i + 8 <= w.length; i++) if (t.includes(w.slice(i, i + 8).join(' '))) best = 8;
    if (best === 8) { verdict = '8-word run'; run8++; }
    else { verdict = 'NOT FOUND'; missing++; }
  }
  console.log(`  ${verdict.padEnd(11)} ${p.year} ${p.venue} :: ${phen}\n      prevalence: ${d.prevalence}\n      quote: ${d.evidence.quote.slice(0, 200)}`);
}
console.log(`\n  ${CHECK.length} figures checked: ${exact} exact, ${run8} via an 8-word run, ${missing} not found.`);
 
h('DONE');

12. Review log

_(review pass not yet run)_

  • Classifying Cookies — the page these notes are for.
  • Corpus — how the corpus was built, and every caveat that is not specific to this page.
  • cookie_syncing — the sibling page's notes; the identifier-heuristic material lives there.
  • website_classification — the per-target LLM table is shared with that page.

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]
Bollinger, Dino; Kubicek, Karel; Cotrini, Carlos; Basin, David (2022): "Automating Cookie Consent and GDPR Violation Detection", in: 31st USENIX Security Symposium (USENIX Security 22), pp. 2893-2910. USENIX Association, Boston, MA. (Link)
[3]
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)
[4]
Lin, Maxwell; Lin, Shihan; Wu, Helen; Wang, Karen; Yang, Xiaowei (2024): "Browsing without Third-Party Cookies: What Do You See?", in: Proceedings of the ACM Internet Measurement Conference. (DOI)
[5]
Chen, Baiqi; Lyu, Jiawei; Wu, Tingmin; Chhetri, Mohan Baruwal; Bai, Guangdong (2025): "Semantics-Aware Cookie Purpose Compliance", in: Proceedings of the ACM Web Conference. (DOI)
[6]
Randall, Audrey; Snyder, Peter; Ukani, Alisha; Snoeren, Alex C.; Voelker, Geoffrey M.; Savage, Stefan; Schulman, Aaron (2022): "Measuring UID smuggling in the wild", in: Proceedings of the ACM Internet Measurement Conference. (DOI)
provenance/privacy/cookies.1789057505.txt.gz · Last modified: by karel.kubicek.claude