# Whitepages Leads Scraper (`searchshark/whitepages-leads-scraper-v2`) Actor

Find and collect qualified leads from public records by name, phone number, or address. Extract phone numbers, addresses, relatives, contact details, and match confidence into clean, structured data for lead generation and research.

- **URL**: https://apify.com/searchshark/whitepages-leads-scraper-v2.md
- **Developed by:** [SearchShark Tools](https://apify.com/searchshark) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $15.00 / 1,000 results

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 & Reverse Lookup

**Skip Trace & Reverse Lookup** searches U.S. and Canadian public-record data by **name, phone number, or address** and returns clean, structured results for research, lead enrichment, and automation.

- 👤 Search people by name + location
- 📞 Reverse lookup phone numbers
- 🏠 Reverse lookup street addresses
- 📦 Process multiple records in one run
- 🧭 Automatically choose the lookup mode
- 📊 Get match confidence and match evidence
- 🆔 Keep every result connected to your original row
- ⚠️ Separate real no-matches from provider failures

> This Actor returns possible public-record matches. It does **not** verify identity and is **not intended for FCRA-regulated decisions**.

***

### 🌍 Supported Regions

**US ✅**

- People search
- Reverse phone
- Reverse address

**Canada ✅**

- People search
- Reverse phone
- Reverse address

Set `country` on each record to `US` or `CA`. If omitted, it defaults to `US`. For Canada, `province` and `postalCode` are supported aliases for `state` and `zip`.

## UK, Australia, and other regions are not supported in the current version.

### 📦 What data can it return?

|                               |                                  |
| ----------------------------- | -------------------------------- |
| 🆔 **Input row ID**           | 🔗 **External lead ID**          |
| 🔍 **Lookup mode**            | 🚦 **Resolution status**         |
| 🏆 **Candidate rank**         | 📊 **Match confidence**          |
| 🧾 **Match evidence**         | ⚠️ **Ambiguity reason**          |
| 👤 **Full name**              | 🪪 **Aliases**                   |
| 🎂 **Age** when available     | 🏠 **Current address**           |
| 🗂 **Past addresses**          | ☎️ **Phone numbers**             |
| 📱 **Best phone**             | 📞 **Phone type** when available |
| 📡 **Carrier** when available | 👪 **Relatives**                 |
| 👥 **Possible associates**    | 🔗 **Source URL** when available |
| 🕒 **Scrape timestamp**       | ✅ **Success / error metadata**  |

> Missing fields are returned as `null` or empty arrays. The Actor does **not invent missing data**.

***

### 🚀 Features

- **3 lookup modes:** people, reverse phone, reverse address
- **Automatic lookup detection** from the fields in each record
- **Bulk input** through `records[]`
- **Row traceability** with `inputRowId` and `externalLeadId`
- **Deterministic match scoring**
- **Explainable evidence** through `matchEvidence`
- **Configurable confidence threshold**
- **Ambiguous-match handling**
- **Candidate deduplication**
- **Retryable provider-failure states**
- **Structured Apify Dataset output**
- **JSON, CSV, API, and integration friendly**

***

## ⬇️ Input

The main input is:

```text
records[]
```

Each object in `records` is one lookup.

#### 👤 People lookup

Provide a name plus location context.

```json
{
    "inputRowId": "lead-001",
    "fullName": "Jane Example",
    "city": "Austin",
    "state": "TX"
}
```

You can also use `firstName` and `lastName`.

***

#### 📞 Reverse phone lookup

Provide a phone number.

```json
{
    "inputRowId": "lead-002",
    "phone": "2025550104"
}
```

The Actor normalizes phone data before matching.

***

#### 🏠 Reverse address lookup

Provide a street address and location.

```json
{
    "inputRowId": "lead-003",
    "address": "100 Example Ave",
    "city": "Austin",
    "state": "TX",
    "zip": "78701"
}
```

***

### 🧭 Automatic lookup selection

`lookupMode` is optional.

If omitted, the Actor chooses from the available data:

```text
Phone
→ reverse_phone

Address
→ reverse_address

Name + location
→ people

Not enough usable data
→ INVALID_INPUT
```

You can also explicitly set:

```text
people
reverse_phone
reverse_address
```

***

### ⚙️ Main options

| Option                   | Purpose                                        |
| ------------------------ | ---------------------------------------------- |
| `maxCandidatesPerRecord` | Limit candidate rows retained per input record |
| `minimumMatchConfidence` | Set the minimum deterministic match score      |
| `includeAmbiguous`       | Keep strong near-tie candidates                |
| `deduplicatePeople`      | Remove duplicate person candidates             |
| `maxConcurrency`         | Control parallel processing                    |
| `maxRetries`             | Control retry attempts                         |

***

### 🧪 Example bulk input

```json
{
    "records": [
        {
            "inputRowId": "lead-001",
            "externalLeadId": "crm-1001",
            "fullName": "Jane Example",
            "city": "Austin",
            "state": "TX"
        },
        {
            "inputRowId": "lead-002",
            "externalLeadId": "crm-1002",
            "phone": "2025550104"
        },
        {
            "inputRowId": "lead-003",
            "externalLeadId": "crm-1003",
            "address": "100 Example Ave",
            "city": "Austin",
            "state": "TX",
            "zip": "78701"
        }
    ],
    "minimumMatchConfidence": 0.6,
    "includeAmbiguous": true,
    "deduplicatePeople": true
}
```

Each record is processed independently.

***

## ⬆️ Output

Results are stored in the Actor's default **Apify Dataset**.

Each output row stays linked to the source record through `inputRowId` and, when supplied, `externalLeadId`.

#### 📊 Example result

```json
{
    "inputRowId": "lead-001",
    "externalLeadId": "crm-1001",
    "lookupModeUsed": "people",
    "resolutionStatus": "MATCHED",
    "candidateRank": 1,
    "matchConfidence": 0.8,
    "matchEvidence": ["name_match", "city_state_match"],
    "fullName": "Jane Example",
    "currentAddress": "100 Example Ave, Austin, TX 78701",
    "phoneNumbers": ["(202) 555-0104"],
    "bestPhone": "(202) 555-0104",
    "relatives": [],
    "possibleAssociates": [],
    "success": true,
    "errorCode": null,
    "errorMessage": null,
    "retryable": false
}
```

Example values are fictional and only demonstrate the output structure.

***

### 🚦 Resolution statuses

| Status          | Meaning                                                                      |
| --------------- | ---------------------------------------------------------------------------- |
| `MATCHED`       | A candidate met the matching threshold                                       |
| `AMBIGUOUS`     | Multiple strong candidates are too close to safely choose one                |
| `NO_MATCH`      | The lookup completed, but no candidate met the matching rules                |
| `PARTIAL`       | The lookup could not complete normally, such as an upstream provider failure |
| `INVALID_INPUT` | The input row did not contain enough valid lookup data                       |

#### ⚠️ No-match vs provider failure

These are intentionally different:

```text
Lookup completed with no acceptable candidate
→ NO_MATCH

Provider blocked, skipped, or failed
→ PARTIAL + PROVIDER_FAILED
```

This helps automated workflows decide whether a row should be retried.

***

### 📊 Match confidence

`matchConfidence` is a deterministic score based on available evidence.

Matching can use signals such as:

```text
Name
Phone
Address
City
State
ZIP
```

`matchEvidence` shows which evidence contributed to the result.

> Match confidence is a ranking aid, not proof of identity.

***

### 🧹 Candidate handling

When multiple public-record candidates are returned, the Actor can:

1. Normalize the input
2. Deduplicate candidates
3. Score candidates against the original row
4. Rank the strongest candidates
5. Apply `minimumMatchConfidence`
6. Return `MATCHED`, `AMBIGUOUS`, or `NO_MATCH`

The Actor prefers an honest ambiguous or no-match result over promoting weak evidence into a confident match.

***

## 🔌 API & integrations

Run the Actor through the **Apify API** or connect its Dataset to workflows such as:

- Google Sheets
- Make
- Zapier
- CRMs
- Internal APIs
- Data warehouses
- Lead-processing pipelines
- AI agents
- MCP workflows

Use the Actor's **API** tab in Apify Console for ready-made request examples.

***

## 💡 Example use cases

#### 🎯 Lead enrichment

Start with a name and location and attempt to resolve structured public-record contact data while preserving your lead ID.

#### 📞 Reverse phone research

Search a phone number and review possible public-record matches with structured match evidence.

#### 🏠 Address research

Search an address for supported public-record resident or contact information.

#### 🧹 CRM cleanup

Use `inputRowId`, `externalLeadId`, `resolutionStatus`, and `matchConfidence` to review results before syncing them downstream.

***

## 📤 Export results

Apify Dataset results can be exported in formats such as:

```text
JSON
CSV
Excel
XML
HTML
```

***

## ⚠️ Current limitations

The current version supports **U.S. and Canadian public-record lookups** through region-specific providers.

It does not guarantee:

- A result for every person, phone, or address
- That public-record information is current or complete
- Verified identity
- Phone ownership without supporting returned evidence
- Email enrichment
- Consumer-report accuracy
- Continuous availability of every upstream source

Provider coverage can change between runs.

***

## ⚖️ Responsible use

Use this Actor only for lawful public-record research and data workflows.

Do **not** use it for:

- Credit eligibility
- Employment screening
- Housing or tenant decisions
- Insurance eligibility or underwriting
- Stalking or harassment
- Fraud
- Discrimination
- Other unlawful purposes

This Actor is **not a consumer report** and is **not designed for FCRA-regulated decisions**.

You are responsible for complying with applicable privacy, public-record, telecommunications, and data-protection laws.

***

## ❓ FAQ

#### What can I search?

```text
People by name + location
Phone numbers
Street addresses
```

#### Can I process multiple records?

Yes. Add multiple objects to `records[]`.

#### Do I need to select a lookup mode?

No. The Actor can automatically select the mode from the available fields.

#### What does `NO_MATCH` mean?

The lookup completed, but no candidate satisfied the Actor's matching rules.

It does **not** mean that every possible public record was searched.

#### What does `PARTIAL` mean?

The lookup could not complete normally. Check:

```text
errorCode
errorMessage
retryable
```

#### Is `matchConfidence` proof of identity?

No. It is a deterministic matching score.

#### Why are some fields `null`?

Not every source exposes every field. Missing values are preserved instead of fabricated.

#### Can I use it through an API?

Yes. Open the Actor's **API** tab for examples.

***

## 💬 Feedback & support

Found a bug or unexpected result?

Use the Actor's **Issues** tab and include:

```text
lookupModeUsed
resolutionStatus
errorCode
errorMessage
```

Avoid posting sensitive personal data publicly in issue reports.

***

### 🚀 Structured skip tracing for automation

Submit a **name, phone number, or address** and get structured public-record results with traceable row IDs, match confidence, clear no-match handling, and retryable provider-failure states.

# Actor input Schema

## `records` (type: `array`):

Bulk lead records to look up. Provide a phone, an address, or a name plus location. lookupMode is optional.

## `maxCandidatesPerRecord` (type: `integer`):

Maximum candidate rows retained for each input record.

## `minimumMatchConfidence` (type: `number`):

Minimum candidate confidence required for a match.

## `includeAmbiguous` (type: `boolean`):

Include strong near-tie candidates classified as AMBIGUOUS.

## `deduplicatePeople` (type: `boolean`):

Deduplicate person candidates using stable phone or person/address keys.

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

Maximum number of concurrent crawler requests.

## `maxRetries` (type: `integer`):

Maximum retries for retryable request failures.

## Actor input object example

```json
{
  "maxCandidatesPerRecord": 10,
  "minimumMatchConfidence": 0.6,
  "includeAmbiguous": true,
  "deduplicatePeople": true,
  "maxConcurrency": 5,
  "maxRetries": 3
}
```

# Actor output Schema

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

Lead-ready result rows from 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("searchshark/whitepages-leads-scraper-v2").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("searchshark/whitepages-leads-scraper-v2").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 '{}' |
apify call searchshark/whitepages-leads-scraper-v2 --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,searchshark/whitepages-leads-scraper-v2"
        }
    }
}
```

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/ML1eBjFMZhmOaD34i/builds/dGSupabn1aBLDbWi5/openapi.json
