# Skip Trace — People, Phone & Address Finder (`memo23/skip-trace-people-finder`) Actor

Look up a US name, phone, address, or email and get one public-records row per match: phones, emails, address history, relatives, aliases. Mix all four inputs in a single run, or drop a CSV. The email + multi-input slot FastPeopleSearch does not cover. Lawful B2B only — not for FCRA.

- **URL**: https://apify.com/memo23/skip-trace-people-finder.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Lead generation, Real estate
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 1,000 person records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Skip Trace — People, Phone & Address Finder

Look up a US name, phone, address, or email and get one structured record per matched person: phones, emails, current and previous addresses, relatives, aliases, and age. Built for lawful B2B contact enrichment and public-records research — not for FCRA decisions.

Reads publicly available ThatsThem pages. No ThatsThem account or API key required.

#### How it works

![How the Skip Trace scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-skip-trace.png)

#### ✨ Why use this scraper?

- **Phones and emails on the record.** Each matched person includes the phone numbers and emails the public page associates with them.
- **Four lookup modes in one Actor.** Search by **name**, **reverse-phone**, **reverse-address**, or **reverse-email** — mix them in a single run.
- **Whole-person records.** Each row carries name + name variants, aliases, age, deceased flag, every phone, current + previous addresses (with latitude/longitude), and relatives/associates.
- **Bulk-ready.** Drop in a list of names, phones, or addresses and get one row per matched person, billed per record.
- **CSV + CRM built in.** Feed a CSV URL of lookups, POST each result straight to Zapier / Make / GoHighLevel, or preview the exact output for free with demo mode.
- **Fast & clean.** Each search page *is* the result page — a single HTTP call per lookup, no detail-page hop, no pagination.
- **No proxy headaches.** Works on standard US IPs; no captcha-solving or anti-bot bypass required.

#### 🎯 Use cases

| You are a… | Use it to… |
|---|---|
| Real-estate investor / wholesaler | Find the people connected to a property address |
| B2B data / lead-gen team | Append phone numbers and address history to contact lists |
| Due-diligence analyst | Check public address history and known relatives |

#### 📥 Supported inputs

| Input | Example | Returns |
|---|---|---|
| **Name** | `Jane Doe, Springfield, IL` | People matching the name (optional location narrows it) |
| **Phone** (reverse) | `(202) 555-0182` | The likely owner of the number + their record |
| **Address** (reverse) | `123 Main St, Springfield, IL 62704` | People associated with the address |
| **Email** (reverse) | `jane.doe@email.com` | The likely owner of the email |
| **Direct URL** | `https://thatsthem.com/name/Jane-Doe` | Scraped verbatim and parsed the same way |

**Not supported:** pages behind a ThatsThem login, premium background-check reports, and non-US records.

#### 🔄 How it works

1. **Build the lookup URL** for each value you provide (name → `/name/…`, phone → `/phone/…`, address → `/address/…`, email → `/email/…`).
2. **Fetch the result page** with a single HTTP request (impit + sliding-window concurrency for bulk lists).
3. **Parse the person cards** on the result page (and JSON-LD when the site still serves it).
4. **Extract** every person's name, aliases, age, phones, emails, addresses (with geo), and relatives.
5. **Push one row per matched person** to the dataset, capped at your `maxItems`.

#### ⚙️ Input parameters

| Field | Type | Description |
|---|---|---|
| `names` | array | Full names to look up; append `, City, ST` to narrow. |
| `phones` | array | US phone numbers, any format. Reverse lookup. |
| `addresses` | array | Street addresses (`123 Main St, City, ST ZIP`). Reverse lookup. |
| `emails` | array | Email addresses. Reverse lookup. |
| `startUrls` | array | Direct thatsthem.com result URLs, scraped as-is. |
| `csvUrl` | string | URL to a raw CSV whose header names Name / Phone / Address / Email columns (City/State/Zip fold into the name). Each row's cells become lookups. |
| `webhookUrl` | string | Each person record is POSTed here as JSON as it's found (Zapier / Make / GoHighLevel). Best-effort. |
| `demoMode` | boolean | Return one sample record with no lookup and no charge, to preview the output shape. Default `false`. |
| `maxItems` | integer | Hard cap on person records returned (billed per record). Default `100`. |
| `maxConcurrency` | integer | How many lookups to fetch in parallel. Default `8`. |

#### 📊 Output overview

The dataset contains **one row per matched person**. Identity, phones, emails, addresses (current + previous, each with latitude/longitude), and relatives all come merged into that single row — there are no separate address or relative rows to join. Phone numbers are returned **complete**, in `+1-XXX-XXX-XXXX` form. Fields that ThatsThem doesn't have for a given person (e.g. `emails`, `jobTitle`) come back empty rather than guessed.

