# Property Skip Tracing — Address to People Lookup (`memo23/property-skip-tracing`) Actor

Paste a US property address ("123 Main St, Dallas, TX 75201") and get the people on it: phones, emails, mailing address, absentee flag, relatives. One row per person. Pay only when an address matches. Complements name/phone/email skip-trace. Lawful B2B — not for FCRA.

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

## Pricing

from $100.00 / 1,000 skip trace matches

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

## Property Skip Tracing — Address to People Lookup 🏠🔎

**Turn a US property address into named leads in seconds.** Submit a street address and get back the people connected to it — current and former residents, with age, current city, prior locations, and reported relatives. Built for wholesalers, real-estate investors, title researchers, and B2B due-diligence teams who start from a property list, not a name.

**You pay only when an address returns people** — blank lookups are never charged.

#### How it works

![How Property Skip Tracing works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-property-skip-tracing.png)

#### ✨ Why use this Actor?

- **Address-first by design.** Pass `street` + `citystatezip` and get everyone associated with that address — no need to know a name first.
- **Pay only on matches.** The `SkipTraceMatch` event fires once per address that returns at least one person. Empty lookups cost nothing beyond the run start.
- **One row per person.** Output is flat and denormalized with the input address — drop it straight into a CSV, Google Sheet, or dialer with no joins.
- **Single, bulk, or file input.** One address, an array of addresses, or a public CSV/TXT URL — no custom plumbing.
- **Built-in deduplication.** The same person appearing more than once is removed automatically.
- **HTML run report.** Match rate, per-address breakdown, and the lawful-use reminder, saved to the run's key-value store.
- **Standard Apify exports.** JSON, CSV, Excel, plus a webhook to push each record to Zapier / Make / GoHighLevel.

#### 🎯 Use cases

| You are a… | Use it to… |
|---|---|
| Wholesaler / real-estate investor | Turn a distressed-property list into named leads for cold outreach |
| Owner-occupancy checker | See who currently lives at a property — spot likely-absentee owners for direct mail |
| Title / probate researcher | Pull current and former occupants for genealogy / probate context |
| B2B due-diligence / fraud analyst | Cross-check who is associated with a registered business address |
| Process server / investigator | Confirm the people tied to an address before lawful service |

#### 📥 Supported inputs

| Input | Example | Returns |
|---|---|---|
| **Addresses** (one-line) | `["3828 Double Oak Ln, Irving, TX 75061"]` | People connected to each address |
| **Single address** (split) | `street: "3828 Double Oak Ln"`, `citystatezip: "Irving, TX 75061"` | Same lookup, two boxes |
| **Bulk addresses** | `[{ street, citystatezip }, …]` | People for each address, one row per person |
| **Addresses from URL** | `https://example.com/leads.csv` | People for every row of a two-column CSV/TXT |
| **Direct URL** (advanced) | `https://thatsthem.com/address/3828-Double-Oak-Ln-Irving-TX-75061` | Scraped verbatim and parsed the same way |

**Not supported:** international addresses (US-only), records behind a login, and any premium "unlock"-gated report pages.

#### 🔄 How it works

1. **Build the lookup URL** from each address you submit.
2. **Fetch the result page** with a single HTTP request (impit + sliding-window concurrency for bulk lists; automatic anti-bot bypass when needed).
3. **Parse the JSON-LD person graph** embedded in the page.
4. **Dedupe people** and extract each person's name, age, current + prior cities, and reported relatives.
5. **Charge once per matched address**, then **push one row per person** to the dataset (capped at your `maxItems`).

#### ⚙️ Input parameters

| Field | Type | Description |
|---|---|---|
| `addresses` | array | Full one-line US addresses (`123 Main St, Dallas, TX 75201`). Same paste format as other property skip-trace tools. |
| `street` | string | US street address line (optional if `addresses` is set). |
| `citystatezip` | string | `City, ST ZIP` (optional if `addresses` is set). |
| `includePhone` | boolean | Deliver phones. Default `true`. |
| `includeEmail` | boolean | Deliver emails. Default `true`. |
| `bulkAddresses` | array | Array of `{ street, citystatezip }` objects. |
| `addressesFromUrl` | string | Public CSV/TXT URL with two columns: `street, citystatezip`. |
| `startUrls` | array | Direct thatsthem.com URLs, scraped as-is (advanced). |
| `webhookUrl` | string | Each person record is POSTed here as JSON as it's found. Best-effort. |
| `deepSearch` | boolean | Retry unmatched addresses against a secondary public-records source before giving up. Default `true`. |
| `includeContacts` | boolean | Deliver full phone numbers & emails on each row (billed per person that has them). Default `true`. |
| `demoMode` | boolean | Return one sample record with no lookup and no charge. Default `false`. |
| `maxItems` | integer | Hard cap on person records returned. Default `1000`. |
| `maxConcurrency` | integer | How many addresses to fetch in parallel. Default `8`. |

