Skip to main content

OptOut

Self-hosted CLI that automates CCPA/CPRA data-broker opt-out requests.

CI PyPI Python License: AGPL v3


optout status

optout scan


Why this exists

CCPA and CPRA give California residents the right to demand deletion of their data from any company that sells it. Data brokers — Whitepages, BeenVerified, Spokeo, and dozens more — are legally required to comply. They also make exercising that right as hostile as possible: a different form on every site, CAPTCHAs, phone verification calls, 45-day deadlines you have to track manually, and data that silently reappears 60–90 days later.

OptOut automates the hostile parts. You run it on your own machine with your own information. There is no central server, no account, no SaaS subscription — which means the "authorized agent" legal complexity that DeleteMe and Optery have to navigate simply does not apply.


Install

pipx install optout
playwright install chromium   # one-time browser download (~130 MB)
optout init                   # interactive setup wizard

Requirements: Python 3.12+, pipx, Playwright


Quickstart

optout init                      # create ~/.config/optout/config.yml
optout queue                     # add all brokers to the submission queue
optout submit                    # open Chrome, walk each broker's form
optout status                    # table of deadlines and statuses
optout monitor                   # re-scan; re-queues brokers that re-added you

optout submit opens a real Chrome window for each broker. It fills every form field it can, then pauses with a prompt when human action is needed (CAPTCHA, listing selection, phone verification).


Supported brokers

Broker Method Automation Human steps Last verified
BeenVerified Web form Partial Click listing; solve Turnstile CAPTCHA 2026-05-10
MyLife Web form Partial Solve reCAPTCHA; click Submit 2026-05-10
Radaris Web form Mostly automated Click listing; click "Start Removing" 2026-05-10
Spokeo Web form Partial Click listing; confirm email 2026-05-10
Whitepages Web form Partial Click listing; answer phone call 2026-05-10

All five brokers are verified end-to-end as of 2026-05-10. New brokers are added as YAML files — no Python required. See CONTRIBUTING.md.


How it works

OptOut reads broker definitions from YAML files bundled with the package. Each YAML declares the broker's opt-out URL, required fields, and a list of steps. The engine walks those steps using a persistent Playwright Chromium context, so Cloudflare Turnstile cookies survive between runs and you only solve those challenges once.

flowchart LR
    CLI["optout CLI\nTyper + Rich"]
    DB[("SQLite\nsubmissions\ndeadlines")]
    Registry["Broker Registry\nYAML → Pydantic"]
    Dispatcher["Dispatcher"]
    WebForm["web_form\nPlaywright engine"]
    Email["email\nSMTP handler"]
    Chrome(["Chromium\npersistent profile"])
    Brokers(["Live broker\nwebsites"])

    CLI --> Registry
    CLI --> DB
    CLI --> Dispatcher
    Dispatcher --> WebForm
    Dispatcher --> Email
    WebForm --> Chrome
    Chrome --> Brokers

Submissions are tracked in a local SQLite database. optout status surfaces anything overdue. optout monitor re-scans and re-queues automatically — safe to run from cron.


Commands

optout init                          # interactive setup wizard
optout doctor                        # check that everything is installed correctly
optout brokers list [--category]     # list all known brokers
optout brokers info <slug>           # details + your submission history
optout scan    [--broker SLUG]       # check which brokers list you (no submissions made)
optout queue   [--broker SLUG]       # add brokers to the submission queue
optout submit  [--broker SLUG] [-v]  # process the queue; -v shows debug output
optout status  [--broker] [--status] # table of submissions and deadlines
optout monitor                       # one-shot re-scan (cron-friendly)
optout verify  [--broker SLUG]       # check whether broker form selectors still work

Configuration

optout init writes ~/.config/optout/config.yml (mode 600). Key sections:

profile:
  legal_name: "Jane Q Public"
  dob: "1990-05-14"
  current_address:
    street: "123 Main St"
    city: "Austin"
    state: "TX"
    zip: "78701"
  emails:
    current: ["jane@example.com"]
  phones:
    current: ["+15125551234"]

email:
  method: smtp
  smtp:
    host: smtp.gmail.com
    port: 587
    username: jane@example.com
    password_env: OPTOUT_SMTP_PASSWORD   # read from env, never stored in file

playwright:
  headless: false    # keep false so you can solve CAPTCHAs
  slow_mo_ms: 0

Runtime data lives at:

Path Contents
~/.config/optout/config.yml Your profile and settings
~/.config/optout/browser_profile/ Persistent Chrome profile (keeps Cloudflare cookies warm)
~/.local/share/optout/optout.db SQLite — submissions, events, scan history
~/.local/share/optout/artifacts/ Confirmation screenshots

Adding a broker

New brokers are a single YAML file — no Python needed. Five steps:

1. Verify the opt-out flow manually in a real browser. Note every field, selector, and verification step.

2. Copy the nearest template:

cp src/optout/data/brokers/radaris.yml src/optout/data/brokers/new-broker.yml

3. Fill in the metadata — slug, name, domain, method, opt_out_url, legal_basis, statutory_response_days.

4. Write the steps — each step is a type (navigate, form_fill, click, wait_for, prompt_user_if_present, capture) with the relevant CSS selectors.

5. Validate:

uv run pytest tests/test_production_brokers.py -v
uv run optout verify --broker new-broker --headed

Full step reference and template variables are in CONTRIBUTING.md.


Honest limitations

  • Removal is not guaranteed. Some brokers comply in days; others take the full 45-day window or ignore requests.
  • Data reappears. 60–90 days is typical. Run optout monitor monthly to catch this.
  • CAPTCHAs require a human. The tool pauses and prompts — no CAPTCHA solving, by design.
  • Broker forms change. When a broker redesigns their opt-out page, the YAML selectors need updating. optout verify catches this; optout verify --headed shows you exactly what changed.
  • Phone verification is manual. Whitepages calls your phone; you enter the code. The tool waits.

Legal basis

OptOut cites the applicable statute in every submission:

  • CCPA §1798.105 — right to deletion, 45-day response window
  • CPRA — extends CCPA with stronger enforcement
  • GDPR Art. 17 — right to erasure, 30-day response window

Each broker's YAML declares which statutes apply. See COMPLIANCE.md for the full legal posture.


License

AGPL-3.0-only. See LICENSE.

This license was chosen intentionally: anyone who forks this and runs it as a hosted service must publish their changes. The project's legal model depends on each user running their own copy.

Metadata

Release files for optout 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for optout 0.2.0
File Size Uploaded
optout-0.2.0.tar.gz 70.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for optout 0.2.0
File Interpreter ABI Platform
optout-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 129.2 kB

Release files / optout-0.2.0.tar.gz

Download URL optout-0.2.0.tar.gz
Size 70.6 kB
Tags Source
SHA-256 checksum
How to use checksums
ff1e47eef880ff34c6b7b42f9051f304858cb7269563ff2ec7bc61670e6dac51
BLAKE2b-256 checksum
How to use checksums
f8a7252d81f2cee8cbf4cc8f91990d75e285754aba13323f099cfeaa962ec53f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

Release files / optout-0.2.0-py3-none-any.whl

Download URL optout-0.2.0-py3-none-any.whl
Size 58.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7d45aae27e505b95261e70f0b86ad47f572120a839e311c86c655fd1ddc783ed
BLAKE2b-256 checksum
How to use checksums
e82bd41c42a734ccd518c6c003a14b44f46421b8c64f5f6fc2f26f7db97110e5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page