#### 📦 Output sample

```json
{
  "type": "person",
  "fullName": "John Smith Sandreth",
  "givenName": "John",
  "middleName": null,
  "familyName": "Smith Sandreth",
  "aliases": ["John S. Sandreth", "John W. Smith"],
  "ageText": "December 1962 (63 years old)",
  "deceased": false,
  "lastUpdated": "1 week ago",
  "phones": ["+1-541-517-3975", "+1-541-344-1845", "+1-541-682-6594", "+1-214-497-4501"],
  "emails": [],
  "currentAddress": {
    "streetAddress": "85036 Spencer Hollow Rd",
    "addressLocality": "Eugene",
    "addressRegion": "OR",
    "postalCode": "97405",
    "addressCountry": "US",
    "latitude": 43.97259,
    "longitude": -123.087356,
    "url": "https://thatsthem.com/address/85036-Spencer-Hollow-Rd-Eugene-OR-97405"
  },
  "previousAddresses": [
    {
      "streetAddress": "370 Juniper St",
      "addressLocality": "Florence",
      "addressRegion": "OR",
      "postalCode": "97439",
      "latitude": 43.969859,
      "longitude": -124.10961
    }
  ],
  "addressCount": 5,
  "relatives": [
    { "name": "Mary Sandreth" },
    { "name": "Madison Sandreth" },
    { "name": "Gabriel Sandreth" },
    { "name": "Mark Sandreth" }
  ],
  "sourceUrl": "https://thatsthem.com/name/John-Smith/Florence-OR",
  "scrapedAt": "2026-06-20T21:04:28.471Z"
}
```

#### 🗂 Key output fields

| Field | Type | Notes |
|---|---|---|
| `fullName`, `givenName`, `middleName`, `familyName` | string | Name + parsed parts |
| `aliases` | string\[] | "Known as" / AKA names |
| `ageText` | string | e.g. `"December 1962 (63 years old)"` (when shown) |
| `deceased` | boolean | Flagged when ThatsThem marks the person deceased |
| `phones` | string\[] | **Full** numbers in `+1-XXX-XXX-XXXX` form |
| `emails` | string\[] | Associated emails when available |
| `currentAddress` | object | Street, city, region, ZIP, country, `latitude`, `longitude`, ThatsThem URL |
| `previousAddresses` | object\[] | Same shape; the person's address history |
| `addressCount` | integer | Total addresses on record |
| `relatives` | object\[] | Relatives / associates (`name`) |
| `lastUpdated` | string | How fresh ThatsThem's record is (e.g. `"1 week ago"`) |
| `sourceUrl` | string | The lookup page the record came from |
| `scrapedAt` | string | ISO timestamp of the scrape |

#### Pricing

| Event | When | Rate |
|---|---|---|
| Actor start | Once per run (per GB of memory) | see the Store Pricing tab |
| Person record | Each matched person pushed to the default dataset | see the Store Pricing tab |

Empty / no-match lookups are not billed. `demoMode` writes a sample to the `preview` dataset only.

#### ❓ FAQ

**Are the phone numbers complete?** The Actor returns the phone numbers present on the public result page for each matched person. Some records have none.

**How am I billed?** Per person record pushed to the dataset. Use `maxItems` to cap a run. Lookups that return no match cost nothing for that lookup beyond the page fetch.

**Can I bulk-process a list?** Yes — pass arrays of names, phones, or addresses (or a mix). Each value becomes one lookup and may return several matched people.

**Does it cover non-US people?** No. ThatsThem is a US public-records dataset, so coverage is US-only.

**Why are some `emails` or `coordinates` empty?** Those fields aren't present for every record on ThatsThem. The Actor returns what's available and leaves the rest empty rather than guessing.

**Is this legal to use?** The Actor reads only publicly available ThatsThem pages. You are responsible for using the data lawfully — see the Disclaimer below.

#### 💬 Support

Found a missing field or a record that didn't parse? Open an issue from the Actor's **Issues** tab on Apify with the input you used, and it'll be looked into.

#### 🛠 Additional services

Need this wired into a CRM, scheduled as a recurring enrichment job, or combined with email/phone validation? Reach out through the Apify contact form on the developer profile.

#### 🔎 Explore more scrapers

Looking for related data tools? Browse the developer's other people-data, lead-generation, and public-records Actors on the Apify Store. FastPeopleSearch (name / phone / address only) is a separate Actor — this one is the email + mixed-input slot.

### 🤖 For AI Agents & LLM Apps

Compact reference for agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (`memo23/skip-trace-people-finder`).

**Purpose:** US public-records people lookup on ThatsThem. Mix name, reverse-phone, reverse-address, and reverse-email in one run. One dataset row per matched person.

