# Skip Trace API — Phone, Email & Address Lookup (`mu0i/skip-tracing-api`) Actor

Skip trace anyone in the US by name, phone, email or address — one lookup or a list of 1,000, a few seconds each, no browser. Phones with carrier and line type, emails, addresses and relatives, merged from several people-search databases into one row. Pay only for named people with contact data.

- **URL**: https://apify.com/mu0i/skip-tracing-api.md
- **Developed by:** [Mu0i](https://apify.com/mu0i) (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 $6.00 / 1,000 person with contact data

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Skip Trace API — Phone, Email & Address Lookup

### What does Skip Trace API do?

**Skip trace anyone in the US from one clue — a name, a phone number, an email or a street address —
and get back where they live, how to reach them, and who they're connected to.** Paste one search or a
list of up to **1,000**, or point it at a **spreadsheet**. Every lookup is checked against several
independent people-search databases at once, and records for the same person are **merged into one
row**, so one result carries everything those sources know between them. It talks to the data
sources directly — no browser to launch — so a search takes a few seconds, a 1,000-row list finishes
in about half an hour, and a run never dies mid-list.

You pay **$7 per 1,000 results**, and only for results you can act on: a named person with a phone, an
email or a street address. Searches that find nobody, name-only rows and errors are free. On the
**free Apify plan** each run tries 10 searches and returns up to 3 results, so you can see real data
before you pay anything.

#### What you get for each person

| | |
|---|---|
| 📞 **Phone numbers** | with line type (wireless / landline / VoIP), carrier, and first/last-seen dates |
| ✉️ **Email addresses** | deduplicated across sources |
| ⭐ **Best phone & best email** | `bestPhone` / `bestEmail` — the one number and email to try first, at the top of each row for CSV export |
| 🏠 **Current address** | street, city, state, ZIP, county |
| 🚩 **Absentee-owner flag** | on an address search, `absenteeOwner` tells you whether the owner lives at the property or elsewhere |
| 🗂️ **Address history** | previous addresses with first/last-reported dates |
| 👪 **Relatives & associates** | names with ages, where known |
| 🪪 **Identity** | full name, age, birth month/year, deceased flag |
| ✅ **Corroboration** | `matchBasis` — how strongly the row is confirmed across independent sources |

### Why use this skip tracing tool?

- **Fast, and it finishes.** No headless browser to launch or babysit: each search takes about 5
  seconds; three run at once by default, so a list of 1,000 completes in roughly 35
  minutes (about 12 with `maxConcurrency: 10`), in 128 MB of memory. Measured on a 12-search mixed
  list: 26 seconds end to end.
- **Never charged for an empty row.** A row is billed only when it names a person *and* gives a phone,
  an email or a street address. A search returns at most `maxResults` people (default 1), so a list of
  1,000 can never come back as 5,000 rows or bill more than 1,000 results.
- **One row, several sources.** Most skip trace tools return what a single site knows. This one queries
  several at once and folds the matching records together, then unions their phones, emails, addresses
  and relatives. Fewer rows, more in each.
- **The right person first.** Name a town or ZIP in a search and people there rank above richer
  records elsewhere; the living rank above the deceased; a name search never returns a different
  surname. Relatives are listed family first (same surname), not a 50-name network.
- **Merged carefully.** Two records are merged only when they share a street address, or a birth year
  *and* a town (the same city or ZIP code). Same-name strangers stay separate, even in the same state.
  So do a father and son at the same address (Jr / Sr).
- **You can see how sure a row is.** Every result says whether it was confirmed by independent sources
  (`address` or `name+dob+state`) or comes from just one (`single-source`), so you can prioritize
  your outreach.
- **Live data.** Each run queries the sources at that moment, not an old cached export.
- **Built for lists.** Up to 1,000 names, addresses, phones and emails in one run, mixed freely, typed
  in or read from a CSV or a shared sheet. Every output row records the search it came from and its
  status, so it joins straight back to your spreadsheet or CRM.
- **Stops where you say.** The run ends cleanly at your spending limit, never goes over it, and a
  platform restart picks up where it left off without re-running or re-charging anything.

#### Who uses skip tracing?

- **Real estate investors & wholesalers:** skip trace property owners, reach absentee owners and
  motivated sellers.
- **Debt recovery & collections:** locate debtors who have moved or changed numbers.
- **Process servers & legal teams:** find a current address before you serve.
- **Sales & lead enrichment:** turn a name and city into a phone and email.
- **Due diligence & fraud checks:** confirm that a person, phone or email belong together.
- **Reconnecting:** find lost contacts, heirs, alumni and old tenants.

### How to use Skip Trace API

1. Click **Try for free** to open the Actor's input form.
2. Add one or more searches to any of the four lists. Each line is one search, and you can mix all four
   types in one run. Or paste a Google Sheet or CSV link into `csvUrl` (see *Input* below).
3. Optionally add `| Full Name` to an entry to keep only that person, or raise `maxResults`.
4. Click **Start**. Results appear in the **Output** tab, ready to export as CSV, Excel, JSON or HTML.
   The **Call list** view has one phone and one email per person; **To re-run** lists the entries that
   need another look.

The four search types and the field each one goes in:

| Search by | Field | Example entry |
|---|---|---|
| Name | `name` | `Michael Johnson; Los Angeles, CA` or `Michael Johnson; 90001` |
| Address (reverse address lookup) | `street_citystatezip` | `350 5th Ave; New York, NY` |
| Phone (reverse phone lookup) | `phone_number` | `(212) 665-1000` |
| Email (reverse email lookup) | `email` | `someone@gmail.com` |

### Input

All fields are optional, and any mix of them works in one run. The **Input** tab has the same
fields as a form.

#### Example list input

```json
{
  "name": ["Michael Johnson; Los Angeles, CA", "Jane Doe; 78701"],
  "street_citystatezip": ["350 5th Ave; New York, NY"],
  "phone_number": ["(212) 665-1000", "+1 312-555-0100"],
  "email": ["someone@gmail.com"],
  "maxResults": 1
}
```

#### Pick one specific person

End any entry with `| Full Name` to keep only that person. This is handy when an address or phone
number returns a whole household and the person you want is not the first one listed:

```json
{
  "street_citystatezip": ["350 5th Ave; New York, NY | John Smith"],
  "phone_number": ["(212) 665-1000 | Jane Doe"]
}
```

The whole list of people at that address or number is checked, not just the first few. A match is
returned with `nameMatch: true`. If nobody there has that name, you get a free `not_found` row whose
`message` says how many other people the search found. Set `fallbackWhenNoMatch: true` to get the
first person found instead, flagged `nameMatch: false`, so you can still tell the two cases apart.

#### From a CSV or Google Sheet

Paste a **Google Sheet link** into `csvUrl` (share the sheet as **Anyone with the link → Viewer**; the
tab in the link is the one read), or a link to a CSV file (Google Drive and Dropbox links work too).
Each row is one search, so a list of 1,000 rows bills like 1,000 searches. Name your columns and they
are mapped automatically:

```
name,street_citystatezip,phone_number,email
John Smith,350 5th Ave; New York NY,,
,1600 Pennsylvania Ave; Washington DC,,
,,(212) 665-1000,
```

For a **property-owner list**, put the property in `street_citystatezip` (or `address`) and the owner
in `name`: the owner name pinpoints the right resident at that address. Common export headers are
understood: separate `City`, `State` and `Zip` columns are joined onto the street; `Owner Name`,
`Owner First Name` + `Owner Last Name`, `Property Address`, `Situs City` and similar; `Last, First`
names; full state names; ZIPs that lost a leading zero; title rows above the header. A mailing-address
column is ignored (it is where the owner gets mail, not the property). A single column with no header
is searched line by line with the type detected automatically. Duplicate rows are searched once. Rows
from the file carry `csvRow`, the line number in your sheet, so results join back exactly. The CSV adds
to anything typed in the lists above and is limited to 2 MB. If the sheet can't be read, the run ends
with a message saying exactly why (private sheet, wrong link, Excel file) and costs nothing.

#### Optional settings

- `maxResults`: the most people per search, from 1 to 50 (default **1**, the best-corroborated
  match). Raise it for common names without a location, or to see everyone at an address. Each extra
  named person with contact data is another billed result.
- `personFilter`: a `| Full Name` filter that applies to every entry without one of its own.
- `fallbackWhenNoMatch`: when a `| Full Name` filter matches nobody, return the first person found
  (`nameMatch: false`) instead of a `not_found` row. Off by default, so a miss never costs anything.
- `csvUrl`: a CSV or spreadsheet link to read searches from (see above).
- `flatOutput`: also add the spreadsheet column layout other skip trace Actors use (`Phone-1` …
  `Phone-5` with Type / Provider / First and Last Reported, `Email-1` … `Email-5`, `Lives in`,
  `Street Address`, `County Name`, `Previous Addresses`, `Relatives` …) on top of the regular fields, so
  an existing sheet, Zapier zap or CRM mapping keeps working unchanged. Off by default.
- `maxConcurrency`: how many searches run at once, from 1 to 10 (default 3).

Up to 1,000 searches per run. Split bigger lists across runs, or schedule them. For long lists, raise
the run **timeout** in Run options. If a run gets close to it, the Actor finishes cleanly and marks
the remaining entries `skipped`, so you lose nothing and can re-run just those.

#### Tips for better matches

- Add a city and state or a ZIP code to a name search (`Jane Doe; Austin, TX`). Common names without a
  location return many different people. In a big city, a ZIP (`Michael Johnson; 90011`) beats the city
  name: neighborhoods often carry their own postal city (Venice, Van Nuys, Hollywood), so a city-only
  search can rank a person listed under one of those below a name-only match downtown.
- A person who lives in the town you named always ranks above a same-name person elsewhere, even a
  richer record. If nobody there has contact data, the top row is a free name-only row rather than a
  billed stranger from another state.
- For an address search, put a `;` between the street and the city/state/ZIP.
- Phone numbers work in any format: `2126651000`, `(212) 665-1000` and `+1 212-665-1000` are all fine.

### Output

Every row starts with the search it answers (`input`, `searchType`) and a `status`:

| `status` | Meaning | Charged? |
|---|---|---|
| `found` | One row per person found | Only if it has a name plus a phone, an email or a street address |
| `not_found` | The search found nobody, or nobody with the `\| Full Name` you asked for (`message` says how many others it found) | Free |
| `invalid_input` | The entry can't be searched (e.g. a phone that isn't 10 digits); `message` says why | Free |
| `error` | A temporary failure; re-run this entry | Free |
| `skipped` | Not run: the spending limit, free-plan cap or run timeout was reached, or the first 100 searches found nobody (see FAQ) | Free |

