Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

133 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Exposed: Shedding Blacklight on Online Privacy

Who is the most surveilled online? We join one month of passively observed browsing by 1,134 US adults — 6.2 million visits to 64,074 domains — to domain-level privacy audits from Blacklight, and ask who meets the most tracking.

Two accounts compete. One says risk follows vulnerability: the least digitally literate should be the most exposed. The other says risk follows opportunity: exposure should track how much time someone spends online and little else. Neither survives intact. Tracking is close to universal, so there is little room for a vulnerability gap on whether you are tracked; gaps by gender and education close once browsing volume is accounted for, as the opportunity account predicts. But the age gap does not close. Users 65 and older meet 74–87% more trackers per visit than users under 25 — a difference in where people browse, not only how much.

What we find

  • Tracking is near-universal and fast. Over 99% of users encounter ad trackers and third-party cookies; half of them within twelve hours. Session recording, keylogging and canvas fingerprinting reach 42–52% of users within two days.
  • Concentration. One organization — Google, for nine users in ten — observes a median 54% of a person's browsing.
  • The age gap is about site choice. Unadjusted, panelists 65+ meet 1.90× the ad-tracker exposure of under-25s; adjusted for gender, race and education the gap is 74–87%. It survives controlling for device, and decomposes to 85% within content categories — older panelists visit more heavily tracked sites inside the same categories, not different categories.
  • Every estimate is a lower bound. Visits to domains Blacklight could not scan are counted as tracker-free. A re-audit of a random sample of those domains finds more tracking on them, not less.
  • Blockers help, unevenly. EasyList/EasyPrivacy/Disconnect would remove 77% of ad-tracker and 84% of third-party-cookie exposure and narrow the age gap to 1.26×, but 93% of canvas fingerprinting survives — which is what fingerprinting scripts are built to do.

Research design

The panel. YouGov fielded a browsing panel metered by RealityMine in June 2022, matched to US population margins. We use the 1,134 panelists with usable browsing and profile data: 6.2M visits, 64,074 unique domains.

