A locally-run, three-phase system for tracking and executing data broker opt-out requests. No paid removal service, no data leaves this machine except to the brokers themselves.
Data brokers make collecting and selling your information frictionless, and make removing it deliberately hostile: CAPTCHAs, phone verification codes, driver’s license uploads, one-opt-out-per-email limits, and confirmation links buried in email. This workflow doesn’t bypass any of that — it just removes the tedium of looking up 19+ hidden opt-out URLs and babysitting an inbox for confirmation links.
master-registry.md)master-registry.md is the single source of truth. Each row is one broker: name, category, direct opt-out URL, status (🟥 Pending / 🟩 Completed), and the removal method (phone call, email confirmation, form + captcha, etc. — set expectations before you start).
Both scripts below parse this file directly (via scripts/registry.py),
so adding a new broker is just adding a table row — no code changes.
Source list for new entries: Big-Ass-Data-Broker-Opt-Out-List.
scripts/broker_launcher.py)Opens every Pending broker’s opt-out page in real browser tabs, 3 at a
time, pausing between batches so you can actually fill out each form:
python3 ~/Projects/cyber-kb/scripts/broker_launcher.py
At the end it offers to bulk-mark everything it opened as Completed in
the registry (you confirm once, not per-broker).
If no tabs open: this is almost never a script bug — it means
webbrowser.open()/xdg-open can’t reach a working browser. Check:
xdg-open https://example.com # does this alone work?
On this machine the cause was a broken Firefox snap (stale GPU-wrapper
content interface after a snapd/gnome-sdk update — error message:
Content snap GPU wrapper ... not found: ensure slot is connected).
Fix: close Firefox, then sudo snap refresh firefox. Switching the
default browser to a non-snap install (e.g. google-chrome) sidesteps
this class of problem entirely.
scripts/email_watcher.py)Most brokers require clicking a confirmation link emailed to you before
the opt-out actually takes effect. This script polls a dedicated inbox via
IMAP, matches senders against the domains already in your registry
(root-domain match, so mail.lexisnexis.com and optout.lexisnexis.com
both match), extracts the confirmation link from the body, and opens it.
Setup:
cp ~/Projects/cyber-kb/scripts/.env.example ~/Projects/cyber-kb/scripts/.env
# edit .env: IMAP_HOST, IMAP_USER, IMAP_PASS (use a dedicated/burner inbox
# and an app-specific password, not your main email password)
Usage:
python3 email_watcher.py --once # single dry-run pass, prints links, opens nothing
python3 email_watcher.py --once --auto # single pass, opens matched confirmation links
python3 email_watcher.py --auto # polls continuously (default: every 60s)
.env is already covered by the repo’s *.env gitignore rule — never
commit real credentials.
For brokers whose opt-out is a plain email rather than a web form, use the template text block at the bottom of master-registry.md.