#### Example result

```json
{
  "input": "Michael Johnson; Los Angeles, CA",
  "searchType": "name",
  "status": "found",
  "matchBasis": "address",
  "fullName": "Michael A Johnson",
  "firstName": "Michael",
  "middleName": "A",
  "lastName": "Johnson",
  "age": 47,
  "birthYear": 1979,
  "currentAddress": {
    "street": "1234 W Example St",
    "locality": "Los Angeles",
    "region": "CA",
    "postal": "90001",
    "county": "Los Angeles",
    "lastReported": "2026-08-01"
  },
  "bestPhone": "(213) 555-0142",
  "bestEmail": "mjohnson@example.com",
  "phones": [
    { "number": "(213) 555-0142", "type": "wireless", "carrier": "T-Mobile", "lastReported": "2026-07-15" },
    { "number": "(323) 555-0198", "type": "landline", "carrier": "AT&T" }
  ],
  "emails": ["mjohnson@example.com"],
  "previousAddresses": [
    { "street": "88 Sample Ave", "locality": "Pasadena", "region": "CA", "postal": "91101" }
  ],
  "relatives": [{ "name": "Laura Johnson", "age": 45 }],
  "associates": [{ "name": "David Kim", "age": 50 }]
}
```

*The example is illustrative and the contact details are fictional.*

