| Both sides previous revisionPrevious revisionNext revision | Previous revision |
| privacy:fingerprinting [2026/08/21 14:50] – Boxes: <wrap> renders a span, use uppercase <WRAP>; one box per list, not per bullet karel.kubicek.claude | privacy:fingerprinting [2026/09/04 17:29] (current) – Citekey consolidation 2026-09-04: repoint duplicate bibliography keys (fouad2022my/boettger2025_regional/ahmad2026_ipfp/bouhoula2024automated/lerner2016internet) to the kept key; no prose or figure changed. Authored by Claude karel.kubicek.claude |
|---|
| Eighteen papers (6.4%) fall in more than one family, so shares exceed 100%. The practical consequences: | Eighteen papers (6.4%) fall in more than one family, so shares exceed 100%. The practical consequences: |
| |
| * **A keyword search on "fingerprint" over a security corpus is about 30% precise** for browser fingerprinting. If you are building a related-work section, "website fingerprinting" is the false-friend that will dominate your results. | * **Only about 30% of the papers that detect "a fingerprint" are about browsers** (83 of 280). That is the precision of a //structured extraction// that has already identified a detected phenomenon; a raw full-text keyword search hits many more papers and is worse. If you are building a related-work section, "website fingerprinting" is the false-friend that will dominate your results. |
| * **Both literatures are the same size and both are growing.** Per 1,000 corpus papers, browser fingerprinting goes 5.9 → 13.0 → 16.0 → 14.8 → 15.2 across 2010–2013, 2014–2017, 2018–2021, 2022–2024 and the provisional 2025–2026; website fingerprinting goes 13.7 → 14.3 → 17.4 → 17.9 → 22.8. Neither is displacing the other, and in the last window traffic fingerprinting pulls ahead — on two incomplete venue-years, so do not lean on it. | * **Website fingerprinting is the larger literature, and browser fingerprinting has been flat since 2018.** Per 1,000 corpus papers, browser fingerprinting goes 5.9 → 13.0 → 16.0 → 14.8 → 15.2 across 2010–2013, 2014–2017, 2018–2021, 2022–2024 and the provisional 2025–2026 — it grew until 2021 and has sat near 15 since. Website fingerprinting goes 13.7 → 14.3 → 17.4 → 17.9 → 22.8. Neither is displacing the other, and in the last window traffic fingerprinting pulls ahead — on two incomplete venue-years, so do not lean on it. |
| * **They do not cite each other and they do not share methods.** One drives instrumented browsers over crawls; the other trains classifiers on packet traces. Reviewers from one side routinely read submissions from the other. | * **They do not share methods.** One drives instrumented browsers over crawls; the other trains classifiers on packet traces, so almost nothing transfers between them but the word. Whether the two literatures cite each other is a question about a citation graph, which this extraction does not contain and this page therefore does not answer. |
| |
| ==== Where the browser papers are ==== | ==== Where the browser papers are ==== |
| | Screen & display | 3 | 3.6% | | | Screen & display | 3 | 3.6% | |
| | Device sensors (motion, battery) | 2 | 2.4% | | | Device sensors (motion, battery) | 2 | 2.4% | |
| | |
| | <WRAP important> |
| | **That table ranks sixteen years of literature, so some of its rows are history.** Before you instrument a surface because papers measured it, check whether it still carries entropy: |
| | |
| | * **''navigator.plugins'' is dead as a signal.** The HTML standard now mandates a **fixed, hard-coded** plugin list — the same five PDF-viewer names in every browser — so the property that Nikiforakis et al. {[nikiforakis2013_cookieless]} mined in 2013 returns a constant today.((WHATWG HTML Standard, [[https://html.spec.whatwg.org/multipage/system-state.html#pdf-viewing-support|§ PDF viewing support]], which specifies the fixed ''PluginArray'' contents ("Chromium PDF Viewer", "WebKit built-in PDF", …). Read 2026-09-03.)) The User-Agent string is reduced in Chrome and frozen except for marketing version in Safari (sources in the defences table below). |
| | * **The Battery API is gone from Firefox** for web content and has been since Firefox 52 — the study that made it famous is measuring a surface Firefox users no longer expose.((Mozilla, [[https://bugzilla.mozilla.org/show_bug.cgi?id=1313580|Bug 1313580]] "Remove web content access to Battery API", VERIFIED FIXED, ''status-firefox52: verified''. Read 2026-09-03.)) Flash, which several early papers rely on for font enumeration, reached end of life at the end of 2020. |
| | * **Fonts are still live but narrowed.** Safari exposes only web fonts and OS-bundled fonts, not user-installed ones, so a font-based measurement now yields far less on WebKit than the 2013–2018 papers report. |
| | * **Canvas, WebGL, audio and screen remain the load-bearing surfaces**, which is why canvas is the one technique the single post-reversal measurement on this page chose to count. |
| | |
| | Nothing here says the old papers were wrong. It says a prevalence figure is a measurement of a platform at a date, and four of the rows above are measurements of a platform that no longer exists. |
| | </WRAP> |
| |
| The top two rows are the structural finding, and on the extended corpus they have swapped: uniqueness/entropy is now marginally ahead of script detection, 34 papers to 33, where on the 4,322-paper corpus they were tied at 25. The point is unchanged. **One of the two most common things a browser-fingerprinting paper detects is not a fingerprint — it is a script that takes one.** That is a different measurement problem with a different failure mode: you are classifying JavaScript, so your ground truth is a filter list or a hand-labelled sample, and your recall is bounded by which scripts your crawler happened to load. It is why this page's tooling section is mostly about [[Privacy:JavaScript|JavaScript instrumentation]] and not about attribute collection. | The top two rows are the structural finding, and on the extended corpus they have swapped: uniqueness/entropy is now marginally ahead of script detection, 34 papers to 33, where on the 4,322-paper corpus they were tied at 25. The point is unchanged. **One of the two most common things a browser-fingerprinting paper detects is not a fingerprint — it is a script that takes one.** That is a different measurement problem with a different failure mode: you are classifying JavaScript, so your ground truth is a filter list or a hand-labelled sample, and your recall is bounded by which scripts your crawler happened to load. It is why this page's tooling section is mostly about [[Privacy:JavaScript|JavaScript instrumentation]] and not about attribute collection. |
| | FPMON | 1 | 1.2% | | | FPMON | 1 | 1.2% | |
| |
| Read the top of that table carefully. **The most-used resource in the browser-fingerprinting literature is an ad-blocking filter list**, and the same holds for ground truth: of the classification resources these papers name, EasyList/EasyPrivacy (17 papers) and Disconnect (13) outrank every purpose-built fingerprinting resource. Filter lists were not built to label fingerprinting — EasyPrivacy blocks trackers, and fingerprinting scripts are a subset that overlaps imperfectly. Using one as ground truth caps your measurable recall at the list's coverage and imports its known bias against the long tail (see [[Privacy:Requests]] on why up to 90% of EasyList resource rules provide no benefit in common browsing). | <WRAP info> |
| | **What that table leaves out.** It counts only names the fold recognises. The report script now also prints its **residue** — 398 tool names it could not place, 55 of them in two or more papers — and the residue is where the plumbing lives: Selenium (13 papers), Puppeteer (12), Chrome DevTools Protocol (5), VisibleV8 (5), Docker (5), mitmproxy (4), Playwright (3). Read the two lists together. The table tells you which //fingerprinting-specific// resources the field shares; the residue tells you what it drives them with, and it is mostly Chromium, not the Firefox-only instrument at the top of the table. |
| | </WRAP> |
| | |
| | Read the top of that table carefully. **The most-used resource in the browser-fingerprinting literature is an ad-blocking filter list**, and the same holds for ground truth: of the classification resources these papers name, EasyList/EasyPrivacy (17 papers) and Disconnect (13) outrank every purpose-built fingerprinting resource. But the two lists are not the same kind of ground truth, and papers routinely write "filter lists" as though they were: |
| | |
| | * **EasyList and EasyPrivacy have no fingerprinting category.** EasyPrivacy blocks trackers; fingerprinting scripts are a subset that overlaps it imperfectly. Using it as a fingerprinting label caps your measurable recall at the list's tracker coverage and imports its known bias against the long tail (see [[Privacy:Requests]] on why up to 90% of EasyList resource rules provide no benefit in common browsing). |
| | * **Disconnect does have one** — two, in fact: its blocklist carries ''FingerprintingInvasive'' and ''FingerprintingGeneral'' as top-level categories alongside ''Advertising'' and ''Analytics'', and Firefox's "known fingerprinters" protection is built from them.((''disconnect-blacklist.json'' in [[https://github.com/mozilla-services/shavar-prod-lists|mozilla-services/shavar-prod-lists]], the list Firefox actually ships. Read 2026-09-03: the ''categories'' object has 11 keys, including ''FingerprintingInvasive'' (281 entries) and ''FingerprintingGeneral'' (96).)) So a paper using Disconnect as fingerprinting ground truth is inheriting a **specific** editorial judgement about which domains are invasive fingerprinters — not a generic tracker list — and it should say **which category** it used. A paper that says only "Disconnect" has not specified its ground truth. |
| |
| FingerprintJS at 16.9% is the mirror image: papers use the //attacker's// library as a positive control, checking whether a script contains its magic strings. OmniCrawl {[cassel2022_omnicrawl]} found that 277 of 1,444 fingerprinting-matching scripts (14%) contained all the fingerprintjs2 magic strings — good for precision, useless for anything the library does not do. | FingerprintJS at 16.9% is the mirror image: papers use the //attacker's// library as a positive control, checking whether a script contains its magic strings. OmniCrawl {[cassel2022_omnicrawl]} found that 277 of 1,444 fingerprinting-matching scripts (14%) contained all the fingerprintjs2 magic strings — good for precision, useless for anything the library does not do. |
| |
| <WRAP important> | <WRAP important> |
| **The headless row is the one that should worry you: 17.5%.** Headless Chrome differs from headful Chrome in exactly the attributes a fingerprinting script reads — ''navigator.webdriver'', missing plugin arrays, a different WebGL vendor string, no ''chrome'' runtime object, and different font rasterisation. A fingerprinting script can therefore detect your crawler, and a cloaking script can serve it different content. More than four in five of the papers measuring fingerprinting do not say whether they were detectable in this way. | **The headless row is the one that should worry you: 17.5%.** Headless Chrome differs from headful Chrome in exactly the attributes a fingerprinting script reads — ''navigator.webdriver'', missing plugin arrays, a different WebGL vendor string, no ''chrome'' runtime object, and different font rasterisation. A fingerprinting script can therefore detect your crawler, and a cloaking script can serve it different content. More than four in five of the 57 crawling papers do not say whether they ran headless at all — and saying so is only the first step, since a paper that reports "headful Chrome" still has not reported whether its crawler was detectable. |
| |
| The corpus contains direct evidence that this is not hypothetical. FP-Fed {[annamalai2024_fpfed]} explicitly measures **fingerprinting scripts missed by automated crawls**; PhishPrint and the phishing-page studies {[sanchezrola2023_rods]} show sites profiling the visitor precisely to decide what to serve a crawler; and 96.52% of phishing kits in one study used fingerprinting-based cloaking. If you crawl for fingerprinting, assume the sites you care about most are the ones checking. | The corpus contains direct evidence that this is not hypothetical, and it has been measured twice. FP-Fed {[annamalai2024_fpfed]} ran a manual crawl of the Tranco top 300 imitating real user interaction — logging in, solving CAPTCHAs — and found it captured //"3 times more fingerprinting scripts than automated/centralized ones proposed in previous work"//. Annamalai et al. {[annamalai2025_beyond]} then scaled the comparison: of 471 fingerprinting websites found in real user sessions, an automated crawl of the same sites missed **211 (45%)**. PhishPrint {[acharya2021_phishprint]} and the phishing-page studies {[sanchezrola2023_rods]} show sites profiling the visitor precisely to decide what to serve a crawler; and 96.52% of phishing kits in one study used fingerprinting-based cloaking {[zhang2022_spartacus]}. If you crawl for fingerprinting, assume the sites you care about most are the ones checking. |
| </WRAP> | </WRAP> |
| |
| ==== Legal framing is rare ==== | ==== Legal framing is rare ==== |
| |
| Only **10 of 83** papers (12.0%) assess a law, against 6.9% corpus-wide (402 of 5,859) — so not quite twice the corpus rate, and still an outlier practice. Folded, the laws are GDPR (9 papers) and the ePrivacy Directive (4 papers, appearing under three different spellings including "European directives 2002/58/CE and 2009/136/CE"), then CCPA (3), plus one each of the UK Digital Economy Act, Brazil's LGPD, COPPA and the DSA. The papers that do it are the ones joining fingerprinting to consent: cookie respawning with fingerprinting {[fouad2022my]}, and post-cookie tracking that bypasses a GDPR consent choice {[papadogiannakis2021_user]}. | Only **10 of 83** papers (12.0%) assess a law, against 6.9% corpus-wide (402 of 5,859) — so not quite twice the corpus rate, and still an outlier practice. Folded, the laws are GDPR (9 papers) and the ePrivacy Directive (4 papers, appearing under three different spellings including "European directives 2002/58/CE and 2009/136/CE"), then CCPA (3), plus one each of the UK Digital Economy Act, Brazil's LGPD, COPPA and the DSA. The papers that do it are the ones joining fingerprinting to consent: cookie respawning with fingerprinting {[fouad2022_cookie]}, and post-cookie tracking that bypasses a GDPR consent choice {[papadogiannakis2021_user]}. |
| |
| This is a gap, not a finding about the law. Fingerprinting has no consent API, so the compliance question — can a technique that cannot be refused ever rest on consent? — is squarely open, and became sharper in 2025 (see below). See [[Privacy:Consent]] and [[Practices:Legal enforcement]]. | This is a gap, not a finding about the law. Fingerprinting has no consent API, so the compliance question — can a technique that cannot be refused ever rest on consent? — is squarely open, and became sharper in 2025 (see below). See [[Privacy:Consent]] and [[Practices:Legal enforcement]]. |
| ==== Reproducing these figures ==== | ==== Reproducing these figures ==== |
| |
| The report script prints every number on this page with its denominator, the unmapped residue, and the full 83-paper list. The folding rules live in a separate module so they can be audited and reused. | The report script prints every number on this page with its denominator, the unmapped residue, and the full 83-paper list. The folding rules live in a separate module so they can be audited and reused. The block below is that module in full and verbatim — not a summary of it — so that running it reproduces the family table above exactly. The long alternations are the point: each family is a list of the literal phrasings the corpus actually uses, grown by hand as new ones appeared, and a shortened version of them silently reclassifies papers. |
| |
| <file javascript fp_fold.mjs> | <file javascript fp_fold.mjs> |
| // Folding rules for the word "fingerprint" in a free-text `phenomenon` field. | // Folding rules for the word "fingerprint" in `detection.phenomenon`. |
| // | // |
| // Three passes, because one regex cannot do it: | // Why this file exists: the corpus is seven broad security venues, so a |
| // 1. STRONG — ordered patterns naming the SUBJECT of the fingerprint | // substring search for "fingerprint" pulls at least seven unrelated literatures |
| // (a web API, a Tor circuit, a biometric sensor, a TLS stack). | // into one bucket. `detection.phenomenon` is free text and ~20% stable |
| // First match wins: the qualifier discriminates, not the head | // run-to-run (data/extract/README.md), so it can never be aggregated by exact |
| // noun -- "website fingerprinting" and "canvas fingerprinting" | // string — 280 papers produce 459 distinct strings. |
| // share the noun and share nothing else. | |
| // 2. GENERIC — strings naming only a PROPERTY ("fingerprint stability", | |
| // "fingerprint uniqueness") are unresolvable in isolation, so | |
| // they inherit the family of a strong tuple in the same paper. | |
| // 3. HAND — the residue, resolved by reading each evidence quote, with | |
| // the reason recorded. Anything still unresolved is PRINTED. | |
| // | // |
| // Excerpt; the full module and the per-page report are in the wiki repository. | // Three-pass design, because one regex cannot do it: |
| | // |
| | // Pass 1 — STRONG. Ordered patterns naming the *subject* of the |
| | // fingerprint: a web API, a Tor circuit, a biometric sensor, a TLS stack. |
| | // First match wins; the qualifier discriminates, not the head noun |
| | // ("website fingerprinting" and "canvas fingerprinting" share the noun). |
| | // |
| | // Pass 2 — GENERIC, resolved by paper context. A large minority of strings |
| | // name only a *property* of a fingerprint — "fingerprint stability", |
| | // "fingerprint uniqueness", "fingerprint comparison speed". Those are |
| | // unresolvable from the string alone: "fingerprint comparison speed" is a |
| | // PGP key fingerprint, "font fingerprint uniqueness" is a browser. Such a |
| | // tuple inherits the family of a STRONG tuple in the same paper, and if |
| | // the paper has none it stays `unmapped`. |
| | // |
| | // Pass 3 — HAND. The small residue left by passes 1 and 2, resolved by |
| | // reading each `evidence.quote` and the paper title, keyed on |
| | // (slug, phenomenon) with the reason recorded inline. See `HAND` below. |
| | // |
| | // Everything still unmapped after all three passes is PRINTED by the report, so |
| | // the part that could not be classified stays visible instead of vanishing. |
| |
| export const STRONG = [ | export const STRONG = [ |
| // Human biometrics first: "fingerprint sensor/template/image" is a finger. | // 1. Human biometrics. First, because "fingerprint sensor / template / |
| ['biometric', /\b(biometric|minutia|fingerprint (sensor|template|image|reader|spoofing))/i], | // image" is a finger, not a browser. |
| // Physical-object and hardware forensics. | [ |
| ['physical-forensic', /\b(prnu|paper speckle|clock[- ]skew|accelerometer|gyroscope|acoustic)/i], | 'biometric', |
| // Encrypted-traffic analysis: the OTHER fingerprinting literature. | /\b(biometric|minutia|finger position|fingerprint (sensor|template|image|sample|reader|recognition|acquisition|authentication|spoofing|brute-force|smoothness|and camera)|fake fingerprint|half-fingerprint|latent fingerprint|scrap fake|fingerprint-template|spi fingerprint|friction sound|fingerprint-pattern prediction|fingerprint-based authentication|poisoned-fingerprint|tee fingerprint|fingerprint key security|fingerprint extraction|fingerprint image recovery|fingerprint deactivation|mishandled fingerprint updates|fingerprint api misuse)/i, |
| ['traffic-analysis', /\b(website|web ?page|traffic|packet|hidden.service|\btor\b|open-world)/i], | ], |
| // Remote host and network-stack identification. | |
| ['network-stack', /\b(tls|ja3|\bos fingerprint|middlebox|router|web-?server|protocol fingerprint)/i], | // 2. Physical-object and hardware forensics: identifying an object or its |
| // LLM / model identification. New in 2025; before browser-device so that | // manufacturing noise. Includes phone sensors and clock skew, which are |
| // "LLM version fingerprinting" is not swallowed by a generic pattern. | // hardware channels even when reached from JavaScript. |
| ['llm-model', /\b(llm (version )?fingerprint|large language model|known-llm)/i], | [ |
| // Browser fingerprinting: named web APIs or an explicit browser qualifier. | 'physical-forensic', |
| ['browser-device', /\b(canvas|webgl|audiocontext|font|screen|navigator|browser|fingerprinting script|fingerprinter|extension)/i], | /\b(prnu|paper speckle|speckle|crumpling|water soaking|printing or scribbling|3d printer|ecu |can bus|clock-skew|clock skew|clock-based|cpu clock|transmitter|wi-?fi ftm|fpga|optical fingerprint|driving-route|driver fingerprint|magnetometer|gyroscope|accelerometer|motion-sensor|sensor calibration|sensor fingerprint|acoustic|speaker, microphone|environmental fingerprint|remote gpu|gpu fingerprint|decoder fingerprint|model-specific image|camera fingerprint|paper|flash fingerprint|usb timing fingerprint|write-induced fingerprint|physical-layer fingerprint|temperature-induced fingerprint|peripheral timestamp|fingerprint temperature robustness|fingerprint aging)/i, |
| | ], |
| | |
| | // 3. Media content identification (Shazam-style). |
| | [ |
| | 'media-content', |
| | /\b(music-based|video fingerprint|song|content fingerprint)/i, |
| | ], |
| | |
| | // 4. Encrypted-traffic analysis — the *other* fingerprinting literature: |
| | // inferring which page, site, or command a victim loaded. |
| | [ |
| | 'traffic-analysis', |
| | /\b(website|web site|web ?page|site-level fingerprintab|traffic|flow fingerprint|packet|netflow|sequence-number|ack fingerprint|connection-bucketing|keyword fingerprint|search-query|voice-command|streaming-command|alexa skill|command fingerprint|hidden.service|onion|\btor\b|relay fingerprint|openvpn|circumvention|cdnreaper|mobile-app fingerprinting over vpn|smart tv app|concurrent application|background activity|household fingerprintab|open-world|closed-world|defenseless|front-defended|domain-based|sensitive-site|phishing-site|google-resource|call-progress-tone|call-source|broadcast vulnerability|netflow-constrained|ip fingerprint|caching impact|encrypted mobile-app fingerprinting|ar\/vr standalone app fingerprinting|webxr app fingerprinting)/i, |
| | ], |
| | |
| | // 5. Off-web device and hardware identification: BLE/IoT devices, MAC |
| | // randomisation, hardware tokens. Genuinely fingerprinting, genuinely not |
| | // a browser. |
| | [ |
| | 'device-hardware', |
| | /\b(ble |bluetooth|iot|hardware fingerprint|device-signature|identical-model device|device tracking or fingerprinting|device and software fingerprint|mobile sensor|magnetic|wireless charging|dhcp|manufacturing batch|fingerprinting sdk|fingerprinting-signal exfiltration|permissionless android device fingerprinting|stable device fingerprinting)/i, |
| | ], |
| | |
| | // 6. Remote host and network-stack identification: TLS, OS, server, |
| | // middlebox, censorship equipment. Adjacent to browser fingerprinting — |
| | // a TLS fingerprint does identify a browser build — but the measurement |
| | // target is a host, not a visitor. |
| | [ |
| | 'network-stack', |
| | /\b(tls|ja3|schannel|bsafe|rsa|rsalib|asn1|protocol fingerprint|middlebox|router|web-?server|libc|\bos fingerprint|operating-system fingerprint|remote os|http-response|tcp\/tls|tcp stack|malicious-server|server implementation|layered-server|multi-layer|ca side-channel|hidden-service server|dns software|filtering-tool|rp software|relying part|deep packet inspection|dpi behavioral fingerprint|dpi deployment fingerprint|dpi fingerprint|censorship injection fingerprint|honeypot fingerprint|tsc server-fingerprint|operator fingerprint|device and vendor fingerprint)/i, |
| | ], |
| | |
| | // 7. Malware/analysis-environment evasion: fingerprinting the sandbox. |
| | ['evasion-environment', /\b(sandbox|virtual machine|\bvm\b|analysis environment)/i], |
| | |
| | // 7b. LLM / model identification. New in 2025: identifying which model |
| | // serves an endpoint. Its own family because it is a distinct literature |
| | // that did not exist when this fold was written. |
| | ['llm-model', /\b(llm (version )?fingerprint|large language model|known-llm|left-out llm|fingerprinting query efficiency)/i], |
| | |
| | // 8. Browser / device fingerprinting on the web platform: the subject of |
| | // privacy:fingerprinting. Named web APIs, or an explicit browser |
| | // qualifier, or the fingerprinting *script* as the detection target. |
| | [ |
| | 'browser-device', |
| | /\b(canvas|webgl|audiocontext|web audio|audio api|font|screen|resolution|navigator|user-?agent|battery api|webrtc|css fingerprint|storage fingerprint|storage-side-effect|postmessage|global-variable|browser|fingerprintable api|fingerprintable? ?apis|api fingerprinting|api use by fingerprinter|javascript api|fingerprint-related api|fingerprinting api|fingerprinting script|fingerprinter|fingerprinting domains|entropy-based fingerprinting|fingerprinting detector|fingerprinting code reuse|fingerprinting obfuscation|fingerprinting-based cloaking|fingerprinting information sharing|collaborative fingerprinting|fingerprinting-generated cookies|tracking fingerprinting|commercial web fingerprinting|web fingerprint|fingerprinting-feature dependency|fingerprinting-enhanced cohort|cohort unicity|cloakx|bloat|extension|adblock|cross-browser|user-action-only|user perceptions of fingerprinting|fingerprinting intention|fingerprint trackability|filter-list fingerprinting|ad-blocker configuration fingerprinting|wallet fingerprinting|fingerprinting in local frames|fingerprinting-based ad tracking|fingerprinting-based http tracking|fingerprinting under privacy regulations|awareness of digital fingerprinting|acceptance of fingerprinting|concerns about fingerprinting|fingerprint attribute evasion|spatial fingerprint inconsistenc|temporal fingerprint inconsistenc|cloaking fingerprinting)/i, |
| | ], |
| ]; | ]; |
| |
| | // Property-only strings: a family cannot be read off them. Resolved by paper |
| | // context in pass 2. |
| export const GENERIC = | export const GENERIC = |
| /^(?=.*fingerprint)(?!.*(?:website|canvas|browser)).*\b(stability|uniqueness|longevity|evolution|resistance|comparison)\b/i; | /^(?=.*fingerprint)(?!.*(?:website|canvas|browser|biometric)).*\b(stability|stable|uniqueness|unique|longevity|lifetime|persistence|survival|churn|evolution|change|over time|aging|robustness|fragility|discrimination|specificity|similarity|comparison|approximate|matching|collation|distribution|diversity|instability|degradation|reliability|errors|resistance|redundancy|correlation|attribute inference|randomi[sz]|defen[cs]e|blocked|harvest|cloak|cross-session|platform-specific|configuration-sensitive|cross-vendor|value fingerprinting|additive|identical|longitudinal|adversarial|harvest|sharing|leakage|churn)\b/i; |
| |
| export function classifyPaper(phenomena, slug = '') { | // Pass 3 — hand verification. Each entry was resolved by reading its |
| const first = phenomena.map((s) => ({ phenomenon: s, family: strongFamilyOf(s) })); | // `evidence.quote` and the paper title, and is keyed on (slug, phenomenon) |
| // Majority strong family in this paper wins the generics; ties break by the | // with the reason. 14 entries were added on 2026-08-05 against the 4,322-paper |
| | // corpus; 5 more on 2026-08-12 when the corpus grew to 5,859, for 19 in total. |
| | // Anything still unresolved stays unmapped and is printed by the report. This |
| | // table is the only place a human judgement overrides the rules, and it is |
| | // deliberately small and enumerated. |
| | export const HAND = new Map( |
| | [ |
| | // → browser fingerprinting |
| | ['a-privacy-analysis-of-cross-device-tracking|device fingerprint uniqueness', ['browser-device', 'web+mobile browser fingerprints, entropy over browser attributes']], |
| | ['beyond-the-front-page-measuring-third-party-dynamics-in-the-field|device fingerprinting', ['browser-device', 'detected by searching for the Fingerprint2 JS library']], |
| | ['tales-of-favicons-and-caches-persistent-tracking-in-modern-browsers|fingerprint entropy', ['browser-device', 'entropy of immutable browser attributes, 16-24 bits']], |
| | ['your-drm-can-watch-you-too-exploring-the-privacy-implications-of-browsers-mis-im|Android Client ID fingerprint uniqueness', ['browser-device', 'browser DRM (Widevine) Client ID as a browser-reachable identifier']], |
| | ['your-drm-can-watch-you-too-exploring-the-privacy-implications-of-browsers-mis-im|Client ID fingerprint stability', ['browser-device', 'same identifier, longitudinal stability']], |
| | // → other families |
| | ['smudged-fingerprints-characterizing-and-improving-the-performance-of-web-applica|Real-world fingerprinting degradation', ['network-stack', 'identifies which web application software a remote host runs']], |
| | ['keeping-the-smart-home-private-with-smart-er-iot-traffic-shaping-sleeping-habits|Device fingerprinting', ['traffic-analysis', 'IoT devices identified from DNS queries and destination IPs']], |
| | ['voip-fraud-identifying-a-wolf-in-sheeps-clothing|Remote device fingerprinting', ['physical-forensic', 'clock skew estimated from SIP REGISTER timings']], |
| | ['flowprint-semi-supervised-mobile-app-fingerprinting-on-encrypted-network-traffic|longitudinal fingerprint robustness', ['traffic-analysis', 'mobile app identification from encrypted traffic']], |
| | ['flaw-label-exploiting-ipv6-flow-label|IPv6 flow-label device fingerprinting', ['network-stack', 'IPv6 stack implementation identified from flow-label behaviour']], |
| | ['ltrack-stealthy-tracking-of-mobile-phones-in-lte|phone fingerprinting', ['device-hardware', 'handset identified over the LTE radio link']], |
| | ['preventing-sim-box-fraud-using-device-model-fingerprinting|device-model fingerprint uniqueness', ['device-hardware', 'handset model identified from radio-layer configuration, no browser']], |
| | ['preventing-sim-box-fraud-using-device-model-fingerprinting|configuration-sensitive fingerprints', ['device-hardware', 'same paper, same radio-layer fingerprint']], |
| | ['evasion-attacks-and-defenses-on-smart-home-physical-event-verification|evasion-vulnerable physical fingerprints', ['physical-forensic', 'physical event signatures in a smart home']], |
| | // Added 2026-08-12 with the 2025–2026 corpus. Same rule as above: each was |
| | // resolved by reading the phenomenon against the paper title and quote. |
| | ['good-bot-bad-bot-characterizing-automated-browsing-activity|application fingerprinting', ['browser-device', 'identifies the browsing agent from its request behaviour — a browser-side fingerprint, not a server one']], |
| | ['device-fingerprinting-with-peripheral-timestamps|device fingerprinting', ['physical-forensic', 'clock-domain skew of USB/peripheral timestamps; hardware, reachable from JS but not a web API']], |
| | ['device-fingerprinting-with-peripheral-timestamps|user-device fingerprinting', ['physical-forensic', 'same paper, same hardware channel']], |
| | ['device-fingerprinting-with-peripheral-timestamps|fingerprint permanence', ['physical-forensic', 'same paper, longitudinal property of the same hardware channel']], |
| | ['mvpnalyzer-an-investigative-framework-for-auditing-the-security-privacy-of-mobile-vpns|tracking and fingerprinting', ['device-hardware', 'mobile VPN apps fingerprinting the handset; no browser involved']], |
| | ] |
| | ); |
| | |
| | export function strongFamilyOf(phenomenon) { |
| | const s = String(phenomenon).toLowerCase(); |
| | for (const [name, re] of STRONG) if (re.test(s)) return name; |
| | return null; |
| | } |
| | |
| | export function isGeneric(phenomenon) { |
| | return GENERIC.test(String(phenomenon)); |
| | } |
| | |
| | // Classify every fingerprint-mentioning tuple of one paper. Returns an array of |
| | // {phenomenon, family, resolvedBy} in tuple order. |
| | export function classifyPaper(fpPhenomena, slug = '') { |
| | const first = fpPhenomena.map((s) => ({ phenomenon: s, family: strongFamilyOf(s) })); |
| | // Majority strong family in this paper wins the generics; ties broken by the |
| // STRONG order above, which is the order of decreasing confidence. | // STRONG order above, which is the order of decreasing confidence. |
| const votes = new Map(); | const votes = new Map(); |
| for (const t of first) if (t.family) votes.set(t.family, (votes.get(t.family) ?? 0) + 1); | for (const t of first) if (t.family) votes.set(t.family, (votes.get(t.family) ?? 0) + 1); |
| const order = STRONG.map(([n]) => n); | const order = STRONG.map(([n]) => n); |
| const context = [...votes.entries()] | const context = |
| .sort((a, b) => b[1] - a[1] || order.indexOf(a[0]) - order.indexOf(b[0]))[0]?.[0] ?? null; | [...votes.entries()].sort((a, b) => b[1] - a[1] || order.indexOf(a[0]) - order.indexOf(b[0]))[0]?.[0] ?? null; |
| return first.map((t) => { | return first.map((t) => { |
| if (t.family) return { ...t, resolvedBy: 'string' }; | if (t.family) return { ...t, resolvedBy: 'string' }; |
| if (context) return { phenomenon: t.phenomenon, family: context, resolvedBy: 'paper-context' }; | if (context) return { phenomenon: t.phenomenon, family: context, resolvedBy: 'paper-context' }; |
| const hand = HAND.get(`${slug}|${t.phenomenon}`); | const hand = HAND.get(`${slug}|${t.phenomenon}`); |
| if (hand) return { phenomenon: t.phenomenon, family: hand[0], resolvedBy: 'hand' }; | if (hand) return { phenomenon: t.phenomenon, family: hand[0], resolvedBy: 'hand', reason: hand[1] }; |
| return { phenomenon: t.phenomenon, family: 'unmapped', resolvedBy: 'none' }; | return { phenomenon: t.phenomenon, family: 'unmapped', resolvedBy: 'none' }; |
| }); | }); |
| | } |
| | |
| | // Named-thing folding for fingerprinting tools and resources. Unlike |
| | // name_fold.mjs (which canonicalises case and punctuation only) this merges |
| | // synonyms and spellings. Ordered; first match wins. |
| | export const TOOL_FAMILIES = [ |
| | ['FingerprintJS', /fingerprint ?js|fingerprint ?2\b|fingerprintjs2|fp-?js|fpjs/i], |
| | ['FP-Inspector', /fp-?inspector/i], |
| | ['FPMON', /fp-?mon/i], |
| | ['FP-Scanner / FP-Collect', /fp-?scanner|fp-?collect/i], |
| | ['AmIUnique', /am ?i ?unique/i], |
| | ['Panopticlick / Cover Your Tracks', /panopticlick|cover ?your ?tracks/i], |
| | ['OpenWPM', /openwpm/i], |
| | ['Tracker Radar Collector', /tracker ?radar/i], |
| | ['Tor Browser', /tor browser/i], |
| | ['Brave', /^brave|brave browser|brave shields/i], |
| | ['Disconnect list', /disconnect/i], |
| | ['EasyList / EasyPrivacy', /easylist|easyprivacy/i], |
| | ['uBlock Origin', /ublock/i], |
| | ['Privacy Badger', /privacy ?badger/i], |
| | ['puppeteer-extra-plugin-stealth', /stealth/i], |
| | ]; |
| | |
| | export function toolFamilyOf(name) { |
| | const s = String(name); |
| | for (const [fam, re] of TOOL_FAMILIES) if (re.test(s)) return fam; |
| | return null; |
| } | } |
| </file> | </file> |
| |
| Real output of the classification pass: | The first section of that script's output, verbatim and unedited — the full run also prints the per-venue table, the crawl-configuration comparison and the 83-paper list: |
| |
| <code> | <code> |
| detection fired at all 5655 papers | detection fired at all 5655 papers |
| phenomenon names a fingerprint 280 papers | phenomenon names a fingerprint 280 papers |
| only the technique does (excluded) 103 papers | only the technique does (excluded) 103 papers |
| | |
| | ## What "fingerprinting" means in this corpus |
| |
| 459 distinct free-text strings across 280 papers. | 459 distinct free-text strings across 280 papers. |
| Shares exceed 100%: 18 papers (6.4%) fall in more than one family. | Shares exceed 100%: 18 papers (6.4%) fall in more than one family. |
| |
| Tuples: 544 total — 441 resolved by the string, 76 by paper context | Tuples: 544 total — 441 resolved by the string, 76 by paper context (property-only strings), 7 unresolved. |
| (property-only strings), 7 unresolved. | |
| 95 of 544 strings name only a property of a fingerprint, not its subject. | 95 of 544 strings name only a property of a fingerprint, not its subject. |
| |
| Unmapped residue (printed in full): 7 tuples, 6 papers | ## Unmapped residue (printed in full) |
| | |
| | 7 tuples, 6 papers |
| CCS/2011/bitshred-feature-hashing-malware-for-scalable-triage-and-semantic-analysis | CCS/2011/bitshred-feature-hashing-malware-for-scalable-triage-and-semantic-analysis |
| Fingerprint similarity approximation | Fingerprint similarity approximation |
| * **Field stability.** Enum fields (''platforms'', ''crawlConfig.*'', ''legal.law'') reproduce to within a few points on a repeat extraction and carry percentages here. ''detection.phenomenon'' does not, which is what the whole folding exercise is for — the family table is a set of rankings with an honest residue, not a measurement. | * **Field stability.** Enum fields (''platforms'', ''crawlConfig.*'', ''legal.law'') reproduce to within a few points on a repeat extraction and carry percentages here. ''detection.phenomenon'' does not, which is what the whole folding exercise is for — the family table is a set of rankings with an honest residue, not a measurement. |
| * **The 83 is a floor.** A paper that studies fingerprinting without the extractor recording a fingerprint-named phenomenon is missing from it. 103 further papers name a fingerprint only in the ''technique'' field and were deliberately excluded, since "we detected X by fingerprinting the TLS stack" is a paper about X. | * **The 83 is a floor.** A paper that studies fingerprinting without the extractor recording a fingerprint-named phenomenon is missing from it. 103 further papers name a fingerprint only in the ''technique'' field and were deliberately excluded, since "we detected X by fingerprinting the TLS stack" is a paper about X. |
| * **Quotes were spot-checked.** ''scripts/quote_check.mjs --detection fingerprint'' verifies the evidence quotes behind this page in bulk against ''paper.cols.txt''; the results, and the ones that had to be read by hand, are on [[provenance:privacy:fingerprinting]]. The dataset's own "0.9% of quotes could not be located" figure was measured on the earlier 4,322-paper run and has not been re-measured. | * **Quotes were spot-checked.** ''%%scripts/quote_check.mjs --detection fingerprint%%'' verifies the evidence quotes behind this page in bulk against ''paper.cols.txt''; the results, and the ones that had to be read by hand, are on [[provenance:privacy:fingerprinting]]. The dataset's own "0.9% of quotes could not be located" figure was measured on the earlier 4,322-paper run and has not been re-measured. |
| * **Every query behind this section, the report script and its unedited output** are on [[provenance:privacy:fingerprinting]]; corpus-level caveats are on [[literature:corpus]]. | * **Every query behind this section, the report script and its unedited output** are on [[provenance:privacy:fingerprinting]]; corpus-level caveats are on [[literature:corpus]]. |
| |
| |
| - **Uniformity and randomisation are measured differently.** Against a uniformity defence you measure //how many users share a bucket//; against farbling you measure //whether values are linkable across sessions//. A protocol written for one gives a meaningless answer against the other, and this is a common flaw in defence comparisons. | - **Uniformity and randomisation are measured differently.** Against a uniformity defence you measure //how many users share a bucket//; against farbling you measure //whether values are linkable across sessions//. A protocol written for one gives a meaningless answer against the other, and this is a common flaw in defence comparisons. |
| - **Your own crawler's browser is a defence configuration.** A 2026 Firefox with FPP on by default in Standard mode is not the browser that older papers measured with. State the browser, the version, and the fingerprinting-protection settings — the 19.6% of crawling papers in the corpus that state statefulness are ahead of the field, and fingerprinting-protection state is reported even less often than that. | - **Your own crawler's browser is a defence configuration.** A 2026 Firefox with FPP on by default in Standard mode is not the browser that older papers measured with. State the browser, the version, and the fingerprinting-protection settings — the 21.9% of crawling papers in the corpus that state statefulness are ahead of the field, and fingerprinting-protection state is reported even less often than that. |
| |
| ==== The 2025 policy reversal ==== | ==== The 2025 policy reversal ==== |
| On 18 December 2024 Google notified users of its advertising products that **from 16 February 2025 it would no longer prohibit them from employing fingerprinting techniques**. The UK Information Commissioner's Office responded the next day: //"We think this change is irresponsible"//, quoting Google's own 2019 position on fingerprinting back at it — //"We think this subverts user choice and is wrong."//((UK Information Commissioner's Office, [[https://ico.org.uk/about-the-ico/media-centre/news-and-blogs/2024/12/our-response-to-google-s-policy-change-on-fingerprinting/|"Our response to Google's policy change on fingerprinting"]], 19 December 2024. Verified against the ICO page directly on 2026-08-05.)) | On 18 December 2024 Google notified users of its advertising products that **from 16 February 2025 it would no longer prohibit them from employing fingerprinting techniques**. The UK Information Commissioner's Office responded the next day: //"We think this change is irresponsible"//, quoting Google's own 2019 position on fingerprinting back at it — //"We think this subverts user choice and is wrong."//((UK Information Commissioner's Office, [[https://ico.org.uk/about-the-ico/media-centre/news-and-blogs/2024/12/our-response-to-google-s-policy-change-on-fingerprinting/|"Our response to Google's policy change on fingerprinting"]], 19 December 2024. Verified against the ICO page directly on 2026-08-05.)) |
| |
| For a measurement researcher this is the most consequential change in the topic since GDPR. Prevalence figures from before February 2025 describe a web in which the largest ad platform contractually forbade the technique; anything you measure after it does not. | For a measurement researcher this is arguably the most consequential change in the topic since GDPR. Prevalence figures from before February 2025 describe a web in which the largest ad platform contractually forbade the technique //to its own advertising customers//; anything you measure after it does not. The policy never bound the whole web, which is why the pre-reversal figures on this page are not a baseline of "fingerprinting while prohibited" — they are a baseline of the web as it was. |
| |
| **The first post-reversal measurement in these seven venues has now landed.** Luo et al. {[luo2025_canvassing]} crawled the Tranco top 20K and a random tail sample **in May 2025**, three months after the change, and found canvas fingerprinting on **12.7% of 16,276 popular sites and 9.9% of 17,260 tail sites**. That is one technique on one crawl, and it is not a before/after comparison — nobody has run the same instrument on both sides of the date. But the page can no longer say the post-reversal web is unmeasured, and a pre/post study now has a published post-side baseline to work against. | **The first post-reversal measurement in these seven venues has now landed.** Luo et al. {[luo2025_canvassing]} crawled the Tranco top 20K and a random tail sample **in May 2025**, three months after the change, and found canvas fingerprinting on **12.7% of 16,276 popular sites and 9.9% of 17,260 tail sites**. That is one technique on one crawl, and it is not a before/after comparison — nobody has run the same instrument on both sides of the date. But the page can no longer say the post-reversal web is unmeasured, and a pre/post study now has a published post-side baseline to work against. |
| ==== Detecting fingerprinting in a crawl ==== | ==== Detecting fingerprinting in a crawl ==== |
| |
| * **[[https://github.com/openwpm/OpenWPM|OpenWPM]]** — the standard instrumented crawler; its JavaScript instrumentation records every access to a configured API surface, with call arguments and stack, which is the raw material every detector on this page consumes. 15 of the 83 papers use it. See [[Programming:Crawler:OpenWPM]]. | Pick by question, not by citation count. The table above ranks what the literature //used// over sixteen years; what follows is what each instrument is good for now. |
| | |
| | * **[[https://github.com/openwpm/OpenWPM|OpenWPM]]** — the most-cited instrumented crawler (15 of the 83 papers), and still the right default for **request- and cookie-level** work. Two caveats before you adopt it for fingerprinting specifically. It is **Firefox-only** and each release pins one unbranded Firefox build (v0.35.0, June 2026, ships Firefox 152), so its browser is neither a current Chrome nor whatever your reader runs — state the OpenWPM version //and// the Firefox version, because the pin is a default you can override. More important: ''js_instrument=True'' does not mean "instrument JavaScript", it means the fixed ''collection_fingerprinting'' list of 14 objects, whose contents have not changed since 2020 and which covers **neither ''WebGLRenderingContext'' nor ''document.fonts''**, and reads ''window.screen'' only for ''colorDepth'' and ''pixelDepth''. Three of the surfaces in this page's own table — WebGL, fonts, screen — leave no row by default. Write your own ''js_instrument_settings'' and say which APIs it covered. [[Programming:Crawler:OpenWPM]] has the version-to-Firefox map and the rest of the defaults. |
| | * **[[https://github.com/wspr-ncsu/visiblev8|VisibleV8]]** — a patched V8 that logs API accesses **from inside the JavaScript engine** — //"a custom variant of the V8 JavaScript engine that logs all JavaScript API calls and their arguments to a trace log"//, shipped as a patchset over Chromium((''README.md'' of [[https://github.com/wspr-ncsu/visiblev8|wspr-ncsu/visiblev8]], read 2026-09-03. Repository active (last push 2026-07-15); release tags name the Chromium version they patch, most recently the 138.x series.)) — so there is no in-page instrumentation for a script to detect or for a bundler to miss. It is the newest of the three lineages here and the only one still tracking Chrome releases (tags follow Chrome 138 as of 2026-07). It is invisible in the tool table above because the fold dropped it, yet **5 of the 83 papers use it** — more than FP-Inspector or AmIUnique — from extension fingerprinting in 2021, through the automatic discovery of emerging techniques {[su2023_automatic]}, to a 2026 NDSS mobile-tracking study. If your question is //which APIs did this script actually touch//, this is the current answer, and [[Programming:Crawler:PanoptiChrome]] builds taint tracking on top of it. |
| * **[[https://github.com/uiowa-irl/FP-Inspector|FP-Inspector]]** {[iqbal2021_fingerprinting]} — the most-used purpose-built classifier in the corpus (4 papers). Treat it as a **research artifact frozen at its 2021 paper**, not a maintained tool: useful for its classifier, feature set and labelled script list; expect to port it. | * **[[https://github.com/uiowa-irl/FP-Inspector|FP-Inspector]]** {[iqbal2021_fingerprinting]} — the most-used purpose-built classifier in the corpus (4 papers). Treat it as a **research artifact frozen at its 2021 paper**, not a maintained tool: useful for its classifier, feature set and labelled script list; expect to port it. |
| * **[[https://github.com/duckduckgo/tracker-radar-collector|DuckDuckGo Tracker Radar Collector]]** — a lighter Puppeteer-based collector with an API-access collector built in; 6 papers. See [[Programming:Crawler:Tracker radar collector]]. | * **[[https://github.com/duckduckgo/tracker-radar-collector|DuckDuckGo Tracker Radar Collector]]** — a lighter Puppeteer-based collector with an API-access collector built in; 6 papers, and the instrument behind the one post-reversal measurement this page cites {[luo2025_canvassing]}. Chromium, so it is the natural pair to OpenWPM's Firefox. See [[Programming:Crawler:Tracker radar collector]]. |
| * **Filter lists** — EasyPrivacy and Disconnect are what most papers actually use for ground truth. Read the caveat above before you do the same, and see [[Privacy:Requests]] for how to apply them in post-processing rather than during the crawl. | * **Filter lists** — EasyPrivacy and Disconnect are what most papers actually use for ground truth. Read the caveat above before you do the same, and see [[Privacy:Requests]] for how to apply them in post-processing rather than during the crawl. |
| |
| * **[[https://fpmon.github.io/fingerprinting-monitor/|FPMON]]** — a browser extension that reports, in real time, which fingerprinting-relevant APIs the current page touched. Handy for a spot check on a site your pipeline flagged. | * **[[https://fpmon.github.io/fingerprinting-monitor/|FPMON]]** — a browser extension that reports, in real time, which fingerprinting-relevant APIs the current page touched. Handy for a spot check on a site your pipeline flagged. |
| * **[[https://github.com/fingerprintjs/fingerprintjs|FingerprintJS]]** — the open-source library, used as a positive control by 14 of the 83 papers. Licence history matters if you vendor it: MIT, then Business Source License 1.1 for the 4.x series, back to MIT from 5.0.0 (current npm release 5.2.0, MIT, checked 2026-08-05). The hosted **Fingerprint Pro** product is separate and proprietary. | * **[[https://github.com/fingerprintjs/fingerprintjs|FingerprintJS]]** — the open-source library, used as a positive control by 14 of the 83 papers. Licence history matters if you vendor it: MIT, then Business Source License 1.1 for the 4.x series, back to MIT from 5.0.0 (current npm release 5.2.0, MIT, checked 2026-08-05). The hosted **Fingerprint Pro** product is separate and proprietary. |
| | |
| | ==== Datasets you can start from ==== |
| | |
| | 36 of the 83 papers (43.4%) reanalyse an existing dataset rather than crawling. These are the ones worth knowing about before you build a crawl: |
| | |
| | * **[[https://github.com/duckduckgo/tracker-radar|DuckDuckGo Tracker Radar]]** — the //dataset//, as distinct from the Collector above. One JSON file per third-party domain, carrying a ''fingerprinting'' likelihood score, the ''prevalence'' of the domain across crawled sites, and — per resource — an ''apis'' list of //"browser APIs accessed by this resource which are commonly used in fingerprinting"//. That last field is the useful one: it is a public, per-resource record of which fingerprinting surfaces a given script touched, which is exactly the ground truth most papers hand-build. CC BY-NC-SA 4.0, so check the licence against your use.((Field definitions from ''docs/DATA_MODEL.md'', licence from ''README.md'', both in [[https://github.com/duckduckgo/tracker-radar|duckduckgo/tracker-radar]], read 2026-09-03. Sampled values of ''fingerprinting'' on 2026-09-03: doubleclick.net 3, cloudflare.com 2, facebook.net 2, criteo.com 1.)) |
| | * **Disconnect's fingerprinting categories** — ''FingerprintingInvasive'' (281 domains) and ''FingerprintingGeneral'' (96), in the same file Firefox ships. A domain-level label, not a script-level one, and an editorial judgement rather than a measurement — but it is the label 13 of these papers are implicitly using. |
| | * **FP-Inspector's labelled script list** {[iqbal2021_fingerprinting]} — the closest thing the field has to a published fingerprinting-script ground truth, frozen at 2021. Useful as a //seed// and as a comparison point; not usable as a current label set, because the scripts have moved. |
| | * **The papers' own artifacts.** 92.8% of the 83 released an artifact link — the highest-value fact on this page. Before you build a crawl, check whether the study you are extending published its script list, its API traces, or its classifier. |
| | |
| | <WRAP tip> |
| | None of these is a benchmark. There is no fixed site sample with hand-labelled fingerprinting ground truth that papers compete on, the way ad-blocking research has filter lists — which is why the prevalence figures above are incomparable, and why this is still an open problem rather than a solved one. |
| | </WRAP> |
| |
| ==== A crawler self-check you should run ==== | ==== A crawler self-check you should run ==== |
| - Headless-specific values: empty ''navigator.plugins'', missing ''window.chrome'', ''HeadlessChrome'' in the UA string, a Google/SwiftShader WebGL vendor string instead of the host GPU's. | - Headless-specific values: empty ''navigator.plugins'', missing ''window.chrome'', ''HeadlessChrome'' in the UA string, a Google/SwiftShader WebGL vendor string instead of the host GPU's. |
| - Font set and canvas hash from //inside// the container, which is usually a Docker image with a minimal font list and software rendering — a highly distinctive combination. | - Font set and canvas hash from //inside// the container, which is usually a Docker image with a minimal font list and software rendering — a highly distinctive combination. |
| - Whether the fingerprinting scripts you detected are the same set a headful browser on the same page loads. FP-Fed {[annamalai2024_fpfed]} measures precisely this gap. | - Whether the fingerprinting scripts you detected are the same set a **real user session** on the same page loads. Both measurements of this gap — FP-Fed's top-300 manual crawl {[annamalai2024_fpfed]} and Annamalai et al.'s 471-site comparison {[annamalai2025_beyond]} — vary interaction, login and consent together, not headless against headful, so they bound the gap without attributing it. |
| |
| ''puppeteer-extra-plugin-stealth'' patches many of the obvious tells and appears in two corpus papers. Do not treat it as a solution: CreepJS and FP-Scanner-style consistency checks defeat it, and a partially-patched browser occupies an anonymity set of one. If detectability matters to your result, **measure it and report it** rather than assuming it away. | ''puppeteer-extra-plugin-stealth'' patches many of the obvious tells and appears in two corpus papers. Do not treat it as a solution: CreepJS and FP-Scanner-style consistency checks defeat it, and a partially-patched browser occupies an anonymity set of one. If detectability matters to your result, **measure it and report it** rather than assuming it away. |
| <WRAP todo> | <WRAP todo> |
| * No **pre/post comparison** across Google's 16 February 2025 policy change. Luo et al. {[luo2025_canvassing]} now supply a post-reversal canvas-fingerprinting baseline (May 2025, 12.7% of the top 20K), so what is missing is the same instrument run on both sides of the date rather than any measurement at all. The pre-side baseline data (FP-Radar, FP-Inspector) is public. | * No **pre/post comparison** across Google's 16 February 2025 policy change. Luo et al. {[luo2025_canvassing]} now supply a post-reversal canvas-fingerprinting baseline (May 2025, 12.7% of the top 20K), so what is missing is the same instrument run on both sides of the date rather than any measurement at all. The pre-side baseline data (FP-Radar, FP-Inspector) is public. |
| * **Partly answered since this page was written.** Annamalai et al. {[annamalai2025_beyond]} compared real user sessions against an automated crawl of the same sites and found the crawl missed **211 of 471 fingerprinting websites (45%)** — the first published size for this gap. What is still open is the narrower question: how much of that 45% is //headless versus headful// as opposed to interaction depth, authentication and consent, which the paper attributes it to. | * **Partly answered since this page was written.** Annamalai et al. {[annamalai2025_beyond]} compared real user sessions against an automated crawl of the same sites and found the crawl missed **211 of 471 fingerprinting websites (45%)** — the first size for this gap //at scale//, after FP-Fed's top-300 pilot {[annamalai2024_fpfed]} put it at 3×. What is still open is the narrower question: how much of that 45% is //headless versus headful// as opposed to interaction depth, authentication and consent, which the paper attributes it to. Neither study varies one factor at a time, so nobody has isolated the cost of headlessness alone. |
| * Prevalence figures are incomparable across papers because unit, rank cut and definition all vary. A shared benchmark — a fixed site sample with hand-labelled ground truth — does not exist for fingerprinting the way EasyList serves ad-blocking research. | * Prevalence figures are incomparable across papers because unit, rank cut and definition all vary. A shared benchmark — a fixed site sample with hand-labelled ground truth — does not exist for fingerprinting the way EasyList serves ad-blocking research. |
| * Consent and fingerprinting: only 10 of 83 papers touch a law, and none in the corpus tests whether a CMP's consent signal changes fingerprinting behaviour on the same site. Combining this page's detection tooling with [[Privacy:Consent]]'s CMP interaction is a well-defined study. | * Consent and fingerprinting: only 10 of 83 papers touch a law. The obvious experiment has **already been run** — Papadogiannakis et al. {[papadogiannakis2021_user]} crawled each CMP-bearing site three times, once per consent action, and of the **27,180 sites they reached successfully under all three**, 279 fingerprinted with no action taken, 285 after //Reject All// and 330 after //Accept All//, with 247 fingerprinting under all three conditions. Their conclusion is that //"the action of the user has no significant impact on the websites' fingerprinting operations"//. What is open is the **post-2025 repeat** of that design, and whether any signal a user can send — a CMP rejection, Global Privacy Control, an ePrivacy-style refusal — is honoured by fingerprinting scripts specifically. See [[Privacy:Consent]] for the CMP interaction half. |
| * Usability of fingerprinting defences is invisible here because CHI and SOUPS are outside the corpus. Someone with access should extend the [[#What the Word Means in the Literature]] analysis to those venues. | * Usability of fingerprinting defences is **thin** here rather than absent: the 83 include a PETS 2026 study of public awareness and perception of fingerprinting and Berke et al.'s demographics work {[berke2025_demographics]}, but the venues where this subject mostly publishes — CHI and SOUPS — are outside the corpus. Someone with access should extend the [[#What the Word Means in the Literature]] analysis to those venues before concluding anything about how much of it exists. |
| </WRAP> | </WRAP> |
| |
| ===== Related Pages ===== | ===== Related Pages ===== |
| |
| * [[Privacy:Cookies]] — the stateful counterpart; fingerprinting and cookies are used together, and respawning links them directly {[fouad2022my]}. | * [[Privacy:Cookies]] — the stateful counterpart; fingerprinting and cookies are used together, and respawning links them directly {[fouad2022_cookie]}. |
| * [[Privacy:JavaScript]] — classifying the scripts that 39.8% of these papers are actually detecting. | * [[Privacy:JavaScript]] — classifying the scripts that 39.8% of these papers are actually detecting. |
| * [[Privacy:Requests]] — the filter lists that most of this literature uses as ground truth, and why that is a compromise. | * [[Privacy:Requests]] — the filter lists that most of this literature uses as ground truth, and why that is a compromise. |