ideas.
October 16, 2026 3 min read browser-extensionconsumerprivacy

Check whether the cookie banner told the truth

A browser extension that records what a site actually stores and sends after you click Reject, then shows you the gap.

The idea

An extension that sits behind the consent dialog and keeps score. It loads a page twice — once rejecting everything, once accepting — and records every cookie written, every localStorage and IndexedDB key created, and every outbound request to a known tracking endpoint. Then it diffs the reject run against the site's own declared purposes and shows you the things that fired anyway. The output is a plain list: "you rejected advertising, and these eleven requests went to ad domains regardless."

Why build this

Most people have no way to tell whether a consent banner does anything. The regulators do check, but slowly and in samples; a single person who wants to know about one site has nothing. Builders have the same problem in reverse — you ship a consent management platform, configure it once, and never verify that your own tag manager honours it after the next marketing hire adds a pixel.

The reason this is newly tractable is that consent state is machine-readable now. Sites running IAB TCF expose __tcfapi, so the extension can read the exact purpose and vendor flags the page thinks it has, rather than guessing from a button label. Pair that with request classification from a public tracker list and the comparison is mechanical instead of judgemental.

Stack sketch

  • Extension scaffolding with WXT, Manifest V3, Chrome and Firefox from one codebase.
  • Non-blocking chrome.webRequest listeners for the request log; chrome.cookies for cookie writes; a content script that wraps localStorage, document.cookie, and indexedDB.open to catch client-side storage.
  • Consent state read from __tcfapi('getTCData') where present, plus Google's Additional Consent string, plus heuristics for the handful of large non-TCF banners.
  • Request classification against DuckDuckGo Tracker Radar for entity ownership and EasyPrivacy for endpoint matching, both shipped as a bundled snapshot and refreshed on a schedule.
  • Runs stored locally in IndexedDB via Dexie; a report exports as JSON and as a readable HTML file with timestamps and request headers intact.
  • No backend in v1. Nothing leaves the browser unless the user exports a file.

Scope for v1

  • One button: audit this page. It opens a clean profile-isolated run, rejects everything, waits for network idle, records, then repeats accepting everything.
  • The diff view: storage written under reject, tracker requests under reject, and purposes claimed versus purposes observed.
  • Export one run as JSON and HTML.
  • Deliberately out: scheduled monitoring, multi-page crawls, any cloud account, any legal verdict. The report says what happened, never that a site is unlawful.

Where it could go

The obvious extension is turning a one-off check into a watch. Run the same audit headlessly in Playwright against a list of URLs on a cron, store the runs, and alert when a site that was clean starts leaking — that is a self-hostable service a privacy team or a journalist would actually keep running, and it reuses the classification code unchanged.

The second path is selling it inward. The people most willing to pay for this are the ones who deployed the banner: agencies and in-house teams who need evidence their consent setup works before an audit does. That version wants a CI mode, a JUnit-style report so a failing audit breaks a deploy, and per-tag attribution — which script element caused the request — which the debugger protocol can give you via initiator stacks.

Watch out for

The honest failure mode is false positives: a request to a domain on a tracker list is not automatically a consent violation, because legitimate interest, contract necessity, and first-party analytics are all defensible. Word every finding as an observation with the raw evidence attached, and resist the urge to put a compliance score on it.