# US Property Assessment Scraper — Values, Owners & Sale Price (`ai-lead-gen-tools/united-states-property-owner-address-parcel-records-scraper`) Actor

County assessor data from 13 states and 45.5M parcels: assessed value, market value, land and improvement value, tax year, last sale date and price, owner, acreage, year built, mailing address. Search by address, parcel or owner; each owner search returns a free portfolio row with absentee count.

- **URL**: https://apify.com/ai-lead-gen-tools/united-states-property-owner-address-parcel-records-scraper.md
- **Developed by:** [Vladimir Chernykh](https://apify.com/ai-lead-gen-tools) (community)
- **Categories:** Lead generation, Real estate, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.80 / 1,000 property record scrapeds

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

## US Property Assessment Data Scraper — Assessed Value, Sale Price & Owner

Scrape **US property assessment and sales data** from the official statewide parcel layers that
county assessors and state GIS offices publish themselves. No proxy, no API key, no login, no
CAPTCHA. Thirteen states are measured and served, covering **45 542 174 parcels**. Every number on
this page comes from querying the layer's own `returnCountOnly` endpoint before the state was added —
not from a vendor datasheet.

You pay for **valuation, tax and sale depth**, not for a name-and-address list. Of the 13 states,
**10 return a valuation** (land value, improvement value, total or assessed or market value),
**5 return a last sale date**, **4 a last sale price** and **4 the tax year the value applies to** —
and where a source does not publish one of these, the row says so instead of leaving an unexplained
blank.

### Every state it serves, and the format each one returns

The point of this table is that you can see before you spend a cent whether your state and your
fields are covered. `Full` means the layer carries that group for the whole state. `—` means the
source does not publish the column at all, so no row from that state will ever contain it — and each
such row says so explicitly in its `omitted` array.

| State | Jurisdictions covered | Parcels | Returns owner | Returns situs address | Returns mailing address | Returns valuation | Returns county FIPS | Lookups that work |
|---|---|---|---|---|---|---|---|---|
| **North Carolina** (NC) | **100 / 100** counties | 5 938 804 | yes | yes | yes | yes | yes | owner, address, parcel |
| **New York** (NY) | **62 / 62** counties | 5 510 061 | yes (+ co-owner, owner type) | yes | yes | yes | yes | owner, address, parcel |
| **California** (CA) | **58 / 58** counties | 13 138 000 | — | yes | — | — | yes | address, parcel |
| **Colorado** (CO) | 44 / 64 counties | 2 599 937 | yes (+ co-owner) | yes | yes | assessed value | yes | owner, address, parcel |
| **Arkansas** (AR) | **75 / 75** counties | 2 149 448 | yes | yes | — | yes | yes | owner, parcel |
| **Connecticut** (CT) | **8 / 8** counties | 1 282 833 | yes (+ co-owner) | yes | yes | yes, plus tax year | yes | owner, parcel |
| **Maryland** (MD) | **24 / 24** jurisdictions | 2 395 737 | — | yes | yes | yes | yes | address, parcel |
| **Massachusetts** (MA) | **351 / 351** municipalities | 2 559 749 | yes | yes | yes | yes, plus tax year | — | owner, address, parcel |
| **Utah** (UT) | **29 / 29** counties | 1 600 062 | — | yes | — | — | — | address, parcel |
| **Virginia** (VA) | county column absent | 76 957 | yes | — | yes | yes | — | owner, parcel |
| **Washington** (WA) | **39 / 39** counties | 3 321 859 | — | yes | — | yes | 38 of 39 counties | address, parcel |
| **West Virginia** (WV) | **55 / 55** counties | 1 394 081 | yes (+ co-owner) | street line | street line | — | — | owner, address, parcel |
| **Wisconsin** (WI) | **72 / 72** counties | 3 574 646 | yes (+ co-owner) | yes | yes | yes, plus tax year | yes | owner, parcel |

#### The same table as rows and columns per state

| State | Fields the layer actually fills | Fields the source lacks (declared per row) |
|---|---|---|
| NC | parcel, county name, FIPS, jurisdiction, owner, co-owner, owner type, land value, improvement value, total value, acreage, land use code, land use, year built, last sale date, situs, mailing | market value, assessed value, tax year, building sq ft, last sale price |
| NY | parcel, county, FIPS, jurisdiction, owner, co-owner, owner type, land value, improvement value, total value, market value, tax year, acreage, land use code, year built, building sq ft, situs, mailing | assessed value, land use text, sale date, sale price |
| CA | parcel, county, FIPS, situs address | owner (all owner fields), mailing address, every valuation field, acreage, year built, building sq ft, land use, sale date, sale price |
| CO | parcel, county, FIPS, owner, co-owner, total value, assessed value, acreage, land use code, land use, sale date, sale price, situs, mailing | jurisdiction, owner type, land value, improvement value, market value, tax year, year built, building sq ft |
| AR | parcel, county, FIPS, owner, land value, improvement value, total value, assessed value, land use code, situs | jurisdiction, co-owner, owner type, mailing address, market value, tax year, acreage, year built, sale date, sale price |
| CT | parcel, FIPS, jurisdiction, owner, co-owner, land value, improvement value, total value, assessed value, tax year, acreage, land use code, land use, year built, building sq ft, sale date, sale price, situs, mailing | county name, owner type, market value |
| MD | parcel, FIPS, land value, improvement value, total value, acreage, land use code, land use, year built, building sq ft, sale date, sale price, situs, mailing | county name, jurisdiction, owner (all owner fields), market value, tax year |
| MA | parcel, municipality, owner, land value, improvement value, assessed value, tax year, acreage, land use code, land use, year built, building sq ft, sale date, sale price, situs, mailing | county name, county FIPS, co-owner, owner type, market value |
| UT | parcel, county, owner type, situs address | FIPS, jurisdiction, owner name, co-owner, mailing address, every valuation field, acreage, land use, year built, building sq ft, sale date, sale price |
| VA | parcel, owner, land value, improvement value, total value, land use code, land use, mailing address | county name, FIPS, jurisdiction, co-owner, owner type, **situs address**, market value, assessed value, tax year, acreage, year built, building sq ft, sale date, sale price |
| WA | parcel, FIPS, land value, improvement value, land use code, situs address | jurisdiction, owner (all owner fields), mailing address, market value, assessed value, tax year, acreage, year built, building sq ft, sale date, sale price |
| WV | parcel, owner, co-owner, acreage, situs street line, mailing street line | county name, FIPS, jurisdiction, owner type, every valuation field, land use, year built, building sq ft, sale date, sale price |
| WI | parcel, county, FIPS, owner, co-owner, land value, improvement value, assessed value, market value, tax year, acreage, land use code, situs, mailing street line | jurisdiction, owner type, land use text, year built, building sq ft, sale date, sale price |

California is the largest layer here (13.1 M parcels) and the sparsest in columns: it publishes
geometry-linked parcel identity and address, and nothing about the owner. That is a property of the
source, not a mapping gap — and the run summary reports it as such.

#### Which states actually return value and sale prices

This is the part most property datasets obfuscate, so it is on one screen.

| State | Value fields returned | Tax year | Last sale | Physical |
|---|---|---|---|---|
| NC | land, improvement, total | — | date only | acreage, year built, land use |
| NY | land, improvement, total, **market** | yes | — | acreage, year built, sq ft, land use |
| CA | none | — | — | — |
| CO | total, **assessed** | — | date + price | acreage, land use |
| AR | land, improvement, total, **assessed** | — | — | land use |
| CT | land, improvement, total, **assessed** | yes | date + price | acreage, year built, sq ft, land use |
| MD | land, improvement, total | — | date + price | acreage, year built, sq ft, land use |
| MA | land, improvement, **assessed** | yes | date + price | acreage, year built, sq ft, land use |
| UT | none | — | — | — |
| VA | land, improvement, total | — | — | land use |
| WA | land, improvement | — | — | — |
| WV | none | — | — | acreage |
| WI | land, improvement, **assessed**, **market** | yes | — | acreage, land use |

A dash is a fact about the source, and the same fact is repeated in the `omitted` array of every row
from that state. Nothing here is inferred to fill a column.

### The `omitted` array is the reason to trust a blank cell

Every canonical field exists on every record. When one is `null`, it is **never silent** — the row
carries `omitted`, an array naming the field and the reason:

- `source-lacks-field` — the layer has no such column. No record from this state will ever have it.
- `not-published` — the column exists, but this row's value was blank.
- `derived` — the number was computed rather than read, and it says so (New York's improvement value;
  North Carolina's glued addresses).
- `not-covered` — the jurisdiction is outside the layer.
- `lookup-miss` — you searched, and nothing matched.
- `filtered` — your own input excluded it.

So `lastSaleDate: null` with `{ "field": "lastSaleDate", "reason": "source-lacks-field" }` means
**"this county does not publish sale dates"**, not "this house never sold". Those are different
statements and only one of them is true. A property data scraper that quietly leaves cells empty
forces you to guess which. This one does not.

### Input parameters

| Parameter | Type | Default | What it does |
|---|---|---|---|
| `ownerNames` | string list | — | Owner-name search, one name per row, minimum 3 characters. Partial match: `SILVER PINES` finds `SILVER PINES PROPERTIES LLC`. |
| `addresses` | string list | — | Situs address search, one per row, minimum 4 characters, with a street-only fallback. `609 MAIN ST` works better than `609 Main Street, Raleigh, NC 27601`. |
| `parcelIds` | string list | — | Parcel number as the county writes it. `1234-56-789`, `123456789` and `1234 56 789` are all tried. New York wants the PRINT_KEY value. |
| `states` | multi-select | all | Which of the 13 states to query. A state measured as broken is an error naming the measurement, not a silent empty dataset. |
| `bulk` | boolean | `false` | Ignore lookup lists and sample rows straight from the layer, to inspect a source before paying for lookups. |
| `bulkCount` | integer | `50` | Rows per state in bulk mode (max 1000). The layer's own maximum is respected and truncation is reported. |
| `maxRecords` | integer | `50` | Hard cap for the whole run across all states — this is also your cost cap (max 1000). |
| `maxRecordsPerLookup` | integer | `10` | How many parcels one owner name or one address may return. Stops a surname like `SMITH` from eating the budget. |
| `ownerPortfolio` | boolean | `true` | After every owner search, push one **free** `owner_portfolio` row: parcels returned, counties, value totals with the count of records behind each total, acreage, absentee count. Never billed. |
| `includeRaw` | boolean | `false` | Attach the untouched source attributes to each record under `raw`, for columns outside the mapped set. |
| `maxConcurrency` | integer | `2` | Parallel lookups. The layers are public and unauthenticated; 2 is polite and fast enough. |
| `requestTimeoutSecs` | integer | `45` | Per-request timeout. New York answers in 6–8 seconds from the platform, so do not go below 20. |
| `chargePerRecord` | boolean | `true` | Emits one billing event per distinct record pushed. Missed lookups are never charged. |

Example — lookups across two states:

```json
{
  "ownerNames": ["SILVER PINES PROPERTIES LLC"],
  "addresses": ["105 E MAIN ST"],
  "parcelIds": ["010100000100001000100000"],
  "states": ["NC", "NY"],
  "maxRecords": 200
}
```

Example — sample a state without spending on a lookup list:

```json
{ "bulk": true, "bulkCount": 100, "states": ["NC"] }
```

### Output

Two row shapes share the dataset. Parcel rows are one per parcel, identical across all 13 states; the
free `owner_portfolio` row described below is the only other `rowType`. Filter on `rowType` if you feed
the dataset straight into a pipeline.

| Group | Fields |
|---|---|
| Identity | `state`, `countyName`, `countyFips`, `jurisdiction`, `parcelId`, `parcelIdType` |
| Owner | `ownerName`, `ownerName2`, `ownerType` |
| Property address | `situsAddress` (`street1`, `street2`, `city`, `state`, `zip`) and `ownerMailingAddress` |
| Valuation | `landValue`, `improvementValue`, `totalValue`, `assessedValue`, `marketValue`, `valuationType`, `taxYear` |
| Physical | `acreage`, `buildingSqFt`, `yearBuilt`, `landUseCode`, `landUse` |
| Sale | `lastSaleDate`, `lastSalePrice` |
| Provenance | `source`, `sourceUrl`, `lookupType`, `scrapedAt`, `raw` |
| Honesty | `completeness`, `omitted` |

#### The free `owner_portfolio` row

A list of parcels does not tell you whether you found a landlord or a resident. So every owner search
also emits one summary row of `rowType: "owner_portfolio"`, and that row is **never charged**:

```json
{
  "rowType": "owner_portfolio",
  "ownerQuery": "GLOVER FARMS OF CAROLINA LLC",
  "state": "NC",
  "parcelCountReturned": 10,
  "totalMatches": 16,
  "truncated": true,
  "counties": { "Northampton": 10 },
  "countiesCount": 1,
  "ownerNames": ["GLOVER FARMS OF CAROLINA LLC"],
  "valueTotal": 505779,
  "valueRecords": 10,
  "valueBasis": ["totalValue"],
  "lastSalePriceTotal": null,
  "lastSalePriceRecords": 0,
  "acreageTotal": 1170.55,
  "acreageRecords": 10,
  "absenteeCount": 0,
  "absenteeComparableRecords": 10,
  "totalsScope": "all_returned_records",
  "note": null
}
```

Three things make it honest rather than decorative. Every total carries the number of records that
actually contributed to it, and `totalsScope` drops to `records_that_publish_the_field` the moment the
state does not fill that field on every row — so a portfolio total is never silently divided by the
wrong denominator. `totalMatches` comes from the layer's own `returnCountOnly` count on the same
`where` clause, so you can see how much of the portfolio you were truncated out of. And `absenteeCount`
only counts a parcel when the record publishes both the mailing state and the situs state; if it does
not, the count is `null` with a `note` explaining why, because "0 absentee owners" and "I cannot tell"
are different answers.

`valueTotal` follows the state, not a single field: it sums the best valuation each record publishes —
`assessedValue` first, then `marketValue`, then `totalValue` — and `valueBasis` names which one it used.
That is why North Carolina, which publishes only total value, still returns a portfolio figure instead
of `null`.

#### States are inferred from the addresses you give

Leave `states` empty and the actor reads the state out of each address, so a Florida address queries
Florida instead of sweeping all 13 states. It understands `Lakeland, FL 33813`, `WI 546428226` with a
glued ZIP+4, and the spelled-out `Ohio`. When every address resolves, the run narrows to those states
and says so in the log; when only some do, it warns and queries everything rather than silently
dropping the addresses it could not read.

A `SUMMARY` record lands in the key-value store with a per-state breakdown: the coverage statement,
the layer's live row count and drift since it was probed, lookup hits and misses, bulk-slice stats,
`fieldAudit` (which mapped columns the layer actually replied with and which were missing) and
`omissions` (for each null field, how many records lacked it and why). If a source changes its schema
under you, `fieldAudit` is where you see it, in the run where it happened.

### How matching behaves

- **Owner** — `LIKE '%value%'` on the owner column. The column holds the name as the county recorded
  it, so try the surname first, then the full entity name.
- **Address** — `LIKE` on the situs street line with a street-only fallback, because layers store the
  county's own formatting and a full address with city and ZIP often fails to match it.
- **Parcel** — exact match, tried three times: verbatim, compact, compact without dashes.
- **Deduplication** happens before billing, so overlapping lookups never charge twice for the same
  parcel. A lookup that matches nothing costs nothing.

### What it is not

- **Not a nationwide scraper.** Thirteen measured states out of fifty. The registry is data, so adding
  a state means adding an entry — but each entry needs a real probe first, and ten candidates were
  probed and rejected because their layers refuse queries or lack owner and address columns.
- **Not a deeds or liens database.** This is the assessor's roll: ownership, value, physical
  description. Transfers appear only where the source publishes them — you get the **last** sale,
  not a sale history, because the layers carry a current snapshot rather than a transaction ledger.
- **Not a uniform field set.** Four states publish the tax year, five publish a sale date, two publish
  market value. The table above is the contract; a field absent from it is absent from every row of
  that state, with the reason recorded in `omitted`.
- **Not a tax-bill calculator.** `taxYear` tells you which assessment year the value belongs to. The
  millage rate is set by each jurisdiction separately and is not in these layers.
- **Not a guarantee of a situs address in every county.** Address completeness is county-dependent and
  it was measured, not assumed: in North Carolina only 25 of 100 counties publish a situs city and 90
  of 100 publish a situs street.
- **Not a source of exact coordinates.** Geometry is not returned; the parcel number and county FIPS
  join to any public parcel geometry you already have.
- **Not free of the source's own lag.** These are annual assessment rolls. A sale recorded last month
  is not in them yet.

### Cost and speed

**$5 per 1 000 records** — $0.005 per record, and the Store adds its 20 % margin, so you pay
$6 per 1 000. Plus one `apify-actor-start` event per run at $0.00005. You are billed per parcel
record **pushed to the dataset**, not per request and not per lookup, and `maxRecords` is therefore a
real spend cap. The `owner_portfolio` summary row is free, and so is every lookup that matches
nothing — a run that finds no parcels costs only the start event. `chargePerRecord: false` disables
billing entirely.

Most layers answer a query in about 2 seconds. New York takes 6–8 seconds, which is why the timeout
defaults to 45. Concurrency defaults to 2 because the services are public and unauthenticated, and
hammering them is how you get throttled.

### Keywords this actor is built for

property assessment data scraper · property tax records by owner name · county assessor assessed value
lookup · US parcel data with sale price · land and improvement value data · property owner mailing
address list · absentee owner list · acreage and year built data · real estate lead generation by
owner · situs address and parcel number search.

### Frequently asked

**Does it need a proxy?** No. These are public ArcGIS and REST services, and the actor talks to them
directly — which is also why it is fast and why no proxy cost is baked into the price.

**What happens to states whose layer is broken?** They are rejected at probe time and recorded with
the exact error. Asking for one is a run error that names the measurement, so you never mistake "the
source is dead" for "there is no such owner".

**Can I get the raw columns?** Yes — set `includeRaw: true` and each record carries the untouched
source attributes under `raw`, alongside the normalised fields.

**Do I get a tax history or a sale history?** No, and neither does a scraper that claims to: these
layers publish the **current** roll — the latest assessed value, the latest sale — not a yearly
ledger. What you get instead is the year the value applies to (`taxYear`, where the source publishes
it), so you can tell a 2023 assessment from a 2025 one, and `omitted` tells you when a state does not
say.

**How do I find absentee owners?** Search the owner name across a state and read `absenteeCount` on
the free portfolio row: it counts parcels whose recorded mailing state differs from the parcel's own
state. It is `null` — not `0` — where the source publishes no mailing state, because a missing column
is not evidence of an owner who lives on site.

# Actor input Schema

## `ownerNames` (type: `array`):

Owner-name search, one name per row. Partial matches are allowed — "SILVER PINES" finds "SILVER PINES PROPERTIES LLC". The source columns hold the name as the county recorded it, so try the surname first, then the full entity name.

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

Situs (property) address search, one address per row. A partial street with no city works because the fallback matches the street line alone: "609 MAIN ST" is a better input than "609 Main Street, Raleigh, NC 27601". When you leave States empty and every address ends in a state ("... Lakeland, FL 33813"), that state is used and the other twelve are not queried — the run summary reports which states it picked.

## `parcelIds` (type: `array`):

Parcel number as the county writes it. Punctuation and spacing are handled: 1234-56-789, 123456789 and 1234 56 789 are all tried. New York wants the PRINT_KEY value (SWIS plus print key); every other state takes the parcel number as its own layer publishes it. Check the run summary if a parcel is not found — it says which column each state searches.

## `states` (type: `array`):

Which states to query. Leave empty to take the state from the addresses when all of them name one, and otherwise to query every state that works. Thirteen states serve property records; each one was probed live and the coverage shown is the measured one, not the advertised one. Texas and nine other states were measured and their layers refuse queries or lack owner and address columns, so asking for one of them is an error rather than an empty result.

## `bulk` (type: `boolean`):

Ignore the lookup lists and instead sample rows directly from the layer. Useful to inspect what a state publishes before spending money on a lookup list. The summary reports the layer's total row count and states plainly that the sample is a sample.

## `bulkCount` (type: `integer`):

How many rows to sample per state when Bulk sample is on. The layer's own maximum is respected; asking for more than it returns is reported as truncated, never silently.

## `maxRecords` (type: `integer`):

Hard cap for the whole run, across all states and all lookups. You are charged per record pushed, so this is also your cost cap. Maximum 1000.

## `maxRecordsPerLookup` (type: `integer`):

How many parcels one owner name or one address may return. An owner name like "SMITH" can match hundreds of parcels; this stops one lookup from consuming the whole run's budget.

## `ownerPortfolio` (type: `boolean`):

When on, every owner search also pushes one free summary row: how many parcels came back, how many counties, the assessed and market value totals with the number of records behind each total, the acreage, and how many parcels are absentee (the owner's mailing state differs from the parcel state). This row is never charged. On by default because a list of parcels does not tell you whether you found a landlord or a resident.

## `includeRaw` (type: `boolean`):

Add the untouched layer attributes to each record under `raw`. Useful when a column you need is not in the mapped set yet. Off by default to keep the dataset light.

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

How many lookups run in parallel. The layers are public and unauthenticated; 2 is polite and fast enough. Raising it to 8 may get you throttled by the source.

## `requestTimeoutSecs` (type: `integer`):

Per-request timeout. New York's layer answers a lookup in 6–8 seconds from the platform, so do not set this below 20.

## `runBudgetSecs` (type: `integer`):

How long this run may take before it stops and returns what it has. Leave it empty (recommended) and the run uses the whole timeout you set for it, so asking for every state is not cut short. Set a number only to stop earlier. Stopping early is not a failure: the summary lists the states it did not reach under `statesSkippedForBudget`, and you can re-run for them.

## `chargePerRecord` (type: `boolean`):

Emits one billing event per distinct record pushed to the dataset. Missed lookups are never charged. Turn off only for debugging.

## Actor input object example

```json
{
  "ownerNames": [
    "SILVER PINES PROPERTIES LLC"
  ],
  "addresses": [
    "105 E MAIN ST"
  ],
  "states": [],
  "bulk": false,
  "bulkCount": 50,
  "maxRecords": 50,
  "maxRecordsPerLookup": 10,
  "ownerPortfolio": true,
  "includeRaw": false,
  "maxConcurrency": 2,
  "requestTimeoutSecs": 45,
  "runBudgetSecs": 205,
  "chargePerRecord": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

One row per parcel. Every field is always present; values the source cannot provide are null and are also listed in `omitted` with a reason, so a blank never reads as 'this parcel never sold'. See the Properties tab for the full table.

## `summary` (type: `string`):

Per-state coverage statements, per-state lookup counters (hits, misses, errors), the live row count of each layer as measured during the run, which fields each state could not provide, the states that were measured and deliberately not used, and how many charge events were emitted.

# 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 = {
    "ownerNames": [
        "SILVER PINES PROPERTIES LLC"
    ],
    "addresses": [
        "105 E MAIN ST"
    ],
    "runBudgetSecs": 205
};

// Run the Actor and wait for it to finish
const run = await client.actor("ai-lead-gen-tools/united-states-property-owner-address-parcel-records-scraper").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 = {
    "ownerNames": ["SILVER PINES PROPERTIES LLC"],
    "addresses": ["105 E MAIN ST"],
    "runBudgetSecs": 205,
}

# Run the Actor and wait for it to finish
run = client.actor("ai-lead-gen-tools/united-states-property-owner-address-parcel-records-scraper").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 '{
  "ownerNames": [
    "SILVER PINES PROPERTIES LLC"
  ],
  "addresses": [
    "105 E MAIN ST"
  ],
  "runBudgetSecs": 205
}' |
apify call ai-lead-gen-tools/united-states-property-owner-address-parcel-records-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ai-lead-gen-tools/united-states-property-owner-address-parcel-records-scraper"
        }
    }
}
```

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/puf9gKItF5O42xCxq/builds/JIfaODtRzKTy2mzDI/openapi.json
