# US Parcels - Multi-State Parcel & Property Data (`j0401/us-parcels`) Actor

Harmonised multi-state US parcel register (15 states - 34.3M parcels) in one schema: parcel id, owner and mailing address, situs address, land / improvement / assessed values, acreage, year built, last sale and county. Filter by state, owner, address, ZIP, county, class or value.

- **URL**: https://apify.com/j0401/us-parcels.md
- **Developed by:** [Wenhao Yang](https://apify.com/j0401) (community)
- **Categories:** Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / 1,000 us parcel records

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

> **Nevada source outage (2026-10-18):** the Nevada host (`arcgis.water.nv.gov`) is currently unreachable - HTTP 502 from independent networks and repeated read timeouts from Apify. Requests with `state: "NV"` fail with a clear source error until the host returns; the other fourteen states are unaffected. This is a source-side outage, not a code problem - no action is needed on your side, and the notice comes down when the host recovers.

## US Parcels - Multi-State Parcel & Property Data

### Low cost

**From $0.00005 per record, down to $0.00003 at Gold** - pay per record delivered, and nothing for the query. Fifteen states, 34.3 million parcels, one schema, billed by the parcel. One run delivers up to 10,000 parcels; narrow by owner, address, ZIP, county, class or value to reach the rest of the register.

### What you get

One row per source feature (a few layers carry a parcel on more than one row), with the same field names no matter which state it came from - the Wisconsin statewide parcel convention, used verbatim so a pipeline written against one state's parcel data reads the others unchanged.

| Field group | What it holds |
|---|---|
| identity | `PARCELID`, `TAXPARCELID`, `TAXROLLYEAR` |
| owner | `OWNERNME1`, `OWNERNME2`, and the owner's mailing address (`PSTLADRESS` / `PSTLCITY` / `PSTLSTATE` / `PSTLZIP`) |
| situs | `SITEADRESS`, `ADDNUM`, `STREETNAME`, `STREETTYPE`, `UNITID`, `PLACENAME`, `ZIPCODE` |
| value | `CNTASSDVALUE` (assessed total), `LNDVALUE`, `IMPVALUE`, `ESTFMKVALUE` (appraised / estimated market, where the state publishes it) |
| tax | `NETPRPTA`, `GRSPRPTA` where the state publishes a tax figure |
| class | `PROPCLASS`, `SCHOOLDIST`, `SCHOOLDISTNO` |
| land | `ACREAGE`, `LEGALDESC` |
| sale | `LASTSALEDATE`, `LASTSALEPRICE` where the state publishes them |
| trace | `STATEID`, `COUNTY`, `COUNTYFIPS`, `SOURCEURL` (the register's own page for that parcel, where one exists), and the source register + its last-updated stamp where the source keeps one - West Virginia's and Hawaii's layers carry no date of any kind, so their stamp is empty rather than borrowed from an unrelated column |

Every record carries the full key set. A field a state does not publish is empty, never absent - so a consumer never has to branch on which state it is reading.

### Supported states

| State | Parcels | Owner | Situs address | Value | Year built | Last sale |
|---|---|---|---|---|---|---|
| **MA** Massachusetts | 2.56M | yes (99%) | yes | assessed, land, building | yes | yes |
| **AR** Arkansas | 2.15M | yes | yes | assessed, land, improvement | - | - |
| **CO** Colorado | 2.60M | yes (86%) | yes | assessed + appraised | - | yes |
| **NJ** New Jersey | 3.48M | **no** | yes | assessed, land, improvement | yes | price only |
| **WV** West Virginia | 1.39M | yes (99%) | yes | **no** | - | - |
| **NV** Nevada | 1.39M | **no** | **no** | **no** | - | - |
| **OH** Ohio | 6.31M | **no** | yes | **no** | - | - |
| **NC** North Carolina | 5.94M | yes (99%) | yes | assessed, land, improvement | yes | date |
| **WI** Wisconsin | 3.57M | yes (98%) | yes | assessed, market, property tax | - | - |
| **UT** Utah | 1.60M | **no** | yes | **no** (owner class only) | - | - |
| **NE** Nebraska | 1.15M | **no** | yes | assessed, land, improvement | - | price only |
| **MT** Montana | 0.92M | yes (96%) | yes | total, land, building | - | - |
| **AK** Alaska | 0.42M | yes (86%) | **no** | total, land, building | - | - |
| **HI** Hawaii | 0.38M | **no** | **no** | **no** | - | - |
| **WY** Wyoming | 0.37M | yes (89%) | yes | assessed + market | - | - |

34.3M parcels in total. Six of the fifteen - Nevada, New Jersey, Ohio, Utah, Nebraska and Hawaii - publish no owner, no valuation, or neither, but hand back `SOURCEURL`, a deep link to the county's own record page. For those registers that link is the route to what the bulk layer withholds, with one caveat: Nebraska's layer carries the link on only about a quarter of its rows. Hawaii's identifier is the tax map key; Nebraska's assessed figures come from a rolling CAMA extract; Wyoming's is the 2026 tax roll.

This is **not** a nationwide dataset and there is no all-50-state rollup. These are the states whose own public cadastral services publish a usable statewide layer; each is queried directly from its own service.

States were also ruled out where the source itself does not support the claim. Iowa's statewide layer has not been touched since 2024 and carries nine columns; Idaho's public parcel layer was last updated in April 2025; Delaware's publishes a parcel id, an acreage, a county and an update date, and nothing else. They are not listed above rather than listed with a footnote.

### Modes

- **parcels** (default) - individual parcels, up to `maxResults` per run (default 50, maximum 10,000)
- **aggregate** - one count row per group: by county, property class, or Massachusetts town id

Filter by state, parcel id, owner, situs address, city, ZIP, county, property class, year built, or assessed-value bounds.

### Example inputs

**One parcel by id** - `parcelId` is an exact identifier match, case-insensitive.

```json
{ "state": "CO", "parcelId": "0171902304020" }
```

**Everything one owner holds in a county**

```json
{ "state": "CO", "county": "Adams", "owner": "FOWLER", "maxResults": 25 }
```

**New Jersey parcels on a street** - note NJ has no owner name to search.

```json
{ "state": "NJ", "city": "CHERRY HILL", "address": "CHURCH RD", "maxResults": 25 }
```

**Ohio parcels in a county** - Ohio publishes no owner, but it does publish both addresses.

```json
{ "state": "OH", "county": "Franklin", "maxResults": 25 }
```

**North Carolina by county**

```json
{ "state": "NC", "county": "Wake", "maxResults": 25 }
```

**Wisconsin by city**

```json
{ "state": "WI", "city": "MADISON", "maxResults": 25 }
```

**How a state's parcels break down by county**

```json
{ "state": "AR", "aggregate": true, "groupBy": "county" }
```

**West Virginia by county** - the county is given by name; the code it maps to is resolved for you.

```json
{ "state": "WV", "county": "Logan", "maxResults": 25 }
```

### What this is - and what it is not

These are **assessor / cadastral registers**: what each parcel is, where it is, who it is registered to, and what it is assessed at.

**Assessed values are not comparable across states** - and nothing here pretends otherwise. "Assessed" is a legal term that each state defines for itself, so the figure is passed through exactly as published, and the per-state source column is documented with the field mapping. The states are not even on the same kind of scale as each other: Colorado publishes a statutory assessment running around 5-7% of the same parcel's appraised total, and Wyoming around 9.5%; Arkansas' assessed-total column carries a market-basis figure, while the state's own (smaller) statutory assessment lives in a separate column; Massachusetts assesses close to market; New Jersey's is land plus improvement; and West Virginia, Nevada, Ohio, Utah and Hawaii publish no valuation figure at all. Whatever a state publishes is delivered as-is, side by side, never merged into one "value" and never rescaled to look alike. Montana, Alaska and North Carolina each publish a single total whose basis the layer itself does not spell out - North Carolina's rows do carry the state's own type label, which reads "Assessed" - so those figures too are passed through exactly as published and never relabelled as market value.

**Coverage is uneven by design of the sources, not by sampling.** New Jersey publishes an owner column that is empty on every one of its 3.48 million rows - so NJ returns no owner name at all rather than a wrong one. Ohio, Utah, Nebraska and Hawaii publish no owner column; Ohio, Utah, Hawaii, Nevada and West Virginia publish no valuation; Alaska publishes no address of any kind; Hawaii publishes no date of any kind. Arkansas has no sale or year-built columns. Massachusetts' layer carries no county column, so county filtering and grouping are unavailable there. Where a state lacks a field, the request is declined with an explanation instead of being silently dropped. Ohio's layer also contains placeholder rows that carry no parcel identifier at all - those are not delivered, so you are never billed for an empty record, and the run log reports how many were skipped. Other layers also carry rows with no parcel identifier (Massachusetts 3.7%, Montana 3.6%, Utah 1.5%, and smaller shares elsewhere); those rows still carry an owner, address or value and are delivered.

**Parcel ids are state-scoped - and in Nevada, county-scoped.** `0409_278.01_1` is meaningful in New Jersey and nowhere else, and the same real parcel carries different ids in different registers. Nevada goes further: its assessor number is unique only within a county, so the identical id recurs across counties and an id lookup there returns each county's parcel separately - `COUNTY` is what tells them apart. `STATEID` is on every record so the scope is never implied.

### Why this is hard

Putting fifteen states' parcel registers behind one schema is not fifteen retrievals; it is fifteen sets of things that quietly break a shared shape.

**The same concept has a different column name in every state.** Owner is `OWNER1`, `ownername`, `owner`, `ownname`, `OWNERNME1`, `OwnerName`, and in New Jersey a column that exists and is populated by nothing. Situs address is `SITE_ADDR`, `adrlabel`, `situsAdd`, `PROP_LOC`, `SitusAddressAll`, `siteadd`. Land value is `LAND_VAL`, `landvalue`, `landval`, `TotalLandValue`. The harmonisation is the product; the retrieval is the easy part.

**A column can be present, non-null, and empty.** New Jersey's owner column reports as populated if you ask the service how many rows are not null - it is not null on all 3,481,240 rows - and is the empty string on all of them. The check has to be for emptiness, not for null, and it has to run against the whole corpus rather than a sampled page, or the gap is invisible until a customer reads an owner field and finds nothing.

**And the whole corpus is the only honest sample.** Ohio's first hundred thousand object ids carry a situs address on 4% of rows; across the layer it is 86%. The head of that register is one county whose data is sparse, and any check that reads a slice of it would conclude the column was dead.

**A numeric value can be stored as text.** Colorado delivers its sale price and both value columns as strings. Comparing them to a number is either rejected outright or, worse, accepted and compared character by character - where `">= 500000"` matches a handful of rows and skips every price with more digits. Colorado therefore offers no value filter at all, rather than one that quietly returns the wrong parcels.

**A numeric column can also refuse the emptiness test.** Ask a service whether a number is not the empty string and it rejects the query as a type error. The emptiness check has to follow the column's type - text compared to empty, a typed column tested for null - or the guard fails on a healthy source every day.

**One column can hold two different units.** Massachusetts stores lot size in acres on most of its rows and in square feet on 273,148 others - and which one it is is decided by a neighbouring unit column, not by the size of the number. Read without that column and a 1.5-acre lot is published as 67,387 acres. The unit is carried and the value converted, so `ACREAGE` means acres on every row.

**And a sentinel can look like a real value.** Arkansas codes an unknown ZIP as `0` on 53% of its rows. Nebraska dates its sales with values in the year 2052. North Carolina stamps some of its dates `9999-12-31`, and the counties there that do not maintain a sale date stamp `2001-01-01` instead - 42% of one county's rows - so that value is blanked rather than published as a transfer. A zero that reaches the output unchanged reads as data - a ZIP code of 0 - rather than as an absence. Places where zero means "not recorded" rather than a real zero are blanked, not passed through, so an empty field and a genuine zero are never confused; a date that cannot be true is left out of the field set entirely rather than published.

**A county can be published as a number.** West Virginia's layer carries its county as a bare two-digit code with no legend anywhere on the service - `20`, not `Kanawha`. A county-to-code table was rebuilt and then checked against the data rather than trusted from memory: thirteen codes were sampled and every one landed in the expected county, from 01 Barbour to 55 Wyoming, then all fifty-five were checked against the service's own district layer. The names are what you filter and group by; the codes never surface. Nebraska is the case where that could not be done safely: its county number does not follow the state's alphabetical county index at all, so rather than publish a wrong name, no county filter is offered there - only a group under the number the source actually carries.

**The same field name can be two different things.** Hawaii's identifier is a tax map key, Montana's `CityStateZip` is one combined string where every other state splits city, state and ZIP into three, and Montana's owner address is spread across three lines of which only the first is carried. New Jersey's deed date mixes two encodings with no way to tell them apart, so it is not carried at all rather than carried as a coin flip.

**Different services spell the same thing differently.** Four of the fifteen do not call their object-id column `OBJECTID` - three spell it in lowercase and one calls it `FID`. Ask for the uppercase spelling and the service answers with an error rather than a page, so each state declares its own. One caps a response at 1,000 features, half of most and a fifth of North Carolina's and Nevada's 5,000.

**Services differ in what they will even do.** Massachusetts is served from a host that refuses to group by a text column - the query is answered with an error after a minute rather than a result - so town id, an integer, is the only dimension offered there. Ohio's service is the extreme: a whole-corpus count of one column comes back in a second when it is cached and not at all when it is not (three consecutive attempts past 33s, then the identical query in 1.0s minutes later; a cold scan is aborted by the server itself at 56s). Ohio is therefore the one state without a per-column health check - it is protected by its row count and its edit stamp instead, and that gap is stated here rather than hidden. No coverage number anywhere in this actor is ever taken from a slice of rows or from a batch of parallel scans. Ohio's parcel-id lookup therefore requires `county` alongside `parcelId` (the county predicate makes it answer in seconds). A rare-value text search there can still be rejected by the state's service at its ~56-second scan limit even when a county is supplied - that is the source's own limit, not a query error - so use a less selective text filter, or look the parcel up by `parcelId` together with its `county`.

**And some states have no freshness signal to read.** West Virginia's and Hawaii's layers carry no date column and no edit stamp at all. Their stamp is reported empty rather than filled from an unrelated column; what still guards them is the whole-corpus count. North Carolina is the awkward middle: it publishes three date columns, of which one stops at a 9999 sentinel, one is populated on 14% of rows and reads back as null at the top of a sort, and only the third is filled on every row.

### Output

Records are delivered as dataset items - one JSON object per parcel, or one object per group in aggregate mode. Fields a given state does not publish are present and empty, so the shape is constant across states and modes.

# Actor input Schema

## `state` (type: `string`):

Which state's parcel register to query. MA = Massachusetts (2.56M) - owner, year built, values. AR = Arkansas (2.15M) - owner, no sale or year built. CO = Colorado (2.60M) - owner and appraised value; its value columns are text, so value filters are unavailable. NJ = New Jersey (3.48M) - NO owner name (the source's owner column is empty on every row). WV = West Virginia (1.39M) - owner and mailing address, acreage, legal description, no values. NV = Nevada (1.39M) - id, city, acreage, county and a county page link only. OH = Ohio (6.31M) - mailing and situs address, land-use class and a county auditor page link; NO owner and NO valuation. NC = North Carolina (5.94M) - owner, mailing and situs address, values, year built, last sale. WI = Wisconsin (3.57M) - the state whose naming standard this schema uses: owner, full address components, assessed and market values, property tax. UT = Utah (1.60M) - address, city, ZIP, county, an ownership class (private / federal / state / tribal) and a county page link; NO owner name and NO valuation. NE = Nebraska (1.15M) - situs address, acreage, legal description, assessed values and a county page link; NO owner, and county appears only as an internal code. MT = Montana (0.92M) - owner, owner-address line, situs address, values, legal description. AK = Alaska (0.42M) - owner and values, but NO address of any kind. HI = Hawaii (0.38M) - tax map key, county, acreage and a county record page link; NO owner, NO address, NO valuation, and no date of any kind. WY = Wyoming (0.37M) - owner and mailing address, assessed and market values, acreage, legal description, from the 2026 tax roll.

## `parcelId` (type: `string`):

Exact parcel identifier, case-insensitive. E.g. 0171902304020 (CO), 66-00000100 (MA), 001-00352-008 (AR), 0409_278.01_1 (NJ), 1028143 (NV), 1300800035304013 (OH, with county), 555400411879 (NC), 008002310010 (WI), 153 (UT), 880035497 (NE), 37500402101020000 (MT), 14718015 (AK), 389014053 (HI) or 12700620001300 (WY). An exact match rather than a substring, because several states' ids contain underscores. Ohio needs `county` alongside `parcelId` (StateParcelID alone times out on the state's own service). Nevada ids are unique only within a county, so the same id there can return several parcels across counties - look at COUNTY to tell them apart.

