Skip to main content

searchpeoplefree-scraper

PyPI Python License: MIT

A Python scraper for SearchPeopleFree.com person profile pages. One request returns the name, exact age, current and past addresses, every listed phone number and email, aliases, the spouse and relatives, as a Python object, JSON or CSV. Name searches (optionally narrowed to a state) give you the profile URLs.

pip install searchpeoplefree-scraper

Why a plain request fails

SearchPeopleFree shows more for free than most people search sites, and guards it with more layers than most:

Defense What happens
US-only geoblock From a non-US IP the connection is cut off before the server answers. Datacenter IPs and most VPNs fail too.
Cloudflare TLS fingerprinting, JavaScript challenges and Turnstile. A plain requests call gets "Attention Required! | Cloudflare" (HTTP 403).
DataDome A second bot detection layer behind Cloudflare that scores fingerprints and behaviour. Passing Cloudflare alone is not enough.
Email obfuscation Emails in the HTML are encoded with Cloudflare's data-cfemail XOR cipher and decoded by JavaScript in the browser.

This package sends each request through the Scrape.do API with two parameters:

  • geoCode=us keeps the exit IP in the United States
  • super=true uses a residential IP and Scrape.do's anti-bot handling for Cloudflare and DataDome

The emails come from the page's JSON-LD block, where they are plain text, so no decoding is needed. A data-cfemail decoder is included as a fallback. You need a Scrape.do API token; the free plan includes 1,000 credits a month.

Quick start

from searchpeoplefree_scraper import SearchPeopleFreeScraper

scraper = SearchPeopleFreeScraper(token="YOUR_SCRAPEDO_TOKEN")  # or set SCRAPEDO_TOKEN
person = scraper.get_profile("https://www.searchpeoplefree.com/find/<name>/<id>")

print(person.name, person.age)
print(person.address, person.city, person.state, person.zip_code)
print(person.phone, person.email)   # first listed phone and email
print(person.phones, person.emails) # all of them
print(person.spouse, person.relatives)
print(person.aliases, person.past_addresses)

# or start from a name search: about 10 profiles per page
for person in scraper.search_profiles("Jane Doe", state="DC", pages=1, limit=5):
    print(person.name, person.age, person.city)

scraper.search(name, state, pages) returns only the profile URLs; each result page and each profile is one request.

Command line

export SCRAPEDO_TOKEN=your_token

# one profile, JSON to stdout
searchpeoplefree-scraper "https://www.searchpeoplefree.com/find/<name>/<id>"

# many profiles, one URL per line, CSV file
searchpeoplefree-scraper --input urls.txt --format csv --output profiles.csv

# search a name in one state, first 5 profiles
searchpeoplefree-scraper --name "Jane Doe" --state DC --limit 5 -f csv -o jane-doe.csv

Output

Run on the fictional test profile in tests/fixtures:

{
  "name": "Jane Doe",
  "age": 41,
  "address": "2912 Northern Ave",
  "city": "Washington",
  "state": "DC",
  "zip_code": "20001",
  "phones": ["(202) 555-0147", "(202) 555-0199"],
  "emails": ["janedoe@example.com", "jane.m.doe@example.org"],
  "spouse": ["John Doe"],
  "relatives": ["Mary Doe", "Robert Smith", "Emily Doe", "Thomas Doe", "Anna Roe", "Peter Roe"],
  "aliases": ["Jane M Doe", "Jane Marie Doe"],
  "past_addresses": ["44 Elm St, Arlington, VA 22201"],
  "url": "https://www.searchpeoplefree.com/find/jane-doe/example123"
}

In CSV output, list fields are joined with |, so every value fits in one cell.

Fields

Field Source on the page
name JSON-LD Person.name
age article.current-bg summary text ("Age 41"); it is not in the JSON-LD
address, city, state, zip_code JSON-LD contentLocation.address (or address)
phones JSON-LD telephone array
emails JSON-LD email array, falling back to decoding data-cfemail links
spouse JSON-LD spouse (name of each person)
relatives JSON-LD relatedTo (name of each person)
aliases JSON-LD additionalName
past_addresses JSON-LD homeLocation, minus the current address

How the parser works

Every profile page embeds a <script type="application/ld+json"> block of type Person (schema.org). It holds the name, phones, emails, aliases, current and past addresses, spouse and relatives in clean JSON (one test profile listed 37 phones, 30 emails and 54 relatives), and the emails are in plain text there, while the visible HTML hides them behind Cloudflare's email obfuscation. The parser reads that block, then takes the exact age from the profile summary with a regex.

You can also parse HTML you already have, or decode an obfuscated email:

from searchpeoplefree_scraper import decode_cfemail, parse_profile

person = parse_profile(html, url=profile_url)
decode_cfemail("5a303b343f3e353f1a3f223b372a363f74393537")  # 'janedoe@example.com'

parse_profile raises ValueError when the page has no Person JSON-LD block, which usually means a challenge page, a search page or a removed profile.

Limits

  • Name searches only. Phone, address and email lookups are not wrapped; pass the profile URLs they lead to instead.
  • Credits. Every page (search or profile) is one request through a US residential IP: 10 Scrape.do credits in our tests.
  • Layout changes. If SearchPeopleFree changes its markup, parse_profile may return empty fields. Open an issue with the field that broke.
  • Errors. Non-200 responses raise ScrapeError with the status code. Server errors and 429s are retried twice; client errors are not.

Responsible use

This data describes real people. Do not use it to make decisions about employment, housing, credit or insurance: in the US those uses are regulated by the Fair Credit Reporting Act. Honor opt-out requests, follow the privacy laws that apply to you, and follow SearchPeopleFree's terms. This is not legal advice.

Development

git clone https://github.com/bugrahansss/searchpeoplefree-scraper
cd searchpeoplefree-scraper
pip install -e .
python -m unittest discover -s tests -v

The tests run offline against a fictional fixture page.

License

MIT


Source: SearchPeopleFree.com Scraping: Extract Emails, Phones, and Family Data

Metadata

Release files for searchpeoplefree-scraper 0.1.0

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

Source distribution (sdist)

Source distribution for searchpeoplefree-scraper 0.1.0
File Size Uploaded Provenance Actions
searchpeoplefree_scraper-0.1.0.tar.gz 16.9 kB Without provenance Details for searchpeoplefree_scraper-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for searchpeoplefree-scraper 0.1.0
File Interpreter ABI Platform Actions
searchpeoplefree_scraper-0.1.0-py3-none-any.whl Python 3 none any Details for searchpeoplefree_scraper-0.1.0-py3-none-any.whl

Total release size: 29.8 kB

Release files / searchpeoplefree_scraper-0.1.0.tar.gz

Download URL searchpeoplefree_scraper-0.1.0.tar.gz
Size 16.9 kB
Tags Source
SHA-256 checksum
How to use checksums
74a857135177194039393cca5ffdd40b89744a932499534506f1b010b1c42852
BLAKE2b-256 checksum
How to use checksums
0e91ec051536f97a491b5cf5be754dcbfce1c5a36e4798a770d9e3c41be5fcf9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / searchpeoplefree_scraper-0.1.0-py3-none-any.whl

Download URL searchpeoplefree_scraper-0.1.0-py3-none-any.whl
Size 12.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a00b4459d3905ff40521d6d6749e7226a0c7ef4b98f10eaef669119c60d66751
BLAKE2b-256 checksum
How to use checksums
5bf235ce79d26e8bad7edd9a2a9a2127e32580267281527ef016bf7700ae9a74
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for searchpeoplefree-scraper 0.1.0

Provenance

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

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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