`bestPhone` and `bestEmail` are the one number and email to try first (the most recent wireless line),
at the top of every found row so a CSV export is callable without opening the nested `phones` array. On
an **address** search, found rows also carry `absenteeOwner`: `true` when the person's current address
is not the property you searched (an absentee owner — the direct-mail target), `false` when they live
there. It is omitted when the two addresses can't be compared confidently.

Export as CSV or Excel and filter on `status` and `input` to match results back to your list. Filter
on `skipped` or `error` to get exactly the entries to re-run, or on `absenteeOwner` to pull just the
absentee owners.

### How much does skip tracing cost?

**$7.00 per 1,000 results** ($0.007 per result), pay-per-event, with no subscription. Higher Apify
plans get a lower rate.

| You get | You pay |
|---|---|
| 100 named people with a phone, email or street address | $0.70 |
| 1,000 results | $7.00 |
| A search that finds nobody | $0 |
| A name-only row (no phone, email or address) | $0 |
| A row with a name and only a city, state or ZIP | $0 |
| A phone or email that comes back with no person behind it | $0 |
| A list of 1,000 searches at the default `maxResults: 1` | at most $7.00 |
| The same list with `maxResults: 3` | at most $21.00 |

Set a **maximum cost per run** in Apify and the Actor will never go over it. It delivers the results
it can bill, then marks the remaining searches `skipped`.