#### 📊 Output overview

The dataset contains **one row per person** connected to the input address. Every row is denormalized with the `inputStreet` and `inputCityStateZip` you submitted, so the file is ready for CSV / Sheet workflows with no joins. Fields the source doesn't have for a given person come back `null` rather than guessed.

#### 📦 Output sample

```json
{
  "inputStreet": "3828 Double Oak Ln",
  "inputCityStateZip": "Irving, TX 75061",
  "name": "Matthew B. Webb",
  "personId": "Matthew-B-Webb",
  "age": 40,
  "livesIn": "Keller, TX",
  "usedToLiveIn": "Dallas, TX",
  "relatedTo": "Jeffery M. Webb, Sherry L. Webb, Haley M. Webb",
  "phones": null,
  "emails": "webbmb@hotmail.com",
  "profileUrl": "https://thatsthem.com/name/Matthew-B-Webb",
  "page": 1,
  "scrapedAt": "2026-07-22T21:04:18.270Z"
}
```

#### 🗂 Key output fields

| Field | Type | Notes |
|---|---|---|
| `inputStreet` | string | Street address you submitted (denormalized on every row) |
| `inputCityStateZip` | string | City/state/ZIP you submitted |
| `name` | string | Full name of the connected person |
| `personId` | string | Stable identifier derived from the source profile |
| `age` | integer | null | Reported age when available |
| `livesIn` | string | null | Most recent city/state of residence |
| `usedToLiveIn` | string | null | Prior cities/states, comma-separated |
| `relatedTo` | string | null | Reported relatives / associates, comma-separated |
| `phones` | string | null | Full phone numbers, comma-separated (with `includeContacts`) |
| `emails` | string | null | Full email addresses, comma-separated (with `includeContacts`) |
| `profileUrl` | string | Public profile URL on the source |
| `page` | integer | Result page index (single-hop, always `1`) |
| `scrapedAt` | string | ISO timestamp of the scrape |

#### 💰 Pricing

Pay-per-event, **match-only**:

- **Actor start** — a small fixed charge once per run.
- **`SkipTraceMatch`** — charged **only** when an address returns at least one person. Empty lookups are not charged.
- **`ContactInfo`** — charged only per delivered person who actually has a phone number or email on file (people without contact data are free). Turn `includeContacts` off to skip both the fields and the charge.

There's also a **free demo mode** (`demoMode: true`) that returns a sample record with no lookup and no charge, so you can preview the exact output shape before scaling.

#### ❓ FAQ

**Where does the data come from?** The Actor reads publicly available people-search content and returns the people the source associates with an address. Profile URLs in each record link back to the source.

**What if no people are returned for an address?** With `deepSearch` on (the default), an unmatched address is automatically retried against a secondary public-records source before giving up. If both come up empty, you're not charged the match event for it. The run-start charge still applies once per run.

**Why do some addresses return people who don't live there now?** Public records list everyone historically associated with an address — current owner, previous tenants, and their relatives. Use `livesIn` / `usedToLiveIn` to filter.

**Are international addresses supported?** No — US addresses only.

**Can I bulk-process a list?** Yes. Use `bulkAddresses` for an array, or `addressesFromUrl` for a two-column CSV/TXT.

**Can I use this to deny someone housing, credit, or a job?** No. This Actor is not a consumer reporting agency and is not FCRA-regulated — see the Disclaimer.

#### 💬 Support

Found a missing field or an address that didn't parse? Open an issue from the Actor's **Issues** tab on Apify with the input you used.

#### 🔎 Explore more scrapers