**Minimal input:**

```json
{ "names": ["Jane Doe, Springfield, IL"], "emails": ["jane.doe@email.com"], "maxItems": 5 }
```

**Output:** one row per person — `fullName`, `givenName`, `middleName`, `familyName`, `aliases`, `ageText`, `deceased`, `phones[]`, `emails[]`, `currentAddress {streetAddress, addressLocality, addressRegion, postalCode, latitude, longitude, url}`, `previousAddresses[]`, `addressCount`, `relatives[{name}]`, `profileUrl`, `sourceUrl`, `scrapedAt`.

**Behaviors an agent should know:**

- Always set `maxItems`. A common name can return many people; each row is billed.
- Fill any combination of `names`, `phones`, `addresses`, `emails`, `startUrls`, or `csvUrl`. An empty run fails and is not billed.
- `demoMode: true` writes a fake row to the `preview` dataset and the `OUTPUT` key — no lookup, no charge.
- Empty / no-match lookups are not billed. US records only. Not for FCRA decisions.

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by ThatsThem, Intelius, or any of their subsidiaries or affiliates. All trademarks mentioned are the property of their respective owners.

This Actor is an independent tool and is not affiliated with ThatsThem. It reads only publicly available pages. Output may be regulated under the Fair Credit Reporting Act (FCRA), DPPA, GDPR/CCPA, or similar laws. **Do not use this data for credit, employment, insurance, tenant screening, or any FCRA-regulated purpose.** You are responsible for lawful use.

***

### SEO Keywords

thatsthem scraper, people search, reverse phone lookup, reverse address lookup, reverse email lookup, contact enrichment, address history, public records people search, b2b contact data

# Actor input Schema

## `names` (type: `array`):

Full names to look up. Optionally append a location after a comma to narrow results, e.g. "Jane Doe, Springfield, IL". Each value becomes one /name/ lookup and may return several people. Not required if you fill phones, addresses, emails, or startUrls.

## `phones` (type: `array`):

US phone numbers in any format — "(202) 555-0182", "202-555-0182", "+1 202 555 0182". Each number becomes one reverse lookup. Numbers that are not 10 digits after stripping a leading 1 are skipped.

## `addresses` (type: `array`):

Street addresses with city, state and ZIP, e.g. "123 Main St, Springfield, IL 62704". Each address becomes one reverse lookup of the people tied to that property.

## `emails` (type: `array`):

Email addresses to reverse-lookup the likely owner, e.g. "jane.doe@email.com". This is the slot FastPeopleSearch does not take. Invalid emails are skipped.

## `startUrls` (type: `array`):

Direct thatsthem.com result URLs to scrape as-is, e.g. "https://thatsthem.com/name/Jane-Doe". Accepted path prefixes: /name/, /phone/, /address/, /email/.

## `csvUrl` (type: `string`):

HTTPS URL of a raw CSV. Header names should include Name, Phone, Address, and/or Email (City/State/Zip fold into the name). Each populated cell becomes one lookup. Leave empty for array inputs only.

## `webhookUrl` (type: `string`):

HTTPS endpoint that receives each person record as JSON the moment it is found (Zapier / Make / GoHighLevel). Best-effort: a failed webhook never fails the run. Leave empty to skip.

## `demoMode` (type: `boolean`):

When true, write one fake sample record to the preview dataset and the OUTPUT key-value record. No ThatsThem lookup and no per-person charge. Default false.

## `maxItems` (type: `integer`):

Hard cap on person records pushed to the default dataset across all lookups. You are billed per record. Default 100. Minimum 1.

## `maxConcurrency` (type: `integer`):

How many lookup pages to fetch in parallel. Default 8. Raise for large CSV batches; lower if you hit blocks.

## Actor input object example

```json
{
  "names": [
    "John Smith, Florence, OR"
  ],
  "emails": [
    "jane.doe@email.com"
  ],
  "demoMode": false,
  "maxItems": 100,
  "maxConcurrency": 8
}
```

# Actor output Schema

## `results` (type: `string`):

Every matched person record in the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "names": [
        "John Smith, Florence, OR"
    ],
    "emails": [
        "jane.doe@email.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/skip-trace-people-finder").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "names": ["John Smith, Florence, OR"],
    "emails": ["jane.doe@email.com"],
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/skip-trace-people-finder").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "names": [
    "John Smith, Florence, OR"
  ],
  "emails": [
    "jane.doe@email.com"
  ]
}' |
apify call memo23/skip-trace-people-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/skip-trace-people-finder"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/v3ly939v1yKrfZ7ul/builds/GA0QS8n3xcpXhy2t3/openapi.json