**A run can never bill more than searches × `maxResults`.** That ceiling is enforced in the Actor
itself, independent of your cost limit. A run that is restarted by the platform picks up where it
left off: finished searches are never re-run, re-delivered or re-charged.

You are **not charged for Apify platform usage** (compute, storage, data transfer): the price per
result is all you pay, plus Apify's standard start event of $0.00005 per run.

#### Is skip tracing free to try?

Yes. **On the free Apify plan** each run tries up to 10 searches and returns up to 3 results, so you
can see the data before you pay. Entries after that are marked `skipped`.

#### Need a volume, private or custom plan?

Email **support@housedata.dev**. We set up volume rates for steady list work, private deployments,
custom input or output formats, and integrations (n8n, Make, your CRM). Say roughly how many searches
a month and what the list looks like, and we'll answer within one business day.

### Integrations and API

Use it from code, from no-code tools, or from an AI agent:

- **Apify API**: run the Actor and fetch the results over REST. See the **API** tab for JavaScript,
  Python, cURL and OpenAPI examples.
- **Make, Zapier, n8n and spreadsheets**: use Apify's integrations to start lookups from a new CRM lead
  or a spreadsheet row.
- **AI agents**: add the Actor to Claude, Cursor or any agent that uses Apify's MCP integration.
  Every output field is documented in the dataset schema, so an agent knows what `bestPhone` or
  `absenteeOwner` means without guessing.

```js
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "<YOUR_APIFY_TOKEN>" });
const run = await client.actor("mu0i/skip-tracing-api").call({
  phone_number: ["(212) 665-1000", "+1 312-555-0100"],
  maxResults: 1,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("mu0i/skip-tracing-api").call(run_input={
    "name": ["Jane Doe; Austin, TX", "Michael Johnson; 90001"],
    "maxResults": 1,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["status"] == "found":
        print(row["input"], "→", row["fullName"], row.get("bestPhone"))
```

### FAQ

#### Where does the skip tracing data come from?

From publicly available US records and people-search databases, queried live on each run. Coverage
varies by person: someone with a long public footprint returns more than someone who has recently
moved or keeps a low profile.

#### Can I paste the input from another skip trace Actor?

Usually as-is. The input field names (`name`, `street_citystatezip`, `phone_number`, `email`, plus
`max_results`) and the `| Full Name` suffix work the same way. A misspelled field
(`street_citystatzip`, `adress`) or a common alternative (`addresses`, `phones`) is read as the field
you meant, and the run's status message says so. For the **output**, set `flatOutput: true` to get the
same column names you have now (`Search Option`, `Input Given`, `Lives in`, `Phone-1` … `Phone-5`,
`Email-1` … `Email-5`, `Previous Addresses`, `Relatives`), alongside ours.

#### How do I skip trace a list of property owners?

Export your list with the property address and the owner name, share it as a sheet (or a CSV
link) and paste the link into `csvUrl`. The owner name pinpoints the right resident at each address,
and every found row carries `absenteeOwner`, so filtering the export on `absenteeOwner = true` gives
you the direct-mail list. See *From a CSV or Google Sheet* above for the column rules.

#### An address search returns the wrong resident