Need name / phone / email lookups too? Try the companion **[Skip Trace — People, Phone & Address Finder](https://apify.com/memo23/skip-trace-people-finder)** for reverse lookups by any identifier, plus full unmasked phone numbers and address history. Browse the developer's other people-data and lead-generation Actors on the Apify Store.

### 🤖 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/property-skip-tracing`).

**Purpose:** US address → people on that property (current + former residents). One dataset row per person, stamped with the input address.

**Minimal input:**

```json
{ "addresses": ["3828 Double Oak Ln, Irving, TX 75061"], "maxItems": 5 }
```

**Output:** `inputStreet`, `inputCityStateZip`, `propertyAddress`, `name` / `ownerFullName`, `age`, `livesIn`, `usedToLiveIn`, `relatedTo` / `relatives[]`, `phones` / `phoneNumbers[]`, `emails` / `emailAddresses[]`, `ownerMailingAddress`, `isAbsentee`, `lookupStatus` (`contact` or `name_only`), `profileUrl`, `sourceUrl`, `scrapedAt`.

**Behaviors an agent should know:**

- Prefer `addresses` (one-line strings). `street` + `citystatezip` still work.
- Always set `maxItems`. One address can return many people; each row is a person, not an address.
- Empty addresses are not billed the match event. `includePhone` / `includeEmail` default true.
- US only. Not for FCRA decisions.

***

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Zillow Group, ThatsThem, TruePeopleSearch, or any consumer reporting agency. Brand and source names are used solely descriptively to identify the public data the Actor reads. All trademarks are the property of their respective owners.

**Lawful B2B use only.** This Actor returns information about individuals derived from public records. It is **NOT** a consumer reporting agency and its output is **NOT** a "consumer report" under the U.S. Fair Credit Reporting Act (FCRA). You **may not** use any output — directly or indirectly — as a factor in establishing a person's eligibility for credit or insurance, employment, housing or tenant screening, or any other purpose covered by Section 604 of the FCRA (15 U.S.C. § 1681b). You are also responsible for compliance with all applicable privacy laws (CCPA/CPRA, VCDPA, CPA, GDPR, DPPA, GLBA, and any sector-specific regulations). If you are unsure whether your use is permitted, consult qualified legal counsel.

***

### SEO Keywords

property skip tracing, skip tracing scraper, address to owner lookup, owner lookup by address, real estate skip trace, wholesaler skip tracing, absentee owner finder, address to people lookup, reverse address lookup, people search by address, distressed property leads, real estate lead generation, resident lookup, current and former residents, relatives lookup, probate research, title research, b2b due diligence address, thatsthem scraper, apify skip trace, pay per match skip tracing, us address people finder

# Actor input Schema

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

Full US addresses, one per line, e.g. "123 Main St, Dallas, TX 75201". 1–500 per run. Each address that returns at least one person is billed as one match. Do not use this for name search — this actor is address-first.

## `street` (type: `string`):

US street address line, including number and street name (e.g. "3828 Double Oak Ln"). Optional if you filled Addresses.

## `citystatezip` (type: `string`):

Format: "City, ST ZIP" (e.g. "Irving, TX 75061"). State must be a 2-letter US code; ZIP is 5 digits (optional +4). Optional if you filled Addresses.

## `bulkAddresses` (type: `array`):

Array of { "street", "citystatezip" } objects. Example item: { "street": "3828 Double Oak Ln", "citystatezip": "Irving, TX 75061" }

## `addressesFromUrl` (type: `string`):

Public CSV/TXT URL with two columns: street, citystatezip (header row optional). One address per line. Comma- or tab-separated.

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

Direct thatsthem.com URLs to scrape as-is.

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

Each person record is HTTP POSTed here as JSON as soon as it's found. Best-effort; a failed webhook never fails the run.

## `deepSearch` (type: `boolean`):

When the primary source returns no people for an address, automatically retry it against a secondary public-records source before giving up. Raises the match rate at no extra charge — you still pay only per matched address.

## `includeContacts` (type: `boolean`):

Master switch. When false, phones and emails are omitted and ContactInfo is not billed. Default true. Prefer includePhone / includeEmail to turn one side off.

## `includePhone` (type: `boolean`):

When true (default), deliver phone numbers on each person row. Ignored when includeContacts is false. Same job as other property skip-trace tools' includePhone.

## `includeEmail` (type: `boolean`):

When true (default), deliver emails on each person row. Ignored when includeContacts is false. Same job as other property skip-trace tools' includeEmail.

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

Return a single sample record so you can see the exact output format without running a lookup or being charged.

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

Hard cap on the number of person records pushed to the dataset across all addresses.

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

How many addresses (lookups) to fetch in parallel.

## Actor input object example

```json
{
  "addresses": [
    "3828 Double Oak Ln, Irving, TX 75061"
  ],
  "deepSearch": true,
  "includeContacts": true,
  "includePhone": true,
  "includeEmail": true,
  "demoMode": false,
  "maxItems": 1000,
  "maxConcurrency": 8
}
```

# Actor output Schema

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

One record per person found — name, age, current city, prior cities, relatives, and profile URL, stamped with the input address.

## `htmlReport` (type: `string`):

Match rate, per-address results (matched / no match / failed, charged or not), and the lawful-use reminder.

# 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 = {
    "addresses": [
        "3828 Double Oak Ln, Irving, TX 75061"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/property-skip-tracing").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 = { "addresses": ["3828 Double Oak Ln, Irving, TX 75061"] }

# Run the Actor and wait for it to finish
run = client.actor("memo23/property-skip-tracing").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 '{
  "addresses": [
    "3828 Double Oak Ln, Irving, TX 75061"
  ]
}' |
apify call memo23/property-skip-tracing --silent --output-dataset

```

## MCP server setup

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

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/h0M4hKUDhvKMiqb5O/builds/AvmgcttDUFVCRtVGy/openapi.json