## `owner` (type: `string`):

Owner-name substring, case-insensitive, e.g. SMITH or HOLDINGS. Available for MA, AR, CO, WV, NC, WI, MT, AK and WY. Not for NJ (its owner column is empty on every row), NV, OH, UT, NE or HI (those layers carry no owner column at all) - a request there is rejected rather than silently ignored.

## `address` (type: `string`):

Property (situs) address substring, case-insensitive, e.g. MAIN ST. Not available for NV (city only, no street), AK (no address of any kind) or HI (tax map key only) - rejected rather than silently ignored.

## `city` (type: `string`):

City / town / municipality substring, case-insensitive, e.g. NATICK (MA) or CHERRY HILL (NJ). Not available for WV, OH, AK, HI or WY. For MT this matches against the combined "city, ST zip" string the state publishes.

## `zip` (type: `string`):

Situs ZIP prefix, e.g. 017 or 80233. Not available for WV, NV, OH, MT, AK, HI or WY. Note the Arkansas ZIP column is unpopulated on about half its rows, so a ZIP filter returns a subset there.

## `county` (type: `string`):

County substring, case-insensitive, e.g. ADAMS (CO) or CAMDEN (NJ). Not available for MA (its layer carries no county column) or NE (which identifies counties only by an internal number that does not follow the state's county index). Alaska's equivalent of a county is its borough / census area.

## `propertyClass` (type: `string`):

Property / land-use class substring, case-insensitive. The vocabulary differs by state, e.g. Residential (CO), SINGLE FAMILY (MA uses USE_DESC labels), RI or PS (AR parcel types), 2 or 3A (NJ class codes), Improved Property (MT), or the free-text use labels Alaska publishes. For UT this field is the ownership class (Private / Federal / State / Tribal) rather than a land use. Not available for WV, NV, HI or WY.

## `minValue` (type: `integer`):

Only parcels whose assessed total is at or above this amount. Available for MA, AR, NJ, NC, WI, NE, MT, AK and WY. Not for CO (its value columns are text, where a numeric bound would compare lexicographically and silently return the wrong rows) or WV, NV, OH, UT and HI (those layers carry no value column at all) - rejected rather than silently ignored. A bound of 0 means no bound.

## `maxValue` (type: `integer`):

Only parcels whose assessed total is at or below this amount. Available for the same states as minValue - MA, AR, NJ, NC, WI, NE, MT, AK and WY - and rejected with an explanation everywhere else (CO publishes its value columns as text; WV, NV, OH, UT and HI publish no value column).

## `yearBuilt` (type: `string`):

Exact year the primary structure was built, e.g. 1955. Available for MA, NJ and NC only.

## `aggregate` (type: `boolean`):

When on, returns one summary record per group (see groupBy) with a count, instead of individual parcels.

## `groupBy` (type: `string`):

Dimension to aggregate over. county = parcel count per county (every state except MA, whose layer carries no county column; for NE the key is the source's internal county number, not a name). propClass = per property class (AR, CO, NJ, OH, NC, WI, UT, MT, AK - MA's class column is text and its host rejects a text grouping). townId = per Massachusetts town id (MA only). Blank = the state's first available dimension, so an aggregate run works whichever state is selected.

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

Cap the number of parcel records pushed (0 = up to ~10k per run; each record is metered individually, so there is no per-run charge cap). Does not apply in aggregate mode, which returns every group of the chosen dimension.

## Actor input object example

```json
{
  "state": "MA",
  "parcelId": "",
  "owner": "",
  "address": "",
  "city": "",
  "zip": "",
  "county": "",
  "propertyClass": "",
  "yearBuilt": "",
  "aggregate": false,
  "groupBy": "",
  "maxResults": 50
}
```

# Actor output Schema

## `recordsUrl` (type: `string`):

Harmonised parcel records or aggregates - as JSON

## `datasetUrl` (type: `string`):

No description

## `runUrl` (type: `string`):

No description

# 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("j0401/us-parcels").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("j0401/us-parcels").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 j0401/us-parcels --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,j0401/us-parcels"
        }
    }
}
```

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/keLvxfPoMycyIX4YV/builds/e6NIx1WPnhBm7jbkv/openapi.json