An address or phone search lists everyone linked to it, and with `maxResults: 1` you get the
best-corroborated one. To target a particular resident, add `| First Last` to the entry:
`104 Main St; Marietta, GA 30067 | John Smith`. Every person found for that address is checked, so it
works even when the one you want is listed fifth or tenth. If nobody there matches, the row is a free
`not_found` with a `message`; set `fallbackWhenNoMatch: true` if you'd rather get the first resident in
that case.

#### The run stopped after 100 searches and marked the rest `skipped`

None of the first 100 searches found anyone. A real list almost always finds someone well before that,
so this means the entries are not in a form the search understands: usually a wrong column, a name
with no location, or an address without a `;` before the city. Fix the format (see the examples above)
and run again. Nothing was charged.

#### My whole list came back `not_found` or the run says "Nothing to search"

Check the field names first. The lists are `name`, `street_citystatezip`, `phone_number` and `email`.
A field that can't be placed is reported as ignored rather than silently dropped. Addresses, phone
numbers and emails pasted into the `name` list are recognised and searched as what they are. And since
nothing is charged for a `not_found`, `invalid_input` or empty run, a wrong field name never costs you
anything.

#### Can a run return or charge more rows than my list?

No. Each search returns at most `maxResults` people (default 1) plus its own status rows, which are free.
The Actor refuses to bill past searches × `maxResults` in a run, finishes on its own when the list is
done, and a restarted run never repeats a finished search. If you ever see more billed results than
that, report the run and we'll refund the excess.

#### Why did I get fewer people than `maxResults`?

Records for the same person are merged, so several hits for one person become one row. That's
intended: it means fewer duplicates and more data per row.

#### What does `matchBasis` mean?

- `address`: independent sources agree on this person and share a street address. This is the
  strongest match.
- `name+dob+state`: independent sources agree on name, birth year (within one year) and a town: the
  same city or ZIP code somewhere in the person's address history.
- `single-source`: only one source returned this person.

#### Is a phone number guaranteed to be current?

No. Use `lastReported` and the line type to decide which number to try first. Wireless numbers with a
recent date are usually the best bet, and that is what `bestPhone` picks.

#### Do you keep my searches or results?

Results are written only to your own Apify dataset.

#### What happens if a search fails?

Each search is retried automatically. If it still fails, that entry gets `status: "error"` and the rest
of your list keeps going. Failed entries are never charged. A source outage is reported as `error`,
never as `not_found`, so a "not found" really means nobody was found.

#### Something looks wrong, or I need a custom integration

Open an issue in the **Issues** tab with the input you used (leave out anything private), or email
**support@housedata.dev**. Every issue gets an answer within one business day. For a custom workflow —
a different input format, an n8n or Make template, a volume or private plan — email is best.

### Legal and acceptable use

- Coverage is **US only**.
- Results are **not a consumer report** under the Fair Credit Reporting Act (FCRA). Do not use them for
  decisions about credit, employment, tenant screening, insurance, or any other FCRA purpose.
- If you call or text people you find, you are responsible for complying with the TCPA, Do-Not-Call
  rules and state telemarketing laws.
- Do not use this Actor to stalk, harass, threaten or discriminate against anyone, or for any unlawful
  purpose.
- Data is provided as-is from public sources and may be incomplete or out of date. Verify it before you
  act on it.

### More from the same team

Actors that pair well with skip tracing, by the same developer:

