Reduce your data footprint to the empty set.
Find where your personal data is being sold — data brokers, people-search sites, B2B contact platforms — and generate the erasure requests, AI-training objections and regulator complaints that get you off those lists. Runs entirely on your machine, driven by Claude Code.
Data brokers collected your data without asking. Then they make you do the paperwork to remove it — a different form per company, buried three clicks deep, each with its own rules. NullSet flips that burden back onto them.
- What it actually does
- What you need, and how the analysis actually runs
- Install
- How to use it — the full walkthrough
- Command reference
- What it asks you for (and what it refuses to store)
- How the likelihood score works
- Your rights, by jurisdiction
- Repository layout
- Who is in the registry
- Contributing
- FAQ
- Credits
Discover → Confirm → Remove → Escalate → Monitor
| Step | What happens | |
|---|---|---|
| 1 | Scan | Searches people-search sites and indexed broker pages for your name, email and phone. For paywalled B2B brokers (Lusha, Apollo, ZoomInfo…) it scores how likely you are to be in there, and shows you the arithmetic. |
| 2 | Exposure Map | A local report: what is confirmed (with the evidence URL), what is likely and why, plus a checklist of AI-training opt-out toggles. |
| 3 | Draft | Erasure and objection letters with the right legal citations for your jurisdiction, addressed to each company's actual DPO. |
| 4 | DSAR-as-scanner | For brokers you cannot see into, it drafts an access request they are legally obliged to answer. The law becomes your scanner: the reply turns "likely" into confirmed-with-evidence, or clean-on-the-record. |
| 5 | Action Center | A local dashboard: every opt-out link, a prefilled email draft, one-click copy for each field, and an autofill bookmarklet that fills a broker's web form for you. |
| 6 | Escalate | Tracks every statutory deadline. When a company ignores you, it drafts the complaint for your regulator — 20 of them are in the registry, from a GDPR Art. 77 filing 🇪🇺 and an ICO complaint 🇬🇧 to an ANPD petição 🇧🇷, an OAIC complaint 🇦🇺 or a POPIA Form 5 🇿🇦 — with your evidence trail attached. |
| 7 | Harden | Closes the tap: the LinkedIn settings that feed these databases, a dated reservation-of-rights notice for your profile, robots.txt blocks for AI crawlers, and the telemarketing blocklists. docs/HARDENING.md |
Nothing is ever sent automatically. Every letter is a file you read and send yourself. There is no server, no account and no telemetry, and nothing about your case is stored anywhere but your own disk. Searching for yourself does mean your identifiers travel as search queries during the scan — see what leaves your machine for the honest version.
There are three moving parts, and only one of them is this repository.
| What it is | What it costs | |
|---|---|---|
| 1. This repo | Plain text: the workflow file Claude Code reads, 71 broker records as YAML, letter templates, and a zero-dependency CLI. It makes no network calls at all — you can check: grep -rn "fetch(|node:http" bin lib returns nothing. |
free, MIT |
| 2. Claude Code, on your machine | The engine. It reads the workflow, runs the searches, reads the pages, does the scoring and writes the letters into your folder. | see below |
| 3. Your own Claude account | What authenticates and pays for those requests. Not mine. There is no NullSet server, no shared API key, no sign-up, no telemetry, and no account with me. | your existing plan |
Not if you have a paid Claude plan. Claude Code accepts either:
- A Claude subscription — Pro, Max, Team or Enterprise. You run
claude, it opens your browser, you log in, done. No key to paste anywhere. This is what most people will use. - An Anthropic Console account — pay-as-you-go per token. If you have
ANTHROPIC_API_KEYset in your environment, Claude Code asks you once to approve it instead of opening a browser. - A cloud provider — Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry, for people whose company already routes models that way.
One honest caveat: the free Claude.ai plan does not include Claude Code. If you are on free, this tool cannot run for you, and no workaround here changes that.
# 1. install Claude Code (macOS / Linux / WSL — Windows and Homebrew options in the docs)
curl -fsSL https://claude.ai/install.sh | bash
# 2. log in: this opens your browser once, then remembers you
claude
# 3. get NullSet
git clone https://github.com/Bettercallcoutinho/nullset.git
cd nullset
# 4. build your case folder (a short interview — no API key, no account)
node bin/nullset.mjs init
# 5. start Claude Code inside this folder and say what you want
claudeThen, in plain language: "scan my data exposure and draft the removal requests." Claude Code finds the
workflow file in .claude/skills/nullset/ automatically because you are inside the clone, works through
the registry, and writes everything into nullset-case/.
Prefer not to use a terminal at all? The Claude Code desktop app (macOS, Windows, Linux) runs the same session with a graphical interface.
- Reads your
profile.yaml— the file the interview wrote, sitting in your folder. - For each broker whose data is public, fetches its lookup page and runs exact-match searches for your name, email and phone. A hit becomes CONFIRMED, with the URL saved as evidence.
- For each broker that is paywalled, it cannot see inside, so it scores the likelihood from your public footprint and shows you the arithmetic — then offers the access request that settles it legally.
- Writes the Exposure Map, the letters and the dashboard as files in
nullset-case/.
The search and page-reading are Claude Code's own built-in web search and fetch. If your organisation or environment has web search turned off, the scan falls back to fetching each broker's own lookup URL and to the access-request route — slower, still effective, because the law obliges an answer either way.
Running a scan means asking a model to search for you, so the identifiers you are searching for do go out as search queries and prompts — to Anthropic, and to the search provider behind the web-search tool — for the duration of that session. That is inherent to any tool that looks for you online, including the paid removal services. What is different here:
- Nothing is stored anywhere but your disk. No account, no server-side case file, no database of users.
- Nothing is ever sent on your behalf. Every letter is a file you read and send yourself.
- The author sees nothing. There is no channel back to me, by design.
- If even that is more exposure than you want, run the scan with only the identifiers you are willing to search for — the tool works with a name alone, and you can add the phone number later.
- Node.js 18+ for NullSet's own CLI —
node --version. Zero dependencies, nothing tonpm install. - Claude Code on a paid plan, per the section above. Its own installer needs no Node.
- A supported country and an internet connection — Claude Code's requirement, not NullSet's.
- About 20 minutes for the first pass, then ~5 minutes every couple of months.
git clone https://github.com/Bettercallcoutinho/nullset.git
cd nullset
node bin/nullset.mjs initThe skill lives in .claude/skills/nullset/, so Claude Code picks it up automatically when you start
it inside this folder. Nothing else to configure.
Makes NullSet available in every Claude Code session, from any directory:
git clone https://github.com/Bettercallcoutinho/nullset.git
cd nullset
node bin/nullset.mjs install # copies the skill to ~/.claude/skills/nullset/Your case folder is still created in whatever directory you run it from — keep using one dedicated folder so your history stays in one place.
npm link # then you can type: nullset initnode bin/nullset.mjs initA short interview — name and the variants you have used professionally, your emails, phone, city/country, employer and title if they are public, LinkedIn URL. It tells you what each field is for, and it refuses to store a CPF, SSN or passport number.
It writes:
nullset-case/
├── profile.yaml ← your identifiers, local only, gitignored
├── exposure-map.md ← empty for now
├── tracking.md ← the deadline ledger
└── outbox/ ← letters land here
Your country decides the legal track, and it knows about 30-odd of them: GDPR (EU/EEA, 1 month, your
national DPA), UK GDPR, revFADP 🇨🇭, LGPD 🇧🇷 (15 days), CCPA/CPRA + the Delete Act 🇺🇸 and the other US
state acts (45 days), PIPEDA and Quebec Law 25 🇨🇦, the Privacy Act 🇦🇺, Privacy Act 2020 🇳🇿, PDPA 🇸🇬,
APPI 🇯🇵, PIPA 🇰🇷, POPIA 🇿🇦, KVKK 🇹🇷, DPDP 🇮🇳, LFPDPPP 🇲🇽 and the LATAM statutes. Living abroad? You
probably get two — and two laws make a stronger letter than one. Full map:
docs/JURISDICTIONS.md.
claudeThen say:
"Scan my data exposure and draft the removal requests."
Claude Code reads your profile and works through the registry: fetching public people-search pages,
running exact-match searches for your name, email and phone in every format, sweeping the families of
sites that share one database, and scoring the paywalled brokers. Anything it finds on a company the
registry does not know about goes on the map anyway. It shows you the work as it goes, and writes
exposure-map.md.
If the calls have already started, tell it: "a rep from X called me and said they got my number from Y." A named source beats every inference score in the tool — and asking the caller where they got your number usually works, because to them it is not a secret, it is a subscription.
Open nullset-case/exposure-map.md. Three things to check:
- CONFIRMED — there is an evidence URL. Click it. If it is not you, say so and it gets removed.
- LIKELY / POSSIBLE — read the score breakdown.
public LinkedIn (+40), corporate email (+20)is an argument, not a fact. You decide whether it is worth a request. - AI-training opt-outs — a checklist of toggles you can flip yourself in a few minutes.
Tell Claude which targets to act on, or just:
"Draft erasure requests for everything confirmed, and access requests for the likely ones."
Each letter arrives in nullset-case/outbox/ as e.g. 2026-08-26_rocketreach_erasure.md, with the
destination address at the top. They cite the articles that actually apply to you, name the controller
entity, attach your evidence URL, and demand the four things people usually forget to ask for:
- erasure of the data,
- the source it was collected from,
- the recipients it has already been sold to — and that they be notified,
- suppression of your identifiers, so you are not re-collected in the next crawl.
node bin/nullset.mjs actions
open nullset-case/action-center.htmlA local dashboard, one card per company:
- Open opt-out form ↗ — goes straight to that company's real removal page.
- Draft email ↗ — opens your mail client with the recipient, subject and full letter prefilled.
- Copy letter — the whole letter on your clipboard, for web forms that want a message body.
- Copy buttons for each single value a form will ask for.
The autofill bookmarklet. Drag the ∅ Fill this form button onto your browser's bookmarks bar. Now, on any broker's opt-out form, click it: it matches the page's fields against your profile and fills in your name, email, phone, city, country, employer, title and the request text. It never submits — you review it, solve the CAPTCHA, and press send yourself.
⚠️ Your profile travels inside the bookmark itself. That is what lets it work with no server and no network call — but it also means browser bookmark sync (Chrome Sync, iCloud, Firefox Sync) would replicate those identifiers to your browser vendor's cloud. Use it in a browser profile with sync off, or delete the bookmark when you are done —nullset actionsrebuilds it in a second.
Send the emails and submit the forms. Then open nullset-case/tracking.md and flip sent? to yes
for each one — or tell Claude "I sent the RocketReach and Spokeo requests today" and it fills the
ledger and computes each deadline for you.
This ledger is what makes escalation possible later. A complaint without dates is just a complaint.
node bin/nullset.mjs statustarget type sent deadline days status
rocketreach erasure yes 2026-09-25 12 left awaiting response
spokeo erasure yes 2026-09-10 3 over no response
When a deadline passes with no adequate answer:
"Escalate the expired deadlines."
You get the filled complaint in outbox/, addressed to the authority that actually covers you — a GDPR
Art. 77 complaint to your national DPA, an ICO complaint, an ANPD Petição de Titular or Denúncia, an OAIC
or OPC complaint, a POPIA Form 5, a KVKK filing. It checks that regulator's admissibility rules first,
because they differ: Türkiye, Canada and Australia require a prior request to the company (it is right
there in your outbox), and German complaints about a private company go to the state authority, not the
federal one. Paste the company's reply into Claude and it will classify it:
complied, partial, demanding excessive ID (itself a violation — GDPR Art. 12(2), LGPD Art. 18 §3º),
refused, or stalling.
Brokers re-collect. A clean result is a snapshot, not a state.
"Re-scan my exposure and compare against last time."
It diffs against your previous map and flags reappearances. A reappearance after a confirmed erasure is a fresh violation — and the single strongest fact you can put in front of a regulator.
Deleting without hardening buys you about 60 days: the brokers rebuild from the same source, and that source is usually your public professional profile.
"Harden my profile against this."
It walks docs/HARDENING.md with you: the exact LinkedIn settings that feed these
databases (AI-training toggle, discovery by email and phone, off-LinkedIn visibility, third-party
sharing), a dated reservation-of-rights notice for your About section in English or Portuguese, the
robots.txt block list for AI crawlers on your own domains, and the telemarketing registers that stop
the calls this week — Não Me Perturbe 🇧🇷, Procon, donotcall.gov 🇺🇸, TPS 🇬🇧.
The notice is a legal signal and dated evidence, not a firewall: it removes the "they could not have known you would mind" argument that legitimate interest rests on. The letters are what bind them.
| Command | What it does |
|---|---|
node bin/nullset.mjs init |
Guided setup. Builds nullset-case/. |
node bin/nullset.mjs actions |
Rebuilds the Action Center dashboard from your case. |
node bin/nullset.mjs status |
Deadline table: what is running, what has expired. |
node bin/nullset.mjs install |
Installs the skill to ~/.claude/skills/nullset/. |
node bin/nullset.mjs doctor |
Checks Node, the registry, and that your PII is gitignored. |
node bin/nullset.mjs |
No argument: resumes where you left off. |
Everything else — the scanning, the drafting, the escalation — happens by talking to Claude Code inside the folder.
Collected (all optional except name, email and country): name + variants · email addresses · phone numbers · city and country · employer and job title · LinkedIn URL.
That is deliberately the same set a broker already sells. Nothing extra helps you, and everything extra is one more thing sitting on your disk.
Never collected: CPF · SSN · passport or national ID numbers · document scans · passwords.
The wizard actively rejects them, and the letters tell the company that a disproportionate identity demand is itself unlawful (GDPR Art. 12(2) + EDPB Guidelines 01/2022; LGPD Art. 18 §3º). If a portal genuinely requires ID verification, you do that inside that portal, yourself. NullSet never brokers your documents.
nullset-case/ is gitignored. nullset doctor fails loudly if that ever stops being true.
action-center.html lives in that same folder and holds your profile in cleartext — that is what
makes the copy buttons and the autofill work with no server. Treat it as the case file it is: do not
send the file to anyone, and crop your screenshots.
For brokers whose database is behind a login, nobody can confirm from the outside — so NullSet scores instead of guessing, and always shows its work:
| Signal | Points |
|---|---|
| Public LinkedIn profile | +40 |
| Corporate email domain | +20 |
| Job title visible on LinkedIn | +15 |
| Broker covers your country / sector | +15 |
| An indexed stub page turns up in search | +10 |
≥ 70 → LIKELY · 40–69 → POSSIBLE · < 40 → UNKNOWN. An indexed page that is unmistakably you is promoted straight to CONFIRMED.
The honest way to resolve a LIKELY is the access request: the company has to tell you, in writing, within 15–30 days, whether it holds your data. That answer is worth more than any score.
| Law | Deadline | Erasure | Objection to marketing/resale | Regulator | |
|---|---|---|---|---|---|
| 🇪🇺 | GDPR (EU 2016/679) | 1 month | Art. 17 | Art. 21(2) — absolute | your national DPA |
| 🇬🇧 | UK GDPR + PECR | 1 month | Art. 17 | Art. 21(2) | ICO |
| 🇨🇭 | revFADP | ~30 days | Art. 32 | Art. 30 | FDPIC |
| 🇧🇷 | LGPD (Lei 13.709/2018) | 15 days | Art. 18, VI | Art. 18, §2º | ANPD |
| 🇺🇸 | CCPA/CPRA + Delete Act (CA) | 45 days | §1798.105 | §1798.120 + DROP | CalPrivacy |
| 🇺🇸 | ~20 other state privacy acts | 45 days | yes | opt out of sale + targeted ads | state Attorney General |
| 🇨🇦 | PIPEDA · Quebec Law 25 | 30 days | consent withdrawal; Quebec: de-indexing | CASL + National DNCL | OPC · CAI |
| 🇦🇺 | Privacy Act 1988 (APPs) | 30 days | no general right — ask for cessation + destruction | APP 7 + Do Not Call Register | OAIC |
| 🇳🇿 | Privacy Act 2020 | 20 working days | no general right — IPP 13 correction | cessation of disclosure | OPC |
| 🇸🇬 | PDPA | 30 days | withdrawal → deletion | DNC Registry, same regulator | PDPC |
| 🇯🇵 | APPI | reasonable period | unlawfully obtained data | cessation of third-party provision | PPC |
| 🇰🇷 | PIPA | ~10 days | yes | suspension of processing | PIPC |
| 🇿🇦 | POPIA | 30 days | s. 24 | s. 11(3) Form 2 + s. 69 | Information Regulator |
| 🇹🇷 | KVKK (6698) | 30 days, prior request mandatory | Art. 7 | Art. 11 | KVKK |
| 🇲🇽 🌎 | LFPDPPP (ARCO) · AR, CL, CO, PE, UY | 10–20 days | Cancelación | Oposición | SABG · AAIP · SIC · APDP … |
| 🇮🇳 🇨🇳 🇮🇱 🇳🇬 🇸🇦 🇦🇪 | DPDP · PIPL · PPL · NDPA · PDPL | ~30 days | yes | yes | see the full map |
Objection to direct marketing under GDPR Art. 21(2) — and its LGPD twin, Art. 18 §2º — has no balancing test: the company must stop. That is usually the strongest sentence in your letter. Where a regime has no erasure right at all (Australia, New Zealand), the letter asks for cessation and destruction instead — an Art. 17-shaped demand there just invites a one-line refusal.
Not on the list? You are not out of options: most of these companies are established in the EU, the US
or Israel, so their law reaches them even when yours is silent — and several registry entries carry the
company's EU Art. 27 representative, whose whole job is to answer you. The full country-by-country map,
with the citations and the admissibility traps, is in
docs/JURISDICTIONS.md.
.claude/skills/nullset/SKILL.md the workflow Claude Code follows
bin/nullset.mjs the CLI (init · actions · status · install · doctor)
lib/ YAML reader, registry loader, jurisdictions, dashboard generator
test/ 47 tests, no dependencies — `node --test test/*.test.mjs`
registry/
brokers/*.yaml data brokers: DPO contacts, legal bases, scan method, SLAs
ai/*.yaml AI platforms: training opt-out channels
authorities/*.yaml ANPD, CNPD, DPC, ICO, EDPB directory
templates/en/ templates/pt/ erasure, access and complaint letters
CHANGELOG.md what changed, and which bug each fix was for
docs/REGISTRY.md the registry schema, and where to find new targets
docs/JURISDICTIONS.md country → law, deadline, rights, regulator (30+ regimes)
docs/HARDENING.md LinkedIn lockdown, the profile notice, robots.txt, call blocklists
examples/ what a finished Exposure Map looks like
Currently covering 71 brokers, 12 AI platforms and 20 supervisory authorities. Broker contacts go stale —
every entry carries a last_verified date, nullset doctor warns after 180 days, and the workflow
re-checks a contact before putting it in a letter.
71 companies across four continents, grouped by what they actually sell. Each one is a YAML file in
registry/brokers/ carrying its opt-out channel, DPO address, controller entities, legal basis, statutory
deadline — and how that channel was last verified.
B2B contact data (22) — sells your work email and mobile to sales teams, by subscription
Lusha · Apollo.io · ZoomInfo · Cognism 🇬🇧 · Kaspr 🇫🇷 · Dealfront / Echobot 🇩🇪🇫🇮 · RocketReach · ContactOut · SignalHire · Seamless.AI · LeadIQ · UpLead · Lead411 · SalesIntel · Swordfish AI · Nymeria · Datanyze · Wiza 🇨🇦 · Adapt.io · Amplemarket · Econodata 🇧🇷 · Speedio 🇧🇷
Enrichment / wholesale APIs (9) — sells the same data to other products, so you never see the name
People Data Labs · Coresignal 🇱🇹 · Clearbit (HubSpot Breeze Intelligence) · Hunter.io · Prospeo 🇫🇷 · Snov.io · Skrapp.io · Bright Data 🇮🇱 · Dropcontact 🇫🇷
People-search (22) — public listings, indexed by Google, free to read
Pipl (global) · Spokeo · BeenVerified · Radaris · Whitepages · TruePeopleSearch · FastPeopleSearch · Intelius · PeopleFinders · TruthFinder · Instant Checkmate · MyLife · Nuwber · ThatsThem · Social Catfish · SmartBackgroundChecks · 192.com 🇬🇧 · Ratsit 🇸🇪 · MrKoll 🇸🇪 · Canada411 / Yellow Pages 🇨🇦 · White Pages 🇦🇺 · Casa dos Dados 🇧🇷
Marketing data and identity graphs (13) — household profiles, intent data, cross-site IDs
Acxiom · LiveRamp · Experian (marketing) · Epsilon · Data Axle · LexisNexis Risk · Bombora · Dun & Bradstreet · Cerved 🇮🇹 · eInforma / Informa D&B 🇪🇸 · BigDataCorp 🇧🇷 · Neoway 🇧🇷 · Assertiva 🇧🇷
Credit bureaus that also monetise marketing data (5)
SCHUFA 🇩🇪 · Creditreform 🇩🇪 · Experian UK 🇬🇧 · Serasa Experian 🇧🇷 · Equifax BVS, ex-Boa Vista 🇧🇷
AI platforms (12) — training opt-outs and crawler blocks: OpenAI · Anthropic · Google · Meta · Microsoft · Apple · Amazon · X/Grok · Perplexity · LinkedIn · Common Crawl · Spawning (Have I Been Trained).
Supervisory authorities (20) — one escalation path per region: ANPD 🇧🇷 · CNIL 🇫🇷 · AEPD 🇪🇸 · Garante 🇮🇹 · the German federal + state authorities 🇩🇪 · CNPD 🇵🇹 · DPC 🇮🇪 · the EDPB directory for the rest of the EU/EEA · ICO 🇬🇧 · FDPIC 🇨🇭 · CalPrivacy 🇺🇸 · OPC + CAI Québec 🇨🇦 · OAIC 🇦🇺 · OPC 🇳🇿 · PDPC 🇸🇬 · PPC 🇯🇵 · PIPC 🇰🇷 · KVKK 🇹🇷 · Information Regulator 🇿🇦 · India's DPDP Board 🇮🇳.
Each authority entry carries its own admissibility rules, because they differ in ways that cost you months if you get them wrong: Türkiye and Canada require a prior request to the company, Germany routes private-sector complaints to the state authority rather than the federal one, and CalPrivacy's DROP is a single deletion request that every registered broker has had to honour since 1 August 2026.
Not every entry has a self-service form — but far more of them do than you would guess, and the form is
usually hidden in a footer under "Do Not Sell or Share My Personal Information", "Opt out" or
"Portal do Titular", not in the privacy policy. Where the registry says there is no form, it says how the
channel was checked: live-check (the URL answered on that date), documented (from the company's own help
centre, but bot-blocked), or unverified — and doctor keeps nagging about the last kind until someone
confirms it.
The registry is plain YAML on purpose — you do not need to read the code to improve it.
- Add a broker — copy any file in
registry/brokers/, fill it in, open a PR. Seedocs/REGISTRY.mdfor the schema. Includelast_verifiedandverification. Runnode --test test/*.test.mjsfirst; CI runs it on your PR on Node 18 through 24. The suite exists so your entry can be merged without anyone re-reading the whole registry: it checks that ids match filenames, that channel URLs are absolute, that emails are emails, that deadlines are numbers a statute could support, and that no CPF- or SSN-shaped number ever lands in a file. - Verify an entry — DPO addresses and opt-out URLs move constantly. A PR that just re-checks and re-dates existing entries is as valuable as a new one.
- New jurisdictions and languages — Spanish templates are the obvious next step.
Found yourself on a broker that is not covered? Claude Code will offer to draft the registry entry for it during your scan. Send it upstream.
Does this send anything on my behalf? No. It produces files and opens links. Every send is a deliberate act by you. That is a design constraint, not a limitation — an automated blast in your name would be both less effective and, in some places, legally dubious.
How does the scanning actually work — and whose AI account does it use? Yours, on your machine, under your own Claude login — there is no NullSet server, no shared key and no account with me. You do not need an API key if you have a paid Claude plan. Full answer, with the five commands and an honest account of what travels over the network: what you need, and how the analysis actually runs.
Is scanning these sites legal? You are searching public pages for your own data, and then exercising a statutory right. That is squarely what these laws are for. NullSet does not bypass CAPTCHAs, logins or paywalls — when a lookup is gated, it falls back to the access request, which is the lawful way in.
Can I use it for someone else? Only as a documented representative or guardian. The workflow is built for a person acting on their own behalf, and it will say so if you ask it to profile a third party.
Why does it want my LinkedIn URL? Because it is the single most common source of a B2B broker record. It is optional — but if your profile is public, that is very likely how you got into Lusha and Apollo.
Does it work outside Brazil and the EU?
Yes — that is the point. The jurisdiction map covers 30-plus regimes and the registry carries 20
regulators, from the OAIC and the OPC to the PDPC, the PPC, the PIPC, the KVKK and South Africa's
Information Regulator, each with its own admissibility rules. The letter templates are English and
Portuguese today and are drafted in other languages on request; full templates/es/, templates/fr/ and
templates/de/ sets are the most useful contribution anyone can make. And if your country has no
data-protection law at all, the letter uses the company's own regime — most of these firms are established
in the EU, the US or Israel, and several publish an EU Art. 27 representative whose whole job is to answer
you.
A company has an opt-out page and NullSet says it doesn't. What now? Tell it — "Lusha has a removal form, find it" — and it will search, use it, and offer to update the registry entry with the URL and today's date. That is how the registry grew: the forms are usually in the site footer under "Do Not Sell or Share My Personal Information" or "Portal do Titular", almost never linked from the privacy policy. Send the fix upstream as a PR and everyone else gets it too.
Nothing was found. Is it broken?
Run node bin/nullset.mjs doctor. An empty map is a real result if your professional footprint is
small — but check that your name variants and work email are in profile.yaml, since those are what
the B2B brokers key on.
NullSet provides legal information and document drafting assistance — not legal advice. It is not a law firm and does not represent you. Laws referenced include GDPR (EU 2016/679), UK GDPR, revFADP, LGPD (Lei 13.709/2018), CCPA/CPRA and the US state privacy acts, PIPEDA and Quebec Law 25, the Australian Privacy Act 1988, New Zealand's Privacy Act 2020, PDPA, APPI, PIPA, POPIA, KVKK, DPDP and LFPDPPP. Deadlines and legal bases are recorded to the best of the registry's knowledge and are re-verified at draft time; for a complex or high-stakes case, talk to a qualified professional in your jurisdiction.
Built by Better Call Coutinho.
→ linkedin.com/in/gacoutinho — LinkedIn is the only contact channel for this project. There is no contact email, by design.
Made for anyone who has ever gotten a cold sales call and wondered how did they get my number. If NullSet got you off a list, tell me about it — and star the repo so the next person finds it.
- Code and templates: MIT
- Registry data (
registry/): CC-BY-SA 4.0 — derivatives must stay open, so the contact data keeps flowing back to the people who need it.