Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"id": "addresses",
|
||||
"name": "Addresses.com",
|
||||
"category": "people_search",
|
||||
"priority": "standard",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"covered_by": "intelius",
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.addresses.com/",
|
||||
"fetch": "web_extract",
|
||||
"match_signal": "result",
|
||||
"by": [
|
||||
"name"
|
||||
],
|
||||
"url_patterns": {
|
||||
"name": "https://www.addresses.com/people/{First}+{Last}"
|
||||
},
|
||||
"url_format_quirks": [
|
||||
"Name people page: /people/{First}+{Last} (a literal '+' joins first and last). Surfaced a real subject listing during the OSINT cross-check.",
|
||||
"It is a PeopleConnect/Intelius FRONT-END: every 'report' link resolves to tracking.intelius.com. The data is the Intelius cluster's."
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T1",
|
||||
"method": "web_form",
|
||||
"url": "https://suppression.peopleconnect.us/login",
|
||||
"requires": {
|
||||
"profile_url": false,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"contact_email"
|
||||
],
|
||||
"notes": "COVERED BY THE INTELIUS/PEOPLECONNECT CLUSTER -- do NOT file a separate opt-out. addresses.com is a front-end (report links -> tracking.intelius.com), and 'addresses' is listed in intelius.owns, so one PeopleConnect suppression (see intelius.json) removes it too. Recorded here only so the scan cross-check has the URL pattern and knows it maps to the parent. After the intelius suppression confirms, re-scan this URL to verify it dropped.",
|
||||
"quirks": [
|
||||
"Front-end only; holds no independent removal channel. The PeopleConnect Suppression Center is the lever."
|
||||
],
|
||||
"est_processing_days": 7,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": "2026-07-03",
|
||||
"source": "field_verified",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"id": "advancedbackgroundchecks",
|
||||
"name": "AdvancedBackgroundChecks",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": ["US"],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.advancedbackgroundchecks.com",
|
||||
"fetch": "web_extract",
|
||||
"match_signal": "result",
|
||||
"by": ["name", "phone", "address"],
|
||||
"url_patterns": {
|
||||
"name": "https://www.advancedbackgroundchecks.com/name/{first}-{last}",
|
||||
"name_state": "https://www.advancedbackgroundchecks.com/name/{first}-{last}/in/{ST}",
|
||||
"phone": "https://www.advancedbackgroundchecks.com/phone/{digits10}",
|
||||
"address": "https://www.advancedbackgroundchecks.com/address/{num}-{street-with-type}-{city}-{ST}-{zip}",
|
||||
"person_profile": "https://www.advancedbackgroundchecks.com/find/person/{first}-{last}-{22charID}"
|
||||
},
|
||||
"url_format_quirks": [
|
||||
"All path segments lowercase, spaces -> hyphens. Name: /name/jane-public ; name+state: /name/jane-public/in/NY (state 2-letter UPPERCASE).",
|
||||
"Phone: /phone/5551234567 (10 digits, NO punctuation).",
|
||||
"Address: /address/123-main-st-anytown-ny-12345 (all hyphen-joined incl. ZIP; abbreviations like 'S' and 'Ave' kept verbatim, not expanded).",
|
||||
"Removable unit is the person profile: /find/person/{first}-{last}-{22charID} (opaque mixed-case ID). Also /find/name/{first}-{last} and /find/name/{first}-{last}/in/{ST}.",
|
||||
"NO 404s for plausible patterns: an empty search returns a soft-200 page with 'similar' fuzzy rows. The real 'not found' signal is the ABSENCE of an exact-match block in the results heading, NOT an HTTP error. Do not record not_found off a 404 here; read the heading.",
|
||||
"No anti-bot gating on search/result/phone/address pages (web_extract reads them fine). Site self-brands as 'ActualPeopleSearch' in FAQ text.",
|
||||
"Search tabs: /?tab=phone /?tab=email /?tab=address. Directories: /lastnames/{surname} /firstnames/{first} /people/{state-name}/{city-name} /people/zip/{zip} /people/areacode/{code}."
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://www.advancedbackgroundchecks.com/opt-out",
|
||||
"requires": {
|
||||
"profile_url": false,
|
||||
"email_verification": true,
|
||||
"captcha": true,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": ["full_name", "contact_email"],
|
||||
"notes": "Two-step email-verification flow: initial form (radio 'I am: The subject of the request / An authorized agent of the subject', First name*, Middle name, Last name*, Email*, consent) -> emailed link -> full form -> confirmation (processed within 45 days). CAPTCHA-gated: Google reCAPTCHA ('Recaptcha requires verification'). Verified read-only 2026-06-30; not submitted.",
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": "2026-06-30",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"id": "beenverified",
|
||||
"name": "BeenVerified",
|
||||
"category": "people_search",
|
||||
"priority": "crucial",
|
||||
"jurisdictions": ["US"],
|
||||
"parent": "beenverified",
|
||||
"owns": ["peoplelooker", "peoplesmart"],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.beenverified.com/app/optout/search",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"by": ["name", "phone", "email", "address"]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T1",
|
||||
"method": "web_form",
|
||||
"url": "https://www.beenverified.com/svc/optout/search/optouts",
|
||||
"email": "privacy@beenverified.com",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": ["full_name", "contact_email", "profile_url"],
|
||||
"deletion": {
|
||||
"via": "email_followup",
|
||||
"email": "privacy@beenverified.com",
|
||||
"kinds": ["ccpa", "generic"],
|
||||
"notes": "privacy@beenverified.com is the documented address for opt-out, access, deletion, and correction requests (verified from the live privacy policy 2026-07-01). Controller is The Lifetime Value Co. -- a deletion request here can name their other properties too. DPO: dpo@beenverified.com. CCPA window: respond within 45 days (extendable to 90)."
|
||||
},
|
||||
"playbook": [
|
||||
"Opt-out tool at beenverified.com/svc/optout/search/optouts ('Do Not Sell or Share' footer link; the legacy /app/optout/search path serves the same search) -- clears PeopleLooker + PeopleSmart.",
|
||||
"Search the subject, open the matching listing, and submit with the confirmed profile URL + contact email. Email verification: poll-verification picks up the confirmation link; open it in the agent's own browser.",
|
||||
"ONE opt-out per email address via the tool; for additional listings email support@beenverified.com or privacy@beenverified.com.",
|
||||
"FULL DELETION follow-up (right-to-delete, beyond listing suppression): send-email --kind ccpa (CA) / generic to privacy@beenverified.com naming the listing URL(s); as the controller is The Lifetime Value Co., ask that the deletion cover affiliated LTV properties (NeighborWho, Ownerly, NumberGuru, Bumper) in the same request.",
|
||||
"A separate property-search opt-out exists (NeighborWho/Ownerly are property-focused sisters); note residual exposure if relevant and re-scan the children after the parent confirms."
|
||||
],
|
||||
"notes": "Opt-out form + deletion email both verified from the live privacy policy 2026-07-01 (policy dated 2025-10-21). Authorized agents: signed authorization letter or CA POA emailed to privacy@beenverified.com; agent-submitted delete/know requests must include the consumer's name, valid email, age, and address.",
|
||||
"quirks": [
|
||||
"The 'Do Not Sell or Share My Personal Information' footer link now points to /svc/optout/search/optouts (observed 2026-07-01); records citing /app/optout/search are the same tool's older entry.",
|
||||
"One opt-out per email address through the tool; email support for additional removals. The same browser/inbox must open the confirmation link.",
|
||||
"Sister LTV Co. properties (NeighborWho, Ownerly, NumberGuru, Bumper) keep separate opt-out tools -- do NOT assume the BV tool cleared them; the privacy@ deletion request can name them, then verify by scanning each.",
|
||||
"Right-to-know requests get an initial response within 10 days; deletion/access within 45 days (CCPA)."
|
||||
],
|
||||
"est_processing_days": 7,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": "2026-07-01",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"id": "clustal",
|
||||
"name": "Clustal",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": ["US"],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.clustal.org/",
|
||||
"fetch": "web_extract",
|
||||
"match_signal": "record",
|
||||
"by": ["name"],
|
||||
"url_patterns": {
|
||||
"name_index": "https://www.clustal.org/people-search/{letter}/{first-last}/",
|
||||
"name_state": "https://www.clustal.org/people-search/{letter}/{first-last}/{st}/",
|
||||
"record": "https://www.clustal.org/record/{first-last}-{8charID}/"
|
||||
},
|
||||
"url_format_quirks": [
|
||||
"Name index: /people-search/{first-initial}/{first-last}/ e.g. /people-search/k/jane-public/ (lowercase, first letter of LAST name as the {letter} segment, hyphen-joined name). Optional state refine appends /{st}/ lowercase 2-letter.",
|
||||
"Detail (removable unit): /record/{first-last}-{8charID}/ e.g. /record/jane-public-a1b2c3d4/ (opaque mixed-case 8-char id). The index page links each match to its /record/ URL.",
|
||||
"Readable via web_extract (no hard bot gate as of 2026-07-01). Rich profile: age/DOB, current+prior addresses, phones, emails, relatives, neighbors, associates.",
|
||||
"Name only: search is by name(+state); no reverse phone/email/address path observed. NOTE: clustal.org squats the 'Clustal' bioinformatics brand but IS a real people-search/data-broker site ('Find Your DNA Relatives'), not the sequence-alignment tool - do not dismiss it as a false positive."
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T0",
|
||||
"method": "web_form",
|
||||
"url": "https://www.clustal.org/privacy-control/",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": ["profile_url", "contact_email"],
|
||||
"notes": "Opt-out at /privacy-control/ using the /record/ profile URL; support help@clustal.org. Verify the exact form fields + any CAPTCHA live before submitting (requires flags below are provisional from the site's opt-out copy, not yet a live form walk-through).",
|
||||
"email": "help@clustal.org",
|
||||
"est_processing_days": 7,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": "2026-07-01",
|
||||
"source": "BADBOOL",
|
||||
"confidence": "curated"
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"id": "clustrmaps",
|
||||
"name": "ClustrMaps",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"parent": "clustrmaps",
|
||||
"owns": [],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://clustrmaps.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"antibot": "cloudflare",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://clustrmaps.com/bl/opt-out",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"contact_email",
|
||||
"profile_url"
|
||||
],
|
||||
"notes": "Address/resident aggregator. Opt-out at /bl/opt-out: submit the profile URL + email, confirm the link.",
|
||||
"quirks": [
|
||||
"Opt-out URL is the documented public endpoint; datacenter IPs get 403 (anti-bot), so confirm the live flow via the operator's residential browser before the first submission, then set last_verified.",
|
||||
"Needs the confirmed profile_url (the address/person page).",
|
||||
"Email verification required."
|
||||
],
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": null,
|
||||
"source": "curated",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"id": "cyberbackgroundchecks",
|
||||
"name": "CyberBackgroundChecks",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"parent": "cyberbackgroundchecks",
|
||||
"owns": [],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.cyberbackgroundchecks.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"antibot": "cloudflare",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://www.cyberbackgroundchecks.com/removal",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"full_name",
|
||||
"contact_email",
|
||||
"profile_url"
|
||||
],
|
||||
"notes": "Free people-search. Opt-out at /removal: find the record, submit email, confirm link.",
|
||||
"quirks": [
|
||||
"Opt-out URL is the documented public endpoint; datacenter IPs get 403 (anti-bot), so confirm the live flow via the operator's residential browser before the first submission, then set last_verified.",
|
||||
"Needs the confirmed profile_url.",
|
||||
"Email verification required."
|
||||
],
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": null,
|
||||
"source": "curated",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"id": "familytreenow",
|
||||
"name": "FamilyTreeNow",
|
||||
"category": "people_search",
|
||||
"priority": "crucial",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"parent": "familytreenow",
|
||||
"owns": [],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.familytreenow.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"antibot": "cloudflare",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://www.familytreenow.com/optout",
|
||||
"requires": {
|
||||
"profile_url": false,
|
||||
"email_verification": false,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"full_name"
|
||||
],
|
||||
"notes": "Notorious free people-search / doxxing site (no registry). Opt-out: search the record, select it, confirm removal on-site. No account, free.",
|
||||
"quirks": [
|
||||
"Opt-out URL is the documented public endpoint; datacenter IPs get 403 (anti-bot), so confirm the live flow via the operator's residential browser before the first submission, then set last_verified.",
|
||||
"Select the exact record from search results, then confirm removal; historically no email step, but re-lists periodically so keep the re-scan scheduled."
|
||||
],
|
||||
"est_processing_days": 2,
|
||||
"reappearance_risk": "high"
|
||||
},
|
||||
"last_verified": null,
|
||||
"source": "curated",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"id": "fastpeoplesearch",
|
||||
"name": "FastPeopleSearch",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": ["US"],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.fastpeoplesearch.com/",
|
||||
"fetch": "browser",
|
||||
"antibot": "datadome",
|
||||
"match_signal": "result",
|
||||
"match_signal_notes": "SEO TRAP: title/H1/intro echoes the query ('Over 100+ FREE public records found for {Name}') with no real match behind it, and /name/{first}-{last} list pages are fuzzy-SURNAME namesakes (different states, no address overlap). Record `found` ONLY on a result CARD corroborated by the subject's address or DOB. Ignore templated title/intro/H1 text.",
|
||||
"by": ["name", "phone", "address"],
|
||||
"url_patterns": {
|
||||
"name": "https://www.fastpeoplesearch.com/name/{first}-{last}"
|
||||
},
|
||||
"url_format_quirks": [
|
||||
"Name path /name/jane-public (lowercase, hyphen join) was ACCEPTED by the router under challenge, so the name pattern is confirmed even though content never rendered.",
|
||||
"Sibling of truepeoplesearch (near-identical removal flow/branding); phone pattern is LIKELY /{digits} or /phone/{digits} and address /address/... but UNCONFIRMED - do not assume.",
|
||||
"MOST aggressively gated of the people-search trio (2026-06-30): both server-side scraping (Firecrawl 504) AND headless browser (Cloudflare -> DataDome) fail on search AND /removal. Treat as fully blocked; needs residential-proxy/stealth browser to scan or opt out."
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://www.fastpeoplesearch.com/removal",
|
||||
"requires": {
|
||||
"profile_url": false,
|
||||
"email_verification": true,
|
||||
"captcha": true,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": ["full_name", "contact_email"],
|
||||
"notes": "Opt-out NOT directly observed (2026-06-30): /removal is itself behind DataDome. By sibling-site pattern almost certainly mirrors truepeoplesearch (email-link flow, subject/agent toggle, name+email fields, hCaptcha) - INFERRED, not verified. Confirm before acting.",
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "high"
|
||||
},
|
||||
"last_verified": "2026-06-30",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"id": "intelius",
|
||||
"name": "Intelius",
|
||||
"category": "people_search",
|
||||
"priority": "crucial",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"parent": "peopleconnect",
|
||||
"owns": [
|
||||
"truthfinder",
|
||||
"instantcheckmate",
|
||||
"ussearch",
|
||||
"zabasearch",
|
||||
"classmates",
|
||||
"peoplefinder",
|
||||
"peoplelookup",
|
||||
"addresses",
|
||||
"anywho",
|
||||
"publicrecords"
|
||||
],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.intelius.com/",
|
||||
"fetch": "web_extract",
|
||||
"match_signal": "result",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
],
|
||||
"url_patterns": {
|
||||
"name": "https://www.intelius.com/people-search/{First}-{Last}/",
|
||||
"name_state": "https://www.intelius.com/people-search/{first}-{last}/{state-name}/",
|
||||
"full_report": "https://www.intelius.com/search/?firstName={First}&lastName={Last}&city={City}&state={ST}&traffic%5Bsource%5D=INTSEO"
|
||||
},
|
||||
"url_format_quirks": [
|
||||
"Name summary page: /people-search/{First}-{Last}/ (hyphen join; case-insensitive, both Jane-Public and jane-public work). Readable via web_extract (no hard bot gate as of 2026-06-30).",
|
||||
"State refine: /people-search/{first}-{last}/{state-name}/ with the state SPELLED OUT lowercase, e.g. /jane-public/new-york/ (NOT the 2-letter code).",
|
||||
"The summary shows last-known address + a 'possible relatives' list + a FAQ ('Where does X live?'). Corroborate the subject by address before acting; the 'Top People with the Last Name {Last}' block is unrelated namesakes.",
|
||||
"Part of PeopleConnect: same data surfaces on Truthfinder/InstantCheckmate/USSearch; one suppression at suppression.peopleconnect.us covers the cluster."
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T1",
|
||||
"method": "web_form",
|
||||
"url": "https://suppression.peopleconnect.us/login",
|
||||
"email": "privacy@peopleconnect.us",
|
||||
"requires": {
|
||||
"profile_url": false,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false,
|
||||
"dob": true
|
||||
},
|
||||
"inputs": [
|
||||
"contact_email",
|
||||
"full_name",
|
||||
"date_of_birth"
|
||||
],
|
||||
"deletion": {
|
||||
"via": "in_flow",
|
||||
"prefer": false,
|
||||
"url": "https://suppression.peopleconnect.us/guided-mode",
|
||||
"email": "privacy@peopleconnect.us",
|
||||
"kinds": ["ccpa", "generic"],
|
||||
"notes": "INVERTED for PeopleConnect: do NOT use 'Right to Delete / DELETE MY USER DATA' if the goal is staying out of search results. Per their privacy-center, deleting your user data ALSO deletes any suppressions you have, and deletion does NOT stop the people-search sites from showing you (public-records-sourced data re-lists). Suppression is the do-not-display list, so it is the effective lever and must be maintained. Use deletion ONLY if the goal is purging the account data they hold, accepting that you will re-list and must re-suppress. privacy@peopleconnect.us is the rights-request address for that data-purge path. FIELD-CONFIRMED 2026-07-03: a completed deletion emailed 'removed your identifying information from your suppression settings and you will need to re-enter that information' -- the suppression was wiped and the subject re-listed cluster-wide. If a 'deletion request is Complete' email appears, treat the suppression as gone: re-run suppression and re-verify the Control step reads 'suppressed'."
|
||||
},
|
||||
"playbook": [
|
||||
"PeopleConnect portal (suppression.peopleconnect.us/login, privacy-center entry at /privacy-center) -- ONE flow here covers Truthfinder, Instant Checkmate, US Search, ZabaSearch, Classmates and ~15 more. DO THIS PARENT FIRST.",
|
||||
"Step 1 asks ONLY for an email + consent checkbox (no name/DOB, no CAPTCHA) -> sends a verification email. Least-disclosure entry: just the contact email.",
|
||||
"poll-verification will pick up the verify link. The link is a JWT (aud PeopleConnect-email-login then -registration), carries a deviceId, has a ~15-min TTL, and is Cloudflare-gated; it authenticates a SESSION bound to the browser that OPENS it. The SAME agent browser that submitted step 1 must open the link and drive guided-mode straight through. Do NOT hard-navigate to /guided-mode after auth -- that drops the in-memory session and bounces to /login. If the session is lost, re-request a fresh verify email and follow it through without navigating away.",
|
||||
"guided-mode is a 5-STEP IDENTITY GATE, not a one-click suppress: (1) enter contact email + consent -> verify email; (2) open the verify link in the SAME browser (session/device-bound); (3) enter identity details -- this HARD-REQUIRES date of birth (immutable once saved, no skip) plus legal name; (4) Matching Records -- select the record that describes you, corroborating by address/email/phone, NOT name+DOB alone (namesakes exist); the matched record often aggregates MORE identifiers than the public listing showed (extra emails/addresses) -- expected, not alarming; (5) complete the SUPPRESSION action. So this opt-out discloses DOB + legal name + alias beyond the contact email -- collect DOB at intake (requires.dob=true) or expect a mid-flow pause.",
|
||||
"SUPPRESS, do NOT delete (this cluster is the exception to 'deletion beats suppression'). In guided-mode, complete the SUPPRESSION flow -- it puts you on the do-not-display list, which is what actually removes you from Intelius/TruthFinder/etc. Their privacy-center states: deleting your user data 'must delete any and all suppressions associated with your user', and 'Deleting your user information will NOT prevent other users from searching for your information through the people search websites. To suppress your information ... you must maintain your user information on file with the Suppression Center.'",
|
||||
"Therefore do NOT press 'Right to Delete / DELETE MY USER DATA' if the goal is search-visibility removal: it wipes your suppression and the public-records listing re-appears. Use the delete button ONLY if the operator's explicit goal is purging held account data (accept re-listing + re-suppression).",
|
||||
"Keep the account/suppression on file; do not delete it later. If the portal breaks: sister addresses privacy@intelius.com / privacy@truthfinder.com / privacy@instantcheckmate.com / support@ussearch.com / privacy@classmates.com; phone 1-888-245-1655.",
|
||||
"VERIFY SUPPRESSED (mandatory): after completing suppression -- and ALWAYS before marking this cluster confirmed_removed -- re-open guided-mode and confirm the Control step reads 'configured as suppressed across our people search websites'. The session persists across visits and pre-fills DOB / names / the matched record, so re-affirming is fast.",
|
||||
"DELETE-WIPED-SUPPRESSION MONITOR (field-confirmed 2026-07-03): if a 'Your deletion request for PeopleConnect.us is Complete' email (from privacy@verifications.peopleconnect.us) ever appears, the suppression is GONE -- its own wording says the deletion 'removed your identifying information from your suppression settings and you will need to re-enter that information', and it does NOT stop the affiliate people-search sites from re-listing. This is the delete-vs-suppress inversion happening live. Immediately re-run the SUPPRESSION flow and re-verify the Control step. Never leave this cluster on a completed deletion.",
|
||||
"After suppression confirms, re-scan the covered children (they normally drop out) before submitting any duplicate child opt-out."
|
||||
],
|
||||
"notes": "PeopleConnect portal covers the cluster via SUPPRESSION (maintained), not deletion (see the deletion lane note: delete removes suppressions and does not stop public-records re-listing). Authorized-agent requests: signed written authorization (full name, address, phone, the email the consumer uses) or POA; for Right-to-Delete they verify agent authority with the consumer by email. Verified from the live privacy policy + suppression privacy-center 2026-07-02.",
|
||||
"quirks": [
|
||||
"Step 1 (suppression.peopleconnect.us/login) asks ONLY for an email + a consent checkbox, then 'Continue' -> a verification email with a link. No CAPTCHA, no name/DOB at step 1. Least-disclosure entry: just the contact email. Verified live 2026-06-30.",
|
||||
"The verification link authenticates a SESSION and lands on /guided-mode. That session is bound to the browser that OPENED it; a different browser hitting /guided-mode is redirected back to /login. So for hands-off automation the SAME agent browser must open the verify link (Mode B: read inbox -> agent browser navigates the link -> drive guided-mode). Link is a JWT (aud PeopleConnect-email-login -> -registration) carrying a deviceId, ~15-min TTL, Cloudflare-gated. Do NOT hard-navigate to /guided-mode after auth (drops the in-memory session -> /login); if lost, re-request a fresh verify email and follow it straight through.",
|
||||
"DOB GATE: guided-mode hard-requires date of birth (immutable once saved, no skip) to match records, so requires.dob=true. DOB is not collected at intake by default (sensitive, unneeded for scanning). If absent, the planner pre-warns (needs_operator_input) that this broker needs a human touchpoint; collect it with `intake --dob` up front to run hands-off. The matching step discloses DOB + legal name + alias beyond the contact email -- corroborate the record by address/email/phone, never name+DOB alone.",
|
||||
"INVERTED delete/suppress: SUPPRESSION is the do-not-display list and is what removes you from the people-search sites; it requires keeping your identifiers on file. 'DELETE MY USER DATA' deletes those suppressions and does NOT stop the sites showing you (public records re-list). Verbatim from the privacy-center: deleting user data 'must delete any and all suppressions associated with your user'; and 'Deleting your user information will NOT prevent other users from searching for your information ... To suppress your information ... you must maintain your user information on file with the Suppression Center.' So prefer suppression; use delete only for a deliberate data-purge. Verified live 2026-07-02.",
|
||||
"Their published request metrics (2025): 33,513 deletion requests, median response < 1 day -- deletion is fast, but per above it is the wrong lever for search-visibility on this cluster.",
|
||||
"DOB field in guided-mode is an HTML <input type=date> -- enter it as ISO YYYY-MM-DD (not MM/DD/YYYY). The guided-mode session persists across visits and pre-fills the DOB / names / matched record, so re-verifying suppression later is quick.",
|
||||
"addresses.com is a PeopleConnect/Intelius front-end (all report links -> tracking.intelius.com) and is in this record's `owns`, so the cluster suppression already covers it -- do NOT file a separate addresses.com opt-out."
|
||||
],
|
||||
"est_processing_days": 7,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": "2026-07-01",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"id": "mylife",
|
||||
"name": "MyLife",
|
||||
"category": "people_search",
|
||||
"priority": "crucial",
|
||||
"jurisdictions": ["US"],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.mylife.com",
|
||||
"fetch": "browser",
|
||||
"match_signal": "profile",
|
||||
"by": ["name"]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T3",
|
||||
"method": "phone",
|
||||
"url": "https://www.mylife.com/privacyrequest",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": false,
|
||||
"captcha": false,
|
||||
"gov_id": true,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"phone_voice": true,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": ["full_name", "profile_url"],
|
||||
"notes": "Often pushes a driver's-license upload or a call to (888) 704-1900. Emailing privacy@mylife.com with name + profile link is an alternative. Also covers Wink.com.",
|
||||
"est_processing_days": 14,
|
||||
"reappearance_risk": "high"
|
||||
},
|
||||
"last_verified": "2026-06-28",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"id": "nuwber",
|
||||
"name": "Nuwber",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"parent": "nuwber",
|
||||
"owns": [],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://nuwber.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"antibot": "cloudflare",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://nuwber.com/removal/link",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"contact_email",
|
||||
"profile_url"
|
||||
],
|
||||
"notes": "People-search. Opt-out: submit the profile URL + email at /removal/link, confirm via the emailed link.",
|
||||
"quirks": [
|
||||
"Opt-out URL is the documented public endpoint; datacenter IPs get 403 (anti-bot), so confirm the live flow via the operator's residential browser before the first submission, then set last_verified.",
|
||||
"Needs the confirmed profile_url (paste the listing URL you recorded).",
|
||||
"Email verification required."
|
||||
],
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": null,
|
||||
"source": "curated",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"id": "peekyou",
|
||||
"name": "PeekYou",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"parent": "peekyou",
|
||||
"owns": [],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.peekyou.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"antibot": "cloudflare",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://www.peekyou.com/about/contact/optout",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"full_name",
|
||||
"contact_email",
|
||||
"profile_url"
|
||||
],
|
||||
"notes": "Aggregates social/web profiles. Opt-out: paste your PeekYou profile URL(s), pick a reason, provide email, confirm the link.",
|
||||
"quirks": [
|
||||
"Opt-out URL is the documented public endpoint; datacenter IPs get 403 (anti-bot), so confirm the live flow via the operator's residential browser before the first submission, then set last_verified.",
|
||||
"Needs the confirmed PeekYou profile_url.",
|
||||
"Email verification required."
|
||||
],
|
||||
"est_processing_days": 7,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": null,
|
||||
"source": "curated",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"id": "peoplefinders",
|
||||
"name": "PeopleFinders",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"parent": "peoplefinders",
|
||||
"owns": [],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.peoplefinders.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"antibot": "cloudflare",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://www.peoplefinders.com/opt-out",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"full_name",
|
||||
"contact_email",
|
||||
"profile_url"
|
||||
],
|
||||
"notes": "Standalone people-search (Confi-Chek family). Opt-out: find the listing, submit with a contact email, confirm via the emailed link.",
|
||||
"quirks": [
|
||||
"Opt-out URL is the documented public endpoint; datacenter IPs get 403 (anti-bot), so confirm the live flow via the operator's residential browser before the first submission, then set last_verified.",
|
||||
"Needs the confirmed profile_url from evidence.",
|
||||
"Email verification: poll-verification picks up the link; open it in the agent browser."
|
||||
],
|
||||
"est_processing_days": 7,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": null,
|
||||
"source": "curated",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"id": "radaris",
|
||||
"name": "Radaris",
|
||||
"category": "people_search",
|
||||
"priority": "crucial",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://radaris.com/",
|
||||
"fetch": "web_extract",
|
||||
"match_signal": "View Profile",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
],
|
||||
"url_patterns": {
|
||||
"name": "https://radaris.com/p/{First}/{Last}/"
|
||||
},
|
||||
"url_format_quirks": [
|
||||
"Name profile page: /p/{First}/{Last}/ with First/Last Capitalized and a TRAILING slash, e.g. /p/Jane/Public/ . Readable via web_extract (no hard bot gate as of 2026-06-30).",
|
||||
"The page aggregates: a 'phone numbers & home addresses' table (the DIRECT hit for the subject), a relatives/namesakes carousel ('Review the potential relatives'), and resume/CV records. The subject's removable row is in the address table; the carousel entries are OTHER people - disambiguate by address/age before acting.",
|
||||
"Page is noisy with testimonials/reviews boilerplate; the signal blocks are 'phone numbers & home addresses N' and 'resumes & CV records N'."
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://radaris.com/control-privacy",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": true,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"profile_url",
|
||||
"contact_email"
|
||||
],
|
||||
"notes": "Multi-step control-privacy wizard: step 1 NEXT -> step 2 'identify your personal page' (paste the NUMBERED profile URL into the 'Or Enter URL of your page' field; typing reveals a NEXT submit button) -> then user_email + Google reCAPTCHA -> emailed verification link. If there is no View Profile button for the subject, email customer-service@radaris.com and reply to the auto-response until removed.",
|
||||
"email": "customer-service@radaris.com",
|
||||
"quirks": [
|
||||
"CAPTCHA: the form carries a Google reCAPTCHA (hidden field g-recaptcha-response) plus anti-bot fingerprint tokens (jfp, token). Tier is T2 without a captcha-clearing browser backend (T1 with Browserbase). (Record previously mis-declared captcha:false.)",
|
||||
"The /control-privacy form REQUIRES the per-person NUMBERED profile URL. Pasting the aggregate /p/{First}/{Last}/ URL is rejected with the validation error: 'The URL must include unique number at the end'. The real removable URL looks like https://{region}.radaris.com/person/~First-Last/1234567890 (see the field placeholder).",
|
||||
"The subject's own record may appear ONLY as a static row in the 'phone numbers & home addresses' table with NO 'View Profile' link, so no numbered profile URL is exposed for them (the /p/{First}/{Last}/ page deep-links only to relatives/namesakes via JS onclick, not static hrefs). When that happens the /control-privacy form cannot be used -- do NOT fabricate or submit a relative's or namesake's profile URL. Fall back to email: write customer-service@radaris.com with the subject's own listed details and request removal, replying to the auto-response until confirmed.",
|
||||
"Pressing Enter in the URL field reloads the wizard to step 1 (does not submit); type into the field and click the revealed NEXT button instead."
|
||||
],
|
||||
"est_processing_days": 14,
|
||||
"reappearance_risk": "high"
|
||||
},
|
||||
"last_verified": "2026-06-30",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"id": "rehold",
|
||||
"name": "Rehold",
|
||||
"category": "property_records",
|
||||
"priority": "long_tail",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://rehold.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"match_signal_notes": "PROPERTY-RECORD, NOT PII. An address match here shows only PUBLIC PROPERTY RECORDS (build year, beds/baths, last sale price, incident history). Resident/owner NAMES sit behind 'View full report', which leads to a paywall/signup, so no personal PII is publicly exposed. Public property records are NOT removable. Record `found` ONLY if a resident NAME matching the subject is publicly displayed on the free page; an address-only match is `not_found` (nothing to opt out of).",
|
||||
"access": "paywall",
|
||||
"by": [
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://rehold.com/optout",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": false,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"profile_url"
|
||||
],
|
||||
"notes": "Address-anchored property/reverse-address site. Only pursue an opt-out if the scan found a publicly displayed resident NAME for the subject (see match_signal_notes); a bare public property record is not personal PII and is not removable. If the subject's personal profile IS shown, submit the profile URL to the opt-out endpoint and confirm the live flow in a residential browser before the first submission, then set last_verified.",
|
||||
"quirks": [
|
||||
"Distinguish 'address exists in a public property DB' (non-removable) from 'the subject's personal profile is displayed' (removable). Only the latter is an actionable exposure.",
|
||||
"'View full report' is a paywall/signup, not proof of a public listing.",
|
||||
"Opt-out endpoint UNVERIFIED: confirm the live flow before the first submission."
|
||||
],
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "low"
|
||||
},
|
||||
"last_verified": null,
|
||||
"source": "curated",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"id": "searchpeoplefree",
|
||||
"name": "SearchPeopleFree",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"parent": "searchpeoplefree",
|
||||
"owns": [],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.searchpeoplefree.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"antibot": "cloudflare",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://www.searchpeoplefree.com/opt-out",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"full_name",
|
||||
"contact_email",
|
||||
"profile_url"
|
||||
],
|
||||
"notes": "Free people-search. Opt-out: find the listing, submit with an email, confirm the link.",
|
||||
"quirks": [
|
||||
"Opt-out URL is the documented public endpoint; datacenter IPs get 403 (anti-bot), so confirm the live flow via the operator's residential browser before the first submission, then set last_verified.",
|
||||
"Needs the confirmed profile_url.",
|
||||
"Email verification required."
|
||||
],
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": null,
|
||||
"source": "curated",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"id": "socialcatfish",
|
||||
"name": "Social Catfish",
|
||||
"category": "people_search",
|
||||
"priority": "standard",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://socialcatfish.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"by": [
|
||||
"name",
|
||||
"email",
|
||||
"phone",
|
||||
"image"
|
||||
],
|
||||
"url_format_quirks": [
|
||||
"Reverse-lookup site (name / email / phone / image / username). Subject exposure is usually an INDIRECT one (an email/phone data point), not a full profile -- verify what is actually shown before choosing a lane."
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://socialcatfish.com/opt-out/",
|
||||
"requires": {
|
||||
"profile_url": false,
|
||||
"email_verification": true,
|
||||
"captcha": true,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"full_name",
|
||||
"contact_email"
|
||||
],
|
||||
"notes": "Automation-HOSTILE opt-out form: in the field the form filled correctly but the submission was automation-defeated, so it lands as a 2-click human task rather than a hands-off submit. Decision order per the blocked-form rule (methods.md): try the in-browser form on the operator's residential browser first; if it will not go through, fall back to the rights-request EMAIL address cited on the Social Catfish privacy policy / opt-out page (confirm the current address before sending -- do NOT use an address sourced from a third-party blog), disclosing name + contact email only. If neither is possible, queue a human_task with the exact end-state.",
|
||||
"quirks": [
|
||||
"Form defeats automation even when fields are filled correctly -> treat as a 2-click human task or use the cited rights-email fallback.",
|
||||
"Confirm the cited rights-request email on the live privacy policy before using it; it is the fallback lane, not the primary."
|
||||
],
|
||||
"est_processing_days": 7,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": "2026-07-03",
|
||||
"source": "field_verified",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"id": "spokeo",
|
||||
"name": "Spokeo",
|
||||
"category": "people_search",
|
||||
"priority": "crucial",
|
||||
"jurisdictions": ["US"],
|
||||
"parent": "spokeo",
|
||||
"owns": ["freepeopledirectory"],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.spokeo.com/search",
|
||||
"fetch": "browser",
|
||||
"match_signal": "profile",
|
||||
"by": ["name", "phone", "email", "address"]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T1",
|
||||
"method": "web_form",
|
||||
"url": "https://www.spokeo.com/optout",
|
||||
"email": "privacy@spokeo.com",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": ["profile_url", "contact_email"],
|
||||
"deletion": {
|
||||
"via": "email_followup",
|
||||
"email": "privacy@spokeo.com",
|
||||
"kinds": ["ccpa", "generic"],
|
||||
"notes": "privacy@spokeo.com is the documented direct privacy contact (verified live on /optout 2026-07-01). Use for full CCPA deletion beyond listing opt-out, for listings the form rejects, and when more listings keep surfacing."
|
||||
},
|
||||
"playbook": [
|
||||
"Opt-out form at spokeo.com/optout -- clears FreePeopleDirectory. Inputs: the confirmed profile URL + contact email; the form emails a confirmation link (poll-verification picks it up; open it in the agent's own browser).",
|
||||
"EVERY LISTING SEPARATELY: 'you may have multiple listings on Spokeo. Each one is identified by a unique URL and must be opted out individually' (their own wording). Run ALL search vectors first, collect every listing URL, and submit one opt-out per URL.",
|
||||
"Fast: requests process in 24-48 hours per their page -- re-scan after 2 days and record the real outcome.",
|
||||
"FULL DELETION follow-up: send-email --kind ccpa (CA) / generic to privacy@spokeo.com naming all listing URLs -- covers data retained beyond the free-search suppression.",
|
||||
"Paid/account data may be retained even when hidden from free search -- verify actual removal via re-scan; never mark confirmed_removed off the free-search view alone."
|
||||
],
|
||||
"notes": "Form + privacy@spokeo.com verified live 2026-07-01. Their page: opting out does not remove data from original sources and listings may reappear as new public records arrive -- keep the reappearance re-scan scheduled.",
|
||||
"quirks": [
|
||||
"Profile URL formats the form accepts: listing URL like spokeo.com/{First}-{Last}/{City}/{ST}/p{id} or a purchase URL spokeo.com/purchase?q=... (examples shown on /optout).",
|
||||
"Multiple listings per person are NORMAL (one per name x location x record cluster); each unique URL must be opted out individually -- feed every found listing URL through the form.",
|
||||
"Processing is 24-48h ('depending on the nature of your request and the amount of data').",
|
||||
"Paid accounts may retain data even when hidden from free search - verify actual removal, don't mark confirmed_removed off the free-search view alone."
|
||||
],
|
||||
"est_processing_days": 2,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": "2026-07-01",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"id": "thatsthem",
|
||||
"name": "That's Them",
|
||||
"category": "people_search",
|
||||
"priority": "crucial",
|
||||
"jurisdictions": ["US"],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://thatsthem.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"by": ["name", "phone", "email", "address"],
|
||||
"url_patterns": {
|
||||
"name": "https://thatsthem.com/name/{First}-{Last}/{City}-{ST}",
|
||||
"phone": "https://thatsthem.com/phone/{areacode}-{prefix}-{line}",
|
||||
"email": "https://thatsthem.com/email/{email}",
|
||||
"address": "https://thatsthem.com/address/{Street}-{City}-{ST}-{ZIP}"
|
||||
},
|
||||
"url_format_quirks": [
|
||||
"ADDRESS path is fully hyphen-joined and joins street+city+state+ZIP with hyphens (e.g. /address/123-Main-St-Anytown-NY-12345) and REQUIRES the ZIP. The older slash form (/address/Street/City-ST) and any ZIP-less form 404.",
|
||||
"NAME and PHONE and EMAIL paths use a slash before city/state and do NOT need a ZIP: /name/First-Last/City-ST , /phone/AAA-PPP-LLLL , /email/addr@host.",
|
||||
"Street abbreviations are kept verbatim (Ave, Pl, St) - do NOT expand to Avenue/Place/Street; expanding 404s.",
|
||||
"A 404 on a constructed URL means WRONG PATTERN, not 'no record present'. Treat as INCONCLUSIVE: fall back to the on-site search box (browser_type into the address/name field + submit) and read the resulting canonical URL."
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://thatsthem.com/optout",
|
||||
"requires": {
|
||||
"profile_url": false,
|
||||
"email_verification": false,
|
||||
"captcha": true,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": ["full_name", "street", "city", "state", "postal", "contact_email", "phone"],
|
||||
"notes": "Opt-out form is gated by a Cloudflare Turnstile CAPTCHA (so tier is T2 without a captcha-clearing browser backend; T1 with Browserbase). All 7 fields are marked required by the form (Full Name, Street Address, City, State, ZIP, Email, Phone). Site sends a confirmation email and states ~72h processing (this is a completion notice, not a click-to-verify link). Least-disclosure tension: the form DEMANDS email+phone even though a public record may show less - disclose only to remove a record that is actually about the subject. Do not click the Spokeo identity-theft-protection link (paid product).",
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "low"
|
||||
},
|
||||
"last_verified": "2026-06-30",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"id": "truepeoplesearch",
|
||||
"name": "TruePeopleSearch",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": ["US"],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.truepeoplesearch.com/",
|
||||
"fetch": "browser",
|
||||
"antibot": "datadome",
|
||||
"match_signal": "result",
|
||||
"match_signal_notes": "SEO TRAP: the page title/H1/intro auto-inserts the query ('FREE public records found for {Name} in {City}') even with ZERO real matches. That templated echo is NOT a result. Record `found` ONLY on an actual result CARD corroborated by the subject's address or DOB; unrelated same-name cards in other states are namesakes. Ignore the title/intro/H1 text entirely.",
|
||||
"by": ["name", "phone", "address", "email"],
|
||||
"url_patterns": {
|
||||
"name": "https://www.truepeoplesearch.com/results?name={First%20Last}&citystatezip={City,%20ST}"
|
||||
},
|
||||
"url_format_quirks": [
|
||||
"Search results URL is QUERY-PARAM, not path: /results?name=Jane%20Public&citystatezip=Anytown,%20NY (space-encoded; comma between city and state). Confirmed as the canonical form the site's own search box generates.",
|
||||
"On-site search tabs: Name / Phone / Address / Email / Neighbors (so name-, phone-, address-, and email-searchable).",
|
||||
"HARD-BLOCKED for automated reads (2026-06-30): Cloudflare 'Just a moment...' interstitial -> DataDome device-check CAPTCHA (geo.captcha-delivery.com) on every results navigation. Page chrome (header/footer) may render while the result body stays blocked; submitting any search bounces to DataDome. web_extract/Firecrawl 504-timed out. Needs a residential-proxy/stealth browser (e.g. Browserbase) to scan; otherwise record 'blocked'."
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://www.truepeoplesearch.com/removal",
|
||||
"requires": {
|
||||
"profile_url": false,
|
||||
"email_verification": true,
|
||||
"captcha": true,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": ["full_name", "contact_email"],
|
||||
"notes": "Removal page renders even when results are blocked. Flow: name+email+captcha -> emailed link -> fill opt-out form matching the record -> confirmation ('allow 3 days'). Fields: dropdown 'Exercise my rights as a: The subject of the request / An authorized agent of the subject', First Name*, Middle Name, Last Name*, Email Address*, consent checkbox. CAPTCHA-gated: hCaptcha ('I am human'). Contact support@truepeoplesearch.com; PO Box 7775 PMB 29296, San Francisco CA 94120-7775. Verified read-only 2026-06-30; not submitted. (Record previously mis-declared email_verification:false.)",
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "high"
|
||||
},
|
||||
"last_verified": "2026-06-30",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"id": "usphonebook",
|
||||
"name": "USPhoneBook",
|
||||
"category": "people_search",
|
||||
"priority": "high",
|
||||
"jurisdictions": [
|
||||
"US"
|
||||
],
|
||||
"parent": "usphonebook",
|
||||
"owns": [],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.usphonebook.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "result",
|
||||
"antibot": "cloudflare",
|
||||
"by": [
|
||||
"name",
|
||||
"phone",
|
||||
"address"
|
||||
]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T2",
|
||||
"method": "web_form",
|
||||
"url": "https://www.usphonebook.com/opt-out",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": [
|
||||
"full_name",
|
||||
"contact_email",
|
||||
"profile_url"
|
||||
],
|
||||
"notes": "Reverse-phone + people-search. Opt-out: paste the listing URL, provide an email, confirm via the emailed link.",
|
||||
"quirks": [
|
||||
"Opt-out URL is the documented public endpoint; datacenter IPs get 403 (anti-bot), so confirm the live flow via the operator's residential browser before the first submission, then set last_verified.",
|
||||
"Needs the confirmed profile_url.",
|
||||
"Email verification required."
|
||||
],
|
||||
"est_processing_days": 3,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": null,
|
||||
"source": "curated",
|
||||
"confidence": "documented"
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"id": "whitepages",
|
||||
"name": "Whitepages",
|
||||
"category": "people_search",
|
||||
"priority": "crucial",
|
||||
"jurisdictions": ["US"],
|
||||
"parent": "whitepages",
|
||||
"owns": ["411"],
|
||||
"search": {
|
||||
"method": "url_pattern",
|
||||
"url": "https://www.whitepages.com/",
|
||||
"fetch": "browser",
|
||||
"match_signal": "listing",
|
||||
"by": ["name", "phone", "address"]
|
||||
},
|
||||
"optout": {
|
||||
"tier": "T1",
|
||||
"method": "email",
|
||||
"url": "https://www.whitepages.com/suppression_requests",
|
||||
"email": "privacyrequest@whitepages.com",
|
||||
"requires": {
|
||||
"profile_url": true,
|
||||
"email_verification": true,
|
||||
"captcha": false,
|
||||
"gov_id": false,
|
||||
"account": false,
|
||||
"phone_callback": false,
|
||||
"payment": false
|
||||
},
|
||||
"inputs": ["full_name", "contact_email", "profile_url"],
|
||||
"deletion": {
|
||||
"via": "email",
|
||||
"email": "privacyrequest@whitepages.com",
|
||||
"url": "https://whitepagesprivacy.zendesk.com/hc/en-us/requests/new",
|
||||
"kinds": ["ccpa", "generic"],
|
||||
"notes": "privacyrequest@whitepages.com handles BOTH opt-out (removal from the site) and CCPA deletion requests, explicitly offered for people who do not want to provide a phone number for the automated tool. ~2 business day reply; opt-outs processed within 15 days. Verified from whitepages.com/privacy/consumer-rights 2026-07-01 (page dated 2026-06-22)."
|
||||
},
|
||||
"playbook": [
|
||||
"EMAIL LANE (fully autonomous -- use this): send the removal + deletion request to privacyrequest@whitepages.com including the confirmed listing URL. This is Whitepages' own documented alternative 'if you would prefer not to provide a phone number'. Expect a reply within ~2 business days; they may ask identity-verification questions (name, email) -- answer with least-disclosure, never an ID number.",
|
||||
"Include in the email: the listing URL(s), the subject's full name as listed, and the request to (a) remove the listing(s), (b) opt out of sale/sharing, and (c) delete personal data (CCPA 1798.105 for CA residents; they honor requests from other states per their consumer-rights page).",
|
||||
"'Once a listing is removed, all known connected listings are also removed and the requester's information will not be sold by Whitepages in any capacity' -- one request covers connected listings; still re-scan afterward, and check Whitepages Premium + 411.com separately.",
|
||||
"Alternative 1: webform at whitepagesprivacy.zendesk.com/hc/en-us/requests/new (same ~2-day handling; good fallback if the mailbox bounces).",
|
||||
"Alternative 2 (only with an operator on the phone): the automated tool at whitepages.com/suppression_requests -- paste the listing URL, provide a phone number, answer the automated voice call and enter the 4-digit code. Fastest (est 1 day) but NOT autonomous.",
|
||||
"Opt-out requests may take up to 15 days; verify with a re-scan before recording confirmed_removed."
|
||||
],
|
||||
"notes": "Email/webform lane verified 2026-07-01: privacyrequest@whitepages.com or the Zendesk form replace the phone-callback tool ('if you would prefer not to provide a phone number... submit a request to a customer service agent'). Authorized agents: written signed permission required. General privacy contact: support@whitepages.com.",
|
||||
"quirks": [
|
||||
"The automated suppression tool (whitepages.com/suppression_requests) REQUIRES a phone number + automated voice call with a 4-digit code + agreeing to their ToS -- that lane is phone_callback/T2. The email/webform lane exists precisely to avoid it; prefer email for autonomy.",
|
||||
"Deletion exceptions they state: public records (property, court), fraud-prevention data, active-subscription data, legal holds. 'Hidden from search' vs 'deleted' distinction applies -- their opt-out removes the listing; the CCPA deletion covers non-public account data.",
|
||||
"CCPA opt-out requests: up to 15 days to process. Right-to-know/access requests also via privacyrequest@whitepages.com or the Zendesk form."
|
||||
],
|
||||
"est_processing_days": 15,
|
||||
"reappearance_risk": "medium"
|
||||
},
|
||||
"last_verified": "2026-07-01",
|
||||
"source": "BADBOOL"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# CCPA / CPRA (California)
|
||||
|
||||
Use for California residents (`residency_jurisdiction` starts with `US-CA`) and, in practice, many US
|
||||
brokers that honor CCPA-style requests nationwide.
|
||||
|
||||
## Rights invoked
|
||||
|
||||
- **Delete** personal information (Cal. Civ. Code 1798.105).
|
||||
- **Opt out** of sale/sharing of personal information (1798.120).
|
||||
|
||||
## Request content
|
||||
|
||||
Render with `legal.render_request("ccpa", broker, fields)` -> `templates/emails/ccpa-deletion.txt`.
|
||||
Include only: full legal name, the contact email for correspondence, and the confirmed listing
|
||||
URL(s). Do **not** include SSN or government IDs.
|
||||
|
||||
## Authorized agent
|
||||
|
||||
When acting for another consenting subject, use `render_request("ccpa_agent", ...)`
|
||||
(`templates/emails/ccpa-authorized-agent.txt`) and attach the authorization artifact recorded in the
|
||||
dossier (`consent.authorization_artifact`). The broker may separately verify the consumer's identity.
|
||||
|
||||
## Notes
|
||||
|
||||
- Brokers must respond within 45 days (extendable). Track as `awaiting_processing` until confirmed.
|
||||
- "Hidden from free search" is not deletion - verify the record is actually gone before
|
||||
`confirmed_removed`.
|
||||
@@ -0,0 +1,34 @@
|
||||
# California DROP portal (highest-leverage lever)
|
||||
|
||||
The California **Delete Request and Opt-out Platform** (`privacy.ca.gov/drop`) lets a California
|
||||
resident demand deletion from **every registered data broker** with a single verified request, for
|
||||
free. DROP is **live** (as of 2026); registered brokers must begin processing requests on
|
||||
**2026-08-01**. The registered universe is the **California Data Broker Registry** (~545 brokers in
|
||||
2025), which this skill ingests as its own coverage lane (`pdd.py registry`); one DROP request covers
|
||||
all of them, which is how this skill reaches (and exceeds) the breadth of commercial services.
|
||||
|
||||
## When to use
|
||||
|
||||
For any subject with `residency_jurisdiction` starting `US-CA`, sequence DROP **first**: `pdd.py next`
|
||||
surfaces a single `drop_submit` action covering the whole registry. Then handle the individual
|
||||
people-search sites (which are also worked directly because they hold free, indexed listings). After
|
||||
filing, run `pdd.py drop <subject> --filed` so the loop stops re-surfacing it. For non-CA subjects
|
||||
DROP does not apply; cover the registry brokers with targeted CCPA/GDPR deletion emails
|
||||
(`pdd.py registry --search`, then `pdd.py send-email`).
|
||||
|
||||
## Flow (agent-assisted, mostly human verification)
|
||||
|
||||
1. The operator creates/verifies a DROP account (identity verification is required by the state; this
|
||||
is a human step - `human_task_queued`).
|
||||
2. Submit one deletion request covering all registered brokers.
|
||||
3. Record a single ledger case `case_<subject>_drop` to track it; mark `submitted` ->
|
||||
`awaiting_processing`. Registered brokers must process deletions on the state's schedule.
|
||||
4. After the DROP cycle, re-scan the people-search long tail and only act on sites still showing data.
|
||||
|
||||
## Caveats
|
||||
|
||||
- DROP covers **registered data brokers**, not every people-search site. Keep doing the individual
|
||||
opt-outs for non-registered sites.
|
||||
- Identity verification means parts of this cannot (and should not) be fully automated.
|
||||
- FCRA-regulated brokers (flagged in the registry, `optout.fcra`) hold consumer-report data with
|
||||
separate rules; deletion may be limited and a dispute or security-freeze may apply instead.
|
||||
@@ -0,0 +1,20 @@
|
||||
# GDPR / UK-GDPR (roadmap - Phase 3)
|
||||
|
||||
For EU/UK subjects. Not part of the P0 US-first scope; templates and routing land in Phase 3.
|
||||
|
||||
## Rights invoked
|
||||
|
||||
- **Erasure** ("right to be forgotten") - Article 17.
|
||||
- **Object** to processing - Article 21.
|
||||
|
||||
## Request content
|
||||
|
||||
Render with `legal.render_request("gdpr", broker, fields)` ->
|
||||
`templates/emails/gdpr-erasure.txt`. Address the controller's privacy/DPO contact. Include the data
|
||||
subject's name, the contact email, and the listing URL(s); cite Article 17.
|
||||
|
||||
## Notes
|
||||
|
||||
- Controllers must respond within one month (Article 12(3)).
|
||||
- EU-specific brokers and portals (e.g. Acxiom's EU consumer portals) are added in Phase 3 with
|
||||
`jurisdictions: ["EU"]` records and residency-aware routing.
|
||||
@@ -0,0 +1,361 @@
|
||||
# Opt-out method playbooks
|
||||
|
||||
How the agent executes each broker `optout.method` using native Hermes tools. Obey **least-disclosure**:
|
||||
submit only the subject's OWN identifiers, and only the fields a broker's official channel requires
|
||||
(`pdd.py plan` lists them per broker). Never disclose more than that, and confirm a listing is really
|
||||
the subject's before acting on any THIRD-PARTY / indirect record (see "Distinguish the subject" and
|
||||
"Indirect exposure"). See the posture section below for when a confirmed listing is NOT a prerequisite.
|
||||
|
||||
**Autonomy:** `pdd.py next <subject>` sequences all of this - it decides which method applies, orders
|
||||
parents first, and routes human-only work to the digest. In `autonomy=full` (default), execute its
|
||||
actions without pausing per submission; the consent recorded at intake is the authorization. These
|
||||
playbooks are the HOW for each action type.
|
||||
|
||||
## Opt-out posture: blind opt-out is the default (not a fallback)
|
||||
|
||||
Operator-directed posture: **submit an opt-out or deletion on EVERY site that exposes an accessible
|
||||
removal channel, even when a listing was not first confirmed** - whichever of opt-out / deletion is
|
||||
optimal per site. Do not hand back a to-do list of "we could not search these."
|
||||
|
||||
- **Why it is sound (does NOT violate least-disclosure):** a blind opt-out sends only the subject's own
|
||||
identifiers to the broker's own official removal channel. You are giving the broker the subject's data
|
||||
*to remove it*, not exposing new data or acting on a third party. (Third-party / indirect records are
|
||||
the exception: those still require confirming the exposure first.)
|
||||
- **The opt-out flow doubles as the authoritative search.** Guided flows that match on email + DOB +
|
||||
legal name and then say "no results" are a **stronger `not_found` than any scrape** - the broker ran
|
||||
its own matcher against real identifiers. On guided-flow sites, "run the opt-out" and "search" are one
|
||||
action (e.g. CheckPeople; see `site-playbooks.md`).
|
||||
|
||||
### Blocked form -> default to the cited rights-email (the headline rule)
|
||||
|
||||
When a removal **form** is automation-hostile (hard CAPTCHA, a Cloudflare wall that will not clear, a JS
|
||||
paywall funnel), **default to the broker's cited rights-request email** rather than recording `blocked`
|
||||
and deferring to a human - unless there is an easy in-browser solve. Decision order per site:
|
||||
|
||||
1. **Easy in-browser solve?** (one-click remove; a guided flow whose CAPTCHA auto-clears on the
|
||||
residential browser; plain email-verify) -> do it in the browser.
|
||||
2. **Form blocked but a cited rights-email exists?** -> send a deletion/opt-out email from the operator's
|
||||
webmail (name + state + contact email only). This is now **preferred** over recording `blocked`.
|
||||
3. **No easy solve AND no cited email** -> `blocked` (or `human_task_queued` with the exact end-state).
|
||||
4. **Only lane requires gov-ID / physical mail** -> do NOT pursue autonomously (least-disclosure);
|
||||
surface as a human decision.
|
||||
|
||||
"Cited" = published by the broker itself (privacy policy / opt-out page / a working deletion alias). Do
|
||||
**not** email addresses sourced only from third-party blogs or Reddit. Per-site lanes and gotchas are
|
||||
pre-recorded in `references/site-playbooks.md` so future runs execute rather than re-derive.
|
||||
|
||||
### Triage an external OSINT list before scanning
|
||||
|
||||
When cross-checking any external "people OSINT" catalog, separate **first-party brokers** (removal
|
||||
targets) from **meta-search / link-out aggregators** (no first-party data -> no-ops, do not file
|
||||
opt-outs), **cluster front-ends** (covered by a parent, e.g. addresses.com -> Intelius), and
|
||||
**non-broker tools / APIs / wrong-jurisdiction** (skip). The skip-lists live in `site-playbooks.md`.
|
||||
|
||||
## Scan ladder (all methods)
|
||||
|
||||
Build the exposure map cheapest first (on a site with an accessible removal channel you may still
|
||||
blind-opt-out even if the scan is inconclusive - see the posture section above). Run **every**
|
||||
`search_vectors` entry from `pdd.py plan` (each name x location, phone, email, and address the broker's
|
||||
`search.by` supports) - different vectors surface different listings for the same person; dedupe found
|
||||
URLs.
|
||||
|
||||
1. `web_extract` on the broker `search.url` (fast HTML -> markdown). Look for `search.match_signal`.
|
||||
Build per-vector URLs from `search.url_patterns` and heed `search.url_format_quirks` (see below).
|
||||
1b. **`site:` search-engine probe (cheap, do it early and in parallel).** `web_search` with
|
||||
`site:<broker-domain> "First Last"` (add a city/ZIP or a unique phone/address to cut namesake
|
||||
noise) often returns the **exact profile-slug URL** in one shot - which both confirms the listing
|
||||
exists AND hands you the opaque `/find/person/<id>` or `/p/<slug>` URL you'd otherwise have to
|
||||
derive. Two big wins seen in the field: (a) it disambiguates namesakes fast - the SERP snippet
|
||||
shows age/city so you can tell the subject from a same-name relative before fetching anything; and
|
||||
(b) a broad `"First Last" <ZIP OR unique-address>` search (no `site:`) surfaces **brokers not yet in
|
||||
your DB** (e.g. information.com, peoplefinders.com) - record those as bonus exposures. Note: empty
|
||||
`site:` results are INCONCLUSIVE (many broker pages aren't indexed / are `noindex`), not `not_found`.
|
||||
2. If the page is JS-rendered or returns nothing useful, `browser_navigate` + `browser_snapshot`
|
||||
(and `browser_type`/`browser_click` to run the site's search box).
|
||||
3. If blocked by stealth/Cloudflare, use the `scrapling` skill via `terminal`. **If the broker record
|
||||
has `search.antibot` set (e.g. `datadome`), results are behind a device-check CAPTCHA**: a
|
||||
cloud/stealth browser (Browserbase) or `scrapling` may get through; if none is available, do **not**
|
||||
burn attempts - `pdd.py record <subject> <broker> blocked` and move on (a re-scan with a stealth
|
||||
backend can pick it up later).
|
||||
3b. **Operator-browser path (the reliable unblock for anti-bot sites).** Cloudflare/DataDome key on
|
||||
datacenter IPs + headless fingerprints, so `web_extract`, the proxyless agent browser, and even a
|
||||
cloud browser often fail - but the **operator's own everyday browser (residential IP, real
|
||||
fingerprint) sails straight through**. For any `blocked` site, hand the operator a paste-ready
|
||||
search URL (built from `search.url_patterns`), give them the identity anchors to judge by (current
|
||||
+ prior addresses, age, a distinguishing detail) and the namesake/relative watch-list, and ask for
|
||||
the verdict or a screenshot (the agent can read screenshots). This is a **first-class scan path, not
|
||||
a fallback** - treat the operator's live check as authoritative and record the real verdict
|
||||
(`found` / `not_found` / `indirect_exposure`), citing `scanned_via: operator_browser`. Same for
|
||||
opt-out forms the agent's browser can't reach: guide the operator field-by-field (least-disclosure),
|
||||
pausing before submit. (This is exactly why the same trick clears email-verification links the agent
|
||||
can't open - see the Verification loop.)
|
||||
4. Capture evidence: save listing URLs and a `browser` screenshot into the subject's `evidence/` dir,
|
||||
then `pdd.py record <subject> <broker> found --found true --evidence '{"listing_urls":[...]}'`.
|
||||
|
||||
If a listing genuinely does not exist: `pdd.py record <subject> <broker> not_found` and move on.
|
||||
|
||||
### A 404 (or empty body) is INCONCLUSIVE, not "not_found"
|
||||
|
||||
A constructed search URL that 404s almost always means the **URL pattern is wrong**, not that the
|
||||
person is absent. Never record `not_found` off a 404. Instead:
|
||||
1. Re-check the broker's `search.url_patterns` / `url_format_quirks` and rebuild the URL.
|
||||
2. Fall back to the **on-site search box**: `browser_navigate` to the search page, `browser_type`
|
||||
the raw query, `browser_click` Search, then read the **canonical result URL** the site lands on.
|
||||
3. Only after the site's own search returns an empty result set do you record `not_found`.
|
||||
4. If a pattern was wrong, fix it in `references/brokers/<id>.json` (`url_patterns` +
|
||||
`url_format_quirks`) so the next run is correct - see the rule below.
|
||||
|
||||
### Log URL/format quirks for every site you scrape
|
||||
|
||||
Whenever you discover how a broker's URLs are actually shaped (path layout, hyphen-vs-slash joins,
|
||||
whether ZIP is required, abbreviation handling, query-param search, anti-bot gating), record it in
|
||||
that broker's `references/brokers/<id>.json` under `search.url_patterns` (the templates) and
|
||||
`search.url_format_quirks` (the gotchas, including which forms 404). Bump `last_verified`. This makes
|
||||
the deterministic URL path reliable across runs and subjects instead of rediscovered each time. If the
|
||||
opt-out form's real requirements differ from the record (extra required fields, a CAPTCHA, an account),
|
||||
fix `optout.requires` / `optout.inputs` / `optout.tier` too - those drive tier selection and
|
||||
least-disclosure. Log opt-out mechanics gotchas (a broker that needs a profile URL but doesn't expose
|
||||
one for the subject, an email-only fallback, an authorized-agent toggle) in `optout.quirks` - the
|
||||
planner surfaces these as `optout_quirks` per broker. Example: Radaris sometimes shows the subject only
|
||||
as a static address-table row with no "View Profile" link, so `/control-privacy` (which needs a profile
|
||||
URL) can't be used - fall back to `optout.email` rather than submitting a namesake's URL.
|
||||
|
||||
### Distinguish the subject from namesakes and relatives
|
||||
|
||||
People-search sites are dense with namesakes and family clusters. Before recording `found`, confirm the
|
||||
record is the **subject themselves** (corroborate via DOB, a known current/prior address, or the
|
||||
identifier you searched). Two non-removable patterns to record as evidence but NOT as the subject's own
|
||||
listing:
|
||||
- **Namesake:** same name, different person (different DOB/location with no overlap). Not the subject.
|
||||
- **Relative record:** the listing is about a *different* person (a relative) and merely *names* the
|
||||
subject in a "Family" field, or carries the subject's email/phone as a secondary datum. This is a
|
||||
third party's record - the consent gate correctly blocks acting on it. See "Indirect exposure" in
|
||||
the web_form section for what the subject *can* still request.
|
||||
|
||||
Two more false-positive traps that a naive scan records as `found` when it should not:
|
||||
- **Property record != PII (address-anchored sites).** Reverse-address / property sites (rehold,
|
||||
clustrmaps-style) can match on a public **property record** (build year, beds/baths, last sale
|
||||
price, incidents) without exposing the subject's personal info - the resident/owner NAME is behind
|
||||
a "View full report" paywall/signup. Distinguish "this address exists in a public property DB"
|
||||
(non-removable, `not_found`) from "the subject's personal profile is displayed" (removable,
|
||||
`found`). Record `found` ONLY if a resident name matching the subject is publicly shown; an
|
||||
address-only match is `not_found` - there is nothing to opt out of, and public property records are
|
||||
not removable anyway. See `rehold.json` `search.match_signal_notes`.
|
||||
- **SEO-templated title/H1 fakes a "found".** Many people-search sites auto-insert the query into the
|
||||
page `<title>`, H1, and intro copy ("FREE public records found for {Name} in {City}", "Over 100+
|
||||
FREE public records found for {Name}"). That echo is **templating, not a result** - the actual
|
||||
result cards are often unrelated namesakes in other states. A `match_signal` on title/intro text
|
||||
yields false positives. Require a real result **card** corroborated by the subject's address or
|
||||
DOB, and ignore the templated title/intro/H1 entirely. See `truepeoplesearch.json` /
|
||||
`fastpeoplesearch.json` `search.match_signal_notes`.
|
||||
|
||||
Both are why the **parent re-verifies every `found` before acting** rule is load-bearing (`pdd.py show
|
||||
<subject> <broker>` reads back a subagent's recorded evidence so the parent can re-verify without
|
||||
re-deriving the listing URL). If a `found` turns out to be a false positive, correct it with a fresh
|
||||
`record ... not_found` carrying an evidence note explaining the retraction.
|
||||
|
||||
## web_form
|
||||
|
||||
1. `browser_navigate` to `optout.url`; `browser_snapshot` to read the form.
|
||||
2. Fill only the planned `disclosure_fields` with `browser_type`/`browser_click`; for `profile_url`,
|
||||
paste the confirmed listing URL from evidence.
|
||||
3. Submit; `browser_snapshot` to confirm the success state; screenshot to `evidence/`.
|
||||
4. `pdd.py record <subject> <broker> submitted --disclosed <field> --disclosed <field> --channel web_form`.
|
||||
5. If the broker requires email verification, follow **Verification loop** below.
|
||||
|
||||
### Indirect exposure (named as a relative / your email on someone else's record)
|
||||
|
||||
You asked the right question: if a broker lists a *relative* and names you in their "Family" field, or
|
||||
shows **your** email/phone on **their** record, that IS personal information about you - even though the
|
||||
record's primary subject is a third party. Resolve it in two distinct lanes:
|
||||
|
||||
- **The self-service opt-out form does NOT cover this.** That form removes a record whose *primary
|
||||
subject* is you. It has no notion of "scrub my identifiers from this other person's record," and
|
||||
submitting it with the relative's address to force a match would be (a) disclosing data the listing
|
||||
doesn't tie to you and (b) acting on a third party's record. Don't. The consent gate exists to stop
|
||||
exactly that.
|
||||
- **What you CAN do - a targeted "delete my personal information" request (CCPA 1798.105 / GDPR Art.17).**
|
||||
These rights attach to *your* personal information *wherever the business holds it*, including as a
|
||||
data point on another person's profile. So the subject may email the broker's privacy address and
|
||||
request suppression of **their own specific identifiers** (this email address, this phone number, my
|
||||
name in family/relative associations), citing the relative listings as the locations. This is a
|
||||
narrower request than a full opt-out and does not require the relative's consent - you are only asking
|
||||
them to delete data about *you*. Use `render-email` with the `ccpa`/`gdpr` template, list only the
|
||||
subject's own identifiers + the URLs where they appear, and record it as a normal `submitted` →
|
||||
`awaiting_processing` email case. Verify by re-scanning those identifier vectors (email/phone) after
|
||||
the statutory window - `confirmed_removed` only when the subject's identifier no longer appears.
|
||||
- **Caveat:** the broker may decline to alter a third party's record beyond removing your specific
|
||||
identifiers, and "your name in a family graph" can be derived from public records they'll re-list.
|
||||
Note residual exposure in the report rather than marking a clean removal. (Operational guidance, not
|
||||
legal advice.)
|
||||
|
||||
## email
|
||||
|
||||
`pdd.py send-email <subject> <broker> --listing <url> [--kind ccpa|gdpr|ccpa_indirect]` always does
|
||||
the deterministic parts (recipient locked to an address the broker record declares, refusing anything
|
||||
else; `--listing` mandatory; records `submitted`, logs disclosure, stamps `next_recheck_at`). How it
|
||||
actually sends depends on `email_mode`:
|
||||
|
||||
1. **browser mode (no password, autonomous):** the command returns a recipient-locked `compose`
|
||||
payload (`to`/`subject`/`body`). Compose a NEW message in the operator's **logged-in webmail** via
|
||||
`browser_*` (paste `compose.body` exactly, disclosing nothing beyond it) and send. No credentials
|
||||
stored. Requires the inbox signed in in the browser Hermes uses.
|
||||
2. **programmatic mode (SMTP creds):** the command SMTP-sends it directly, no human.
|
||||
3. **draft_only fallback:** `pdd.py render-email <subject> <broker> --listing <url>`; a digest entry
|
||||
tells the operator to send it, and the agent records `submitted --channel email` afterward.
|
||||
|
||||
Then follow the **Verification loop** if the broker emails a confirmation link.
|
||||
|
||||
## Verification loop (email_verification brokers)
|
||||
|
||||
- **browser mode (autonomous, no password):** open the broker's confirmation email in the operator's
|
||||
webmail (`browser_*`), then `pdd.py verify-link <subject> <broker> --text '<email body>'` returns
|
||||
the anti-phishing-scored link. `browser_navigate` it **in the same browser** (several brokers, e.g.
|
||||
PeopleConnect, bind the session to the browser that opens the link), finish the flow, record
|
||||
`awaiting_processing`.
|
||||
- **programmatic mode (IMAP):** `pdd.py poll-verification <subject>` polls IMAP for every in-flight
|
||||
case, extracts the link (anti-phishing scored: only opt-out-looking links on the broker's own
|
||||
domains), and auto-advances `submitted → verification_pending`. Then `browser_navigate` the link in
|
||||
the agent's own browser, finish the flow, record `awaiting_processing`.
|
||||
- **draft_only:** the digest tells the operator to click the link in the subject's inbox; the agent
|
||||
records `awaiting_processing` on their word.
|
||||
- Either way, the due queue (`pdd.py due`) brings the case back after the broker's processing window
|
||||
for the verifying re-scan; only that re-scan justifies `confirmed_removed`.
|
||||
|
||||
## phone_callback (e.g. Whitepages)
|
||||
|
||||
Submit the web form, then the site places an automated call with a numeric code. If the operator is
|
||||
available to read the code, capture it and complete the form (T2). Otherwise queue a human task.
|
||||
|
||||
## phone (voice menu) / fax / mail / gov_id -> human task (T3)
|
||||
|
||||
Do **not** attempt to automate. Create a `todo` task and `pdd.py record <subject> <broker>
|
||||
human_task_queued` with exact instructions and an explicit **withhold** list (never SSN; never a
|
||||
driver's-license number unless the subject chooses to and crosses out the ID number). Capture the
|
||||
confirmation reference back into the ledger when the operator completes it.
|
||||
|
||||
## captcha
|
||||
|
||||
**Default: soft/managed CAPTCHAs clear automatically.** The recommended baseline backend is the
|
||||
Browserbase cloud browser (`setup --auto` selects it when `BROWSERBASE_API_KEY` is set). Being a
|
||||
real browser on a residential IP, it passes managed challenges - Cloudflare Turnstile, hCaptcha /
|
||||
reCAPTCHA checkbox - as normal operation, so those brokers stay T1 and you just proceed. This is
|
||||
**not** CAPTCHA solving: no solver service, no fingerprint spoofing.
|
||||
|
||||
Only a **hard** challenge the browser genuinely can't pass (interactive image grids, behavioral
|
||||
scoring that flags the session) becomes a fallback: `record ... blocked` and requeue it for the
|
||||
stealth/operator-browser pass (`methods.md` → scan ladder 3b - the operator's own residential
|
||||
browser is the reliable unblock). Without a cloud browser configured, soft-CAPTCHA brokers drop to
|
||||
T2 and become human tasks. **Never use a third-party CAPTCHA-defeating service.**
|
||||
|
||||
### CAPTCHA policy, clarified (on a consenting first-party opt-out)
|
||||
|
||||
- **Do NOT defeat** behavioral / token challenges: a Cloudflare Turnstile that will not auto-clear,
|
||||
**DataDome**, and **"slide-to-verify" gesture-entropy sliders** (the InfoPay lane). These are hard
|
||||
stops -> take the email lane (rule above) or record `blocked`.
|
||||
- **Acceptable to solve** on the subject's own first-party opt-out: a **static distorted-text image
|
||||
CAPTCHA** (read it with the vision tool) or a **plain arithmetic CAPTCHA** ("8 + 13 = ?"). That is OCR
|
||||
/ arithmetic on a consenting removal, not evasion of a bot-detection system.
|
||||
- **But** if the site then rejects the whole submission ("Captcha verification failed / feature not
|
||||
available") after a correct answer, it is fingerprinting the automation itself, not grading the answer
|
||||
-> **stop, do not loop** (e.g. PrivateRecords' distorted-text-THEN-arithmetic double gate). If no cited
|
||||
rights-email exists, that is a genuine `blocked`.
|
||||
|
||||
## Browser backends: scan vs execute
|
||||
|
||||
Two different jobs need two different browsers. Getting this wrong is the single biggest cause of a
|
||||
run stalling in Phase 2.
|
||||
|
||||
- **Phase 1 (scan, read-only):** a cloud stealth browser (Browserbase) or the `scrapling` skill is
|
||||
ideal. On a residential IP with a real fingerprint it passes managed challenges (Cloudflare
|
||||
Turnstile, hCaptcha checkbox) and reads anti-bot people-search pages that `web_extract` and the
|
||||
proxyless agent browser cannot. This is what the skill's `browser_backend` setting governs
|
||||
(`auto` picks Browserbase when `BROWSERBASE_API_KEY` is present - now also read from
|
||||
`$HERMES_HOME/.env`, not just the shell env, so `doctor`/`setup --auto` detect the key Hermes
|
||||
already loads for its own tools).
|
||||
- **Phase 2 (execute: opt-out forms, webmail sends, session-bound multi-step gates):** the work must
|
||||
run in the **operator's own everyday browser** - real fingerprint, residential IP, AND the
|
||||
operator's logged-in sessions. A headless cloud browser is the WRONG default here for two reasons:
|
||||
(1) it is not signed into the operator's webmail, so browser-mode email sends and confirmation-link
|
||||
opens have no inbox to act in; and (2) it is itself Cloudflare/DataDome-gated on exactly the
|
||||
multi-step flows that matter (e.g. PeopleConnect guided-mode, whose verify link is session- and
|
||||
device-bound to the browser that opens it - a cloud browser both fails the challenge and breaks the
|
||||
binding).
|
||||
- **How to drive the operator's browser (CDP).** Point Hermes's browser tools at the operator's real
|
||||
Chrome over the DevTools protocol: launch
|
||||
`chrome --remote-debugging-port=9222 --user-data-dir="$HOME/.hermes/chrome-debug"` and connect the
|
||||
browser backend to `127.0.0.1:9222`. Use a **dedicated debug profile** (`chrome-debug`), NOT the
|
||||
operator's Default Chrome profile, and have the operator sign into their webmail (and any needed
|
||||
broker accounts) in that profile once. That single browser then carries residential IP + real
|
||||
fingerprint + logged-in sessions, which is precisely what Phase-2 flows need. (This is a Hermes-side
|
||||
browser setup, not a `pdd` config value; `browser_backend` above only selects the Phase-1 scan
|
||||
browser.) **The skill launches this for you: `pdd.py cdp`** finds a Chrome/Chromium/Brave/Edge
|
||||
binary, starts it detached on the dedicated profile, waits for the debug port, and prints the CDP
|
||||
endpoint (`webSocketDebuggerUrl`). `pdd.py cdp --check` reports whether a debug browser is already
|
||||
live (and never launches a second one); `pdd.py cdp --print` just emits the exact command for the
|
||||
operator to run themselves. Point the browser tools at the `endpoint` it returns.
|
||||
- **Always-available fallback:** if no CDP browser is wired up, use the operator-in-the-loop path
|
||||
(scan ladder 3b) - hand over paste-ready URLs and field-by-field least-disclosure guidance, pausing
|
||||
before submit. It never fails; it just needs a human present.
|
||||
|
||||
Backend precedence, most to least autonomous: **operator Chrome over CDP** (Phase 2, hands-off once
|
||||
the profile is signed in) > **Browserbase cloud stealth** (Phase 1 scanning, plus managed-captcha
|
||||
forms that need no login) > **proxyless agent browser** (only already-unblocked sites) >
|
||||
**operator-in-the-loop** (paste-ready URLs; the last-resort unblock that always works).
|
||||
|
||||
## Ownership clusters - DO PARENTS FIRST (playbooks live in the broker records)
|
||||
|
||||
Many brokers are resold shells of a few parents, so **one parent removal clears a whole cluster of
|
||||
children** (see `owns` in each record). In Phase 2 you MUST work the cluster **parents first**, then
|
||||
the standalone listings - doing a child before its parent wastes a submission the parent would have
|
||||
covered. `pdd.py plan <subject> --batch` **orders the `found` group parents-first** and emits a
|
||||
`parent_playbook` whose `steps` come verbatim from each record's **`optout.playbook`** - the single
|
||||
source of truth, field-verified, updated as live runs discover mechanics. What follows is the
|
||||
operating doctrine; the exact steps are in `references/brokers/<id>.json`.
|
||||
|
||||
**Deletion USUALLY beats suppression, email lanes beat forms -- but check the record.** Each parent
|
||||
record carries a structured `optout.deletion` lane (`via: in_flow | email | email_followup`, a
|
||||
privacy address, and `prefer`). The autopilot routes accordingly, and when `deletion.prefer` is
|
||||
false it emits `prefer_suppression` instead of `prefer_deletion`:
|
||||
|
||||
- **`in_flow`** (PeopleConnect, `prefer: false`): the deletion control lives inside the web flow, but
|
||||
for this cluster it is the WRONG lever for search-visibility (see the exception below). Complete the
|
||||
**suppression** flow and maintain it; do not press Delete unless the goal is a data-purge.
|
||||
- **`via: email`** (Whitepages): the fully-autonomous lane - `send-email` the request (residency-picked
|
||||
kind: CCPA for US-CA, GDPR for EU/UK, generic otherwise), then `poll-verification` for their reply
|
||||
and answer identity questions with least-disclosure. This is also the **rescue lane**: any broker
|
||||
whose form demands a phone-callback/gov-ID/account but that declares a deletion email gets routed
|
||||
here instead of the human digest.
|
||||
- **`email_followup`** (BeenVerified, Spokeo): the opt-out form is the fast primary (it clears the
|
||||
listing), and the playbook then sends a right-to-delete email for full erasure beyond suppression.
|
||||
|
||||
Verified parent facts (live-checked 2026-07-02; details + steps in the records):
|
||||
|
||||
- **Intelius/PeopleConnect** (~15+ sites in one flow) -- **EXCEPTION to deletion-beats-suppression.**
|
||||
Portal entry asks only email + consent → verify link is **session-bound to the browser that opens
|
||||
it** → guided-mode. Complete the **SUPPRESSION** flow and keep the account on file: suppression is
|
||||
the do-not-display list that removes you. Per their privacy-center, **'DELETE MY USER DATA' deletes
|
||||
your suppressions and does NOT stop the sites from showing you** (public records re-list), so use it
|
||||
only for a deliberate data-purge. `privacy@peopleconnect.us` is the rights-request address for that
|
||||
path; published metrics: 33.5k deletion requests, median response < 1 day.
|
||||
- **Whitepages**: `privacyrequest@whitepages.com` (or the Zendesk form) handles removal + CCPA
|
||||
deletion **without the phone-callback tool** - that phone call is only required by the automated
|
||||
tool. One removal also drops "all known connected listings". ≤15 days; check 411.com + Premium.
|
||||
- **BeenVerified**: opt-out tool (footer "Do Not Sell" link → `/svc/optout/search/optouts`) + email
|
||||
verification; one opt-out per email address. Then `privacy@beenverified.com` deletion follow-up -
|
||||
controller is The Lifetime Value Co., so name their sister properties (NeighborWho, Ownerly,
|
||||
NumberGuru, Bumper) in the same request, and verify each separately.
|
||||
- **Spokeo**: form takes ONE listing URL at a time and **each listing must be opted out
|
||||
individually** - collect every listing URL from all search vectors first, then submit one opt-out
|
||||
per URL. 24-48h processing. `privacy@spokeo.com` for full deletion beyond free-search suppression.
|
||||
|
||||
After each parent removal is confirmed, **re-scan its children** before submitting anything for them -
|
||||
usually they drop out and need no separate opt-out.
|
||||
|
||||
### Any other parent
|
||||
A parent without a hand-verified `optout.playbook` gets synthesised steps from its structured record
|
||||
(URL/email, `requires` flags, deletion lane, notes/quirks). Follow those, and **write what you learn
|
||||
back into `references/brokers/<id>.json`** (`optout.playbook`, `optout.deletion`, `quirks`,
|
||||
`last_verified`) so the next run is exact - that file, not this one, is where per-broker knowledge
|
||||
accrues.
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# Per-site playbooks (pre-recorded game plans)
|
||||
|
||||
Field-verified game plans so the agent **executes** rather than re-discovers each run: does an
|
||||
in-browser search/opt-out work, what removal lanes exist, which is optimal, and the known gotcha or
|
||||
end-state. This is the durable memory for sites that do not have their own `references/brokers/<id>.json`
|
||||
record (the per-broker JSONs are the memory for the ones that do).
|
||||
|
||||
**Policy lives in `methods.md`** (blind-opt-out default, the blocked-form email-fallback decision order,
|
||||
and the CAPTCHA policy). This file is the site matrix + skip-lists + backend clusters. When you learn a
|
||||
site's mechanics, add or correct a row here (and promote it to a broker JSON if it becomes a recurring
|
||||
removal target).
|
||||
|
||||
## Blocked-tail pass matrix (worked 2026-07-03)
|
||||
|
||||
| Site | In-browser search? | Best lane | Field-verified gotcha / end-state |
|
||||
|---|---|---|---|
|
||||
| **PropertyRecs** | yes (real listing) | in-browser **one-click remove** | Form is a single **Full-Name** field + a **City/State** field (NOT first/last). No email verify, no CAPTCHA. Confirms "Success: Information Removed". Cleanest removal of the batch. |
|
||||
| **CheckPeople** | the flow **is** the search | in-browser **guided flow** | email -> verify link `/opt-out/dob/<token>` (from `info@checkpeople.com`) -> DOB (immutable) -> legal name -> Matching Records. "Unable to find any results that matched your name and date of birth" is a **strong `not_found`** (the broker ran its own matcher). |
|
||||
| **InfoTracer** | form gated | **email** `privacy@infotracer.com` (cited on `/optout`) | Form `members.infotracer.com/removeMyData` has a **slide-to-verify** slider (do NOT defeat). The cited email is a working Zendesk lane (ack + ticket #). **InfoPay backend.** |
|
||||
| **SpyFly** | form gated | **email** `deletemyinfo@spyfly.com` | `/help-center/remove-my-public-record` has a **Cloudflare Turnstile that will not clear**. Privacy policy lists only a form + phone, but the `deletemyinfo@` alias is a working deletion lane. |
|
||||
| **ZoomInfo** | email-gated | submit email (no-op if no profile) | "IF your email matches a profile we will send instructions." No instructions email = no profile. B2B **work-contact** DB; residential-footprint subjects generally do not match. |
|
||||
| **UnMask** | guided flow (stuck) | **human task** | PeopleConnect-family Suppression Center; step-1 "email sent" shown **twice**, but the verify email **never delivers** (checked 2h incl. spam/all-mail) -> broker-side delivery failure, needs a human retry. |
|
||||
| **PrivateRecords** | form (blocked) | **blocked** | `/api/helper/optOutLight/search` -> **double CAPTCHA** (distorted-text image THEN arithmetic) -> still rejected "Captcha verification failed" (it is fingerprinting the automation, not grading the answer). No cited rights-email (policy only has an unsubscribe link). |
|
||||
| **SearchQuarry** | none acceptable | **do NOT pursue** (human decision) | Same **InfoPay** slide-to-verify slider as InfoTracer; FAQ states removals are processed **only** by a mailed/faxed form + a copy of a gov-ID. Violates least-disclosure -> surface as a human decision, do not pursue autonomously. |
|
||||
|
||||
Also recorded `not_found` this pass via operator manual check (`operator_manual_check` evidence note):
|
||||
**ClustrMaps, PeekYou, NeighborReport** (404 / dead), **USA People Search** (no results),
|
||||
**BeenVerified** (no results; an optional preventive deletion email to the controller was left on the
|
||||
table). A dead/404 site or an operator-confirmed "no results" search is a valid `not_found`.
|
||||
|
||||
## Backend clusters (one operator's behavior predicts the others)
|
||||
|
||||
- **InfoPay backend** = **InfoTracer + SearchQuarry** (and other InfoPay-run sites): identical
|
||||
`InfoPay_Core_Components_OptOuts_*` form fields and the same **slide-to-verify** slider. If one shows
|
||||
the slider, expect it on the rest -> go straight to the email lane (where cited) or skip.
|
||||
- **PeopleConnect / Intelius front-end** = **addresses.com** (report links -> `tracking.intelius.com`).
|
||||
Covered by the cluster suppression (`addresses` is in `intelius.owns`); no separate opt-out. See
|
||||
`brokers/intelius.json` and `brokers/addresses.json`.
|
||||
|
||||
## Meta-search / link-out aggregators -- do NOT file opt-outs (no-ops)
|
||||
|
||||
These hold **no first-party data**; they interpolate the name into social-search URLs and show affiliate
|
||||
links to brokers we already handle (Spokeo / TruthFinder / BeenVerified). They clear when the underlying
|
||||
brokers do. Record `not_found` and move on; do **not** add them as broker records or file removals:
|
||||
|
||||
> **IDCrawl, Lullar, Yasni, WebMii, Namesdir, iTools, Skipease.**
|
||||
|
||||
## Triage before scanning (taxonomy)
|
||||
|
||||
When cross-checking any external "people OSINT" list (e.g. an OSINT Radar catalog), separate:
|
||||
|
||||
1. **First-party data brokers** -> removal targets (scan / blind opt-out).
|
||||
2. **Meta-search / link-out aggregators** -> no-ops (skip-list above).
|
||||
3. **Cluster front-ends** -> covered by a parent (e.g. addresses.com -> Intelius); do not double-file.
|
||||
4. **Non-broker tools / APIs / wrong-jurisdiction** -> skip: PhoneInfoga (a tool), People Data Labs
|
||||
(dev API), Truecaller (login-gated app), Canada411 / 192.com (CA / UK jurisdiction).
|
||||
@@ -0,0 +1,56 @@
|
||||
# Case state machine
|
||||
|
||||
One case = one (subject x broker). `pdd.py record` validates every transition against this table and
|
||||
appends it to `audit.jsonl`. Authoritative definition lives in `scripts/ledger.py`.
|
||||
|
||||
## States
|
||||
|
||||
| State | Meaning |
|
||||
|---|---|
|
||||
| `new` | Case created, nothing done |
|
||||
| `searching` | Scan in progress |
|
||||
| `not_found` | Subject not listed (will be re-checked next cycle) |
|
||||
| `found` | Listing confirmed; action needed |
|
||||
| `indirect_exposure` | Subject's PII (email/phone/name) appears on a **third party's** record (e.g. named in a relative's "Family" field). Not removable via self-service opt-out; needs a targeted CCPA/GDPR delete-my-PII request |
|
||||
| `action_selected` | Tier/method chosen |
|
||||
| `submitted` | Opt-out submitted |
|
||||
| `verification_pending` | Awaiting email/callback verification |
|
||||
| `awaiting_processing` | Submitted, no verification needed; broker processing |
|
||||
| `confirmed_removed` | Verified gone |
|
||||
| `reappeared` | Was removed, now listed again |
|
||||
| `human_task_queued` | Needs an operator step (captcha/ID/phone/fax/mail) |
|
||||
| `blocked` | Broker dead / mechanics broken -> flag for DB re-verification |
|
||||
|
||||
## Allowed transitions
|
||||
|
||||
```
|
||||
new -> searching | found | not_found | indirect_exposure | blocked
|
||||
searching -> not_found | found | indirect_exposure | blocked
|
||||
not_found -> searching | found | indirect_exposure | blocked
|
||||
found -> action_selected | submitted | human_task_queued | indirect_exposure | blocked
|
||||
indirect_exposure -> submitted | human_task_queued | not_found | found | blocked
|
||||
action_selected -> submitted | human_task_queued | blocked
|
||||
submitted -> verification_pending | awaiting_processing | human_task_queued | blocked
|
||||
verification_pending -> awaiting_processing | confirmed_removed | human_task_queued | blocked
|
||||
awaiting_processing -> confirmed_removed | human_task_queued | blocked
|
||||
confirmed_removed -> reappeared | confirmed_removed (recheck refreshes the date)
|
||||
reappeared -> found | indirect_exposure
|
||||
human_task_queued -> found | indirect_exposure | action_selected | submitted | verification_pending
|
||||
| awaiting_processing | confirmed_removed | blocked
|
||||
blocked -> searching | found | not_found | indirect_exposure | action_selected
|
||||
| human_task_queued
|
||||
```
|
||||
|
||||
A transition to the same state is always allowed (idempotent field updates).
|
||||
|
||||
## Notes / gotchas learned in the field
|
||||
|
||||
- **`submitted -> not_found` is ILLEGAL.** A lodged request that then finds no matching profile is a
|
||||
no-op that resolves as `awaiting_processing`, never a walk back to `not_found`. (This is why a guided
|
||||
opt-out whose matcher says "no results" after you have already submitted is recorded
|
||||
`awaiting_processing`, not `not_found`.)
|
||||
- **`blocked -> submitted` is ILLEGAL directly** - go `blocked -> action_selected -> submitted`.
|
||||
- **Recording an operator's manual verdict:** attach an `operator_manual_check` evidence note. A
|
||||
dead / 404 site, or an operator-confirmed "no results" search, is a valid `not_found`.
|
||||
- **`--evidence` shell gotcha:** an `--evidence` JSON string containing a literal `&` trips the shell's
|
||||
backgrounding guard - write the word "and" instead of `&`.
|
||||
Reference in New Issue
Block a user