| Actor | What it gives you | Pairs with skip tracing for |
|---|---|---|
| [Zillow Search Scraper](https://apify.com/mu0i/zillow-search-scraper) | Listings by city or ZIP: price, status, days on market, zpid | Build the property list, then skip trace the owners here |
| [Zillow Property Scraper](https://apify.com/mu0i/zillow-property-scraper) | The full record for a property by zpid | Confirm the property before you reach out |
| [TikTok Search Scraper](https://apify.com/mu0i/tiktok-search-scraper) | Videos, users and hashtags for any search | Find creators and local businesses to prospect |
| [TikTok Places Scraper](https://apify.com/mu0i/tiktok-places-scraper) | Locations and their reviews | Local business lead lists |
| [TikTok Video Downloader](https://apify.com/mu0i/tiktok-video-downloader) | MP4 / MP3 without a watermark | — |

All of them run on the same terms: pay per result, nothing for empty runs.

# Changelog

This Actor's version history is a separate document: https://apify.com/mu0i/skip-tracing-api/changelog.md

# Actor input Schema

## `name` (type: `array`):

One person per line, ideally with a location after a semicolon: "Michael Johnson; Los Angeles, CA" or "Michael Johnson; 90001". A location greatly improves matches for common names.

## `street_citystatezip` (type: `array`):

Street, a semicolon, then city/state/ZIP: "350 5th Ave; New York, NY". Add "| Full Name" to keep only one resident: "350 5th Ave; New York, NY | John Smith".

## `phone_number` (type: `array`):

US numbers in any format: "(212) 665-1000", "2126651000" or "+1 212-665-1000". Optionally add "| Full Name".

## `email` (type: `array`):

Email addresses to look up the person behind. Optionally add "| Full Name".

## `personFilter` (type: `string`):

Keep only people whose full name contains all these words, e.g. "John Smith". Applies to every entry that has no "| Full Name" of its own.

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

Paste a Google Sheet link (shared as "Anyone with the link") or a link to a CSV file (Google Drive and Dropbox links work too). Each row is one search. Columns like Name / Owner Name, Address / Property Address (plus City, State, Zip), Phone and Email are recognized; an owner name pinpoints the right person at an address. A single column with no header is searched line by line. Adds to anything typed in the lists above. Column rules: README › "From a CSV or Google Sheet".

## `fallbackWhenNoMatch` (type: `boolean`):

Applies to entries with a "| Full Name" filter. Off: a miss is a free not_found row that says how many other people the search found. On: you get the first people found anyway, flagged nameMatch: false, and they are billed like any result.

## `flatOutput` (type: `boolean`):

Also add the flat column layout other skip trace Actors use — Search Option, Input Given, First/Last Name, Age, Born, Lives in, Street Address, Address Locality/Region, Postal Code, County Name, ZIP+4, Latitude, Longitude, Deliverable, Email-1…5, Phone-1…5 with Type, Provider and First/Last Reported, Previous Addresses, Relatives, Associates — on top of the regular fields. Turn on to keep an existing sheet, Zapier zap or CRM mapping working without changes: Postal Code is still the 5-digit ZIP and no column was renamed or removed, so a mapping that matches on column NAMES is unaffected (one that matches on column POSITION will see the four new columns after County Name).

## `maxResults` (type: `integer`):

Most people to return per search (1–50). Records for the same person are merged and the best-corroborated person comes first, so 1 is right for list skip tracing. Raise it for common names without a location, or to see a whole household at an address. Each extra named person with contact data is one billed result. Free Apify plan: at most 3 results per run.

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

How many searches run at once (1–10). Higher finishes long lists sooner.

## Actor input object example

```json
{
  "name": [
    "Maria Garcia; Houston, TX",
    "Michael Johnson; 90011"
  ],
  "street_citystatezip": [
    "350 5th Ave; New York, NY",
    "104 Main St; Marietta, GA 30067 | John Smith"
  ],
  "phone_number": [
    "(212) 665-1000",
    "+1 312-555-0100"
  ],
  "email": [
    "someone@gmail.com"
  ],
  "csvUrl": "https://docs.google.com/spreadsheets/d/1AbC.../edit#gid=0",
  "fallbackWhenNoMatch": false,
  "flatOutput": false,
  "maxResults": 1,
  "maxConcurrency": 3
}
```

# Actor output Schema

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

The run's dataset: every found person and every status row, in the Results view.

# 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 = {
    "name": [
        "Maria Garcia; Houston, TX"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mu0i/skip-tracing-api").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 = { "name": ["Maria Garcia; Houston, TX"] }

# Run the Actor and wait for it to finish
run = client.actor("mu0i/skip-tracing-api").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 '{
  "name": [
    "Maria Garcia; Houston, TX"
  ]
}' |
apify call mu0i/skip-tracing-api --silent --output-dataset

```

## MCP server setup

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

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/cahxMQxeXApb1CHSc/builds/POQtousvlygll9bJG/openapi.json