The audit. Blacklight visits a domain and reports seven techniques: ad trackers (outgoing requests matched to DuckDuckGo's "Ad Motivated Tracking" list), third-party cookies (Set-Cookie headers on third-party requests), session recording, keylogging, canvas fingerprinting, Facebook Pixel and Google Analytics. Three of these — session recording, keylogging and canvas fingerprinting — are the most invasive, and the ones that operate outside the reach of the hygiene measures users are ordinarily told to adopt.

Each scan also names the third-party domains responsible for each behavior. That is what makes the blocking analysis arithmetic rather than simulation, and what lets us link third parties to parent organizations through DuckDuckGo's Tracker Radar to ask how much of one person's browsing a single organization can see.

The join. Exposure is measured per person two ways: cumulative (total tracker-encounters over the month) and rate (per visit). A person's exposure is the visit-weighted sum of the tracking on the domains they actually visited, so it reflects browsing composition rather than a domain-level average.

What could go wrong, and what we did about it. Browsing was observed in June 2022 but Blacklight scanned in ~January 2025, and scans completed for ~53% of unique domains (~76% of visits). Rather than assume either problem away, we measured both against independent instruments — HTTP Archive's monthly crawls and Wayback Machine snapshots — and re-audited a coded random sample of the unscanned domains. Both point the same direction: the published numbers understate exposure. Details in Validity below.

What this is not. These are associations in an observational panel, not causal effects of age. Blacklight measures a domain at one point in time, not what any individual's browser actually loaded. Assumptions about missing data are enumerated, with their direction, in scripts/missing_data.md.


Reproducing

Everything is Python. Numbers, tables and figures in the manuscript are produced by the pipeline, not maintained by hand.

make setup                # create bl_venv from requirements.txt
make regressions          # Tables 5-6, coefficient plots, age-spline check
make blocking && make residual   # residual exposure under blocklists
make paper                # compile ms/blacklight.pdf (54 pages)
make help                 # every target

Targets

Target What it builds
regressions Tables 5–6, both coefficient plots, the age-gradient check
blocking Attribute behaviors to third parties, apply blocklists, recompute exposure
residual Sensitive categories, device, population projection, security link
implications Demographic robustness to coverage and timing threats
httparchive HTTP Archive comparison (prints a BigQuery cost estimate; runs no billed query)
wayback June-2022 Wayback snapshots and static parses
selection-audit Scan-failure parse, audit sample, re-probe, code validation
tables-ms / paper Wrap pipeline fragments into the manuscript floats; compile

What needs data you have to fetch

Most of the pipeline runs from committed data. Three things do not:

  • data/yg/realityMine_web_*.csv — the raw visit files. The desktop file (287 MB) is public on Dataverse; scripts/09_build_visit_panel.py prints the download command if it is missing. The combined realityMine_web file is restricted, so 02_combine_yg_blacklight.ipynb cannot be re-run here; the derived person-level file it produced is committed, and every downstream script reads that.
  • HTTP Archive — billed BigQuery. make httparchive builds everything else and prints the cost estimate rather than running the query.
  • 04_cum_exposure_by_hour.ipynb — needs visit timestamps, which only 29.5% of visits carry. Its outputs are committed and reconcile with the published figure; it is not re-run.

Layout

data/           panel, Blacklight scans, WhoTracksMe, blocklists, CPS margins
scripts/        numbered pipeline; subdirectories are self-contained modules
  blocking/     residual exposure under EasyList/EasyPrivacy/Disconnect
  httparchive/  HTTP Archive validity strand
  wayback/      Wayback Machine validity strand
  implications/ robustness of the demographic results to coverage and timing
  selection_audit/ what the unscanned domains actually are
  exploratory/  superseded scripts, kept for provenance
tables/         .tex fragments; tab2_formatted..tab6_formatted are the ms floats
figures/        .pdf and .png
ms/             manuscript source

Every script carries a header naming its inputs, its outputs, and which manuscript table or figure it produces. Several gate on reproducing a published number before writing anything — for example, the residual-exposure module rebuilds the person-level exposure file from raw visits and refuses to continue unless it matches the committed file exactly.


Validity

Two features of the design deserve scrutiny: the ~2.5-year gap between browsing and scanning, and the ~53% domain scan rate. Full strand map in scripts/validity_strands.md.

A. Timing. On matched panel domains measured by the same instrument at both dates, visit-weighted ad-tracker prevalence moved 98.1% → 95.2% between June 2022 and June 2025; "any known tracker" barely moved (99.9% → 98.1%). Recomputing user-level exposure under June-2022 vs Jan-2025 measurements shifts means modestly (ad trackers −6.3%, Google Analytics −4.3%) while the cross-user ordering the demographic analyses depend on is strongly preserved (r = 0.75–0.91). If anything, 2025-era scans understate June-2022 exposure.

B. Coverage. The construction already counts unscanned visits as zero tracking, so published rates are lower bounds by design. Replacing that assumption with measurement — June-2022 HTTP Archive request maps cover 62.7% of the missing visit mass, Wayback another 3.2%, calibrated to Blacklight's scale on jointly measured domains — narrows the ad-tracker interval from [4.98, 11.69] to [6.17, 8.41] per visit, against 4.98 published. Third-party cookies: 6.12 published, [7.02, 10.72] measured. Accounting for unscanned domains raises exposure.

C. Instruments agree where they measure the same thing. HTTP Archive and Blacklight (both ~Jan 2025) agree on ad-tracker presence for 86% of shared domains; Wayback static parses recover 92% of ad-tracker presence, weaker for JS-injected measures (Facebook 47%). Construct differences — header-set vs JS-set cookies, GA presence vs GA remarketing — are labeled in every table.

D. What the unscanned half actually is. Scan failures reflect unscannability, not dead sites: at least 66% of unscanned visit mass was on domains demonstrably alive in mid-2022. A seeded random sample of 200 unscanned domains, coded against a written rubric, is mostly ordinary user-facing content (62% of visit mass, CI [51, 70]) plus tracking and CDN infrastructure (28%); dead-with-no-trace domains are 7%. Re-scanning succeeded for 66% of the sample, and on those domains tracking measured directly is heavier than in the originally scanned population (8.8 ad trackers per visit-weighted domain, CI [5.0, 13.3], vs 6.5) — the same direction as the coverage bounds in strand B.

Residual exposure under best-available defenses

A separate question from the validity strands: those bound what the paper measures, this asks what a defense would have removed. Because Blacklight names the third parties responsible for each behavior, applying EasyList, EasyPrivacy and Disconnect to those domains and recomputing every measure is arithmetic rather than simulation. Map in scripts/residual_exposure.md; pipeline in scripts/blocking/README.md.

Blocking removes most ad-tracker (77%) and third-party-cookie (84%) exposure and narrows the unadjusted 65+ gap from 1.90× to 1.26× on ad trackers. A placebo of random blocklists removing the same amount shows that narrowing is not merely arithmetic (p = .05, p < .001). It barely touches canvas fingerprinting — 93% survives and the age coefficient does not move — which is the most robust result here. The apparent widening for session recording does not survive its own placebo (p = .31) and is not reported as evidence of regressive protection. Projected onto CPS 2022 margins, 216M US adults [210, 222] met a keylogging script in the month and 191M [184, 198] would still have behind a blocker.

Data

🔗 Adjacent Repositories

  • themains/reg_breach — Have I Been Pwned? Yes. Evidence from HIBP and Emails From Voter Registration Files.
  • themains/pwned_pols — A third of the politicians have had their data breached at least once. More alarmingly, over one in five have had their sensitive data, such as bank account numbers, biometric data, browsing history, chat logs, credit card CVV, etc., breached.
  • themains/pwned — How Often Are Americans' Accounts Breached?
  • themains/private_gov — How common are third-party cookies, trackers, key loggers, etc. on government websites?
  • themains/know-your-ip — Know Your IP: Get location, blacklist status, shodan and censys results, and more.

About

Privacy Online and Digital Divide on Online Privacy

Topics

Resources

Stars

4 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages