# County Records & Property Owner Phone Lookup (Miami, NYC, LA) (`nice_dev/us-county-property-records-scraper`) Actor

Property owner lookup from official county records in Miami-Dade, New York City and Los Angeles: owner, mailing address, values, homestead, sales history, NYC deeds and mortgages, plus owner phones and e-mails (option). Search by address, owner name or parcel, or list a whole county with filters.

- **URL**: https://apify.com/nice_dev/us-county-property-records-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Real estate, Lead generation, MCP servers
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.32 / 1,000 property 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

### 🏠 What is US County Property Records Scraper?

**US County Property Records Scraper** extracts **official property records** from the county offices of **[Miami-Dade County](https://www.miamidadepa.gov/)** (Florida), **[New York City](https://www.nyc.gov/site/finance/property/property.page)** (the 5 boroughs) and **[Los Angeles County](https://portal.assessor.lacounty.gov/)** (California): **owner, owner's mailing address, market and assessed values, homestead exemption, every recorded sale with buyer, seller and deed reference**, and in New York City the **deeds and mortgages** of each property.

Look up **addresses, owner names or parcel numbers** — or leave them empty to list a **whole county** narrowed by filters: recent sales above a price, companies only, absentee, out-of-state or foreign owners, ZIP codes, property types. Click **Start** and download the records in JSON, CSV or Excel. No login, nothing to set up: **about 20 full records in 40 seconds** (with **Full record** ticked).&#x20;

Need a **property owner lookup with phone and e-mail**? Tick **Add the owner's phones and e-mails**: the owner of record comes from the county, then the Actor finds that person's phones and e-mails — the real owner, even when they live elsewhere.

### 📋 What data can you extract from county property records?

One item per property (a parcel, or a condo unit), 94 fields:

| Category | What you get |
| --- | --- |
| 🏷️ **Property** | parcel number, address and unit, county, borough, coordinates — `02-4210-018-0050` |
| 👤 **Owner** | every owner of record, company / person / government, mailing address with country |
| 🚩 **Owner flags** | absentee owner, out-of-state owner, foreign owner, primary residence (homestead) |
| 💰 **Values** | market, assessed, taxable, land and building values, several years of history |
| 🤝 **Sales** | last sale date and price, buyer, seller, deed reference, full sales history |
| 🏦 **Deeds and mortgages** | New York City: every deed and mortgage with parties, amounts and lenders |
| 🏗️ **Building** | property type, land use, year built, bedrooms, bathrooms, living area, lot size, stories, units |
| 🏊 **Features** | Miami-Dade: pools, docks, fences and other features the county lists, with year and value |
| 📞 **Owner contacts** (option) | the owner's phones (type, carrier), e-mails, current address, age, relatives, whether the owner passed away — looked up at the property first |
| 🏘️ **Owner's other properties** (option) | every other property of the owner in the same county (Miami-Dade, New York City): parcel, address, value, county link |
| 🚨 **Distress score** (option) | a 0-100 "motivated seller" score with each reason: estate or deceased owner, recent foreclosure deed, absentee or out-of-state owner, long ownership, value far above the last price, vacant land |

Every field, with an example, is listed in the **Output** section below.

Fields read in the **full record** (sales history, several years of values, exemptions, New York City deeds and mortgages, Miami-Dade features) are filled when **Full record** is ticked (off by default: the fields of the county's search or open-data row only, `detailLevel` says which one each record is), charged as one extra event per record (see the pricing below).

### ✅ Why use US County Property Records Scraper?

- 🏛️ **The county's own record**: owners, values and sales as the county publishes them — not an estimate.
- 🗺️ **A whole county, filtered**: every sale above $1M in the last 3 months, every company-owned condo in a ZIP code, every property whose owner lives abroad — without a list of addresses to start from.
- 🏙️ **Condo units in New York City**: the owner of each apartment, with the buyer's mailing address from the last deed.
- 🧾 **Full sales history**: buyer, seller, price and deed reference of every recorded sale; New York City mortgages with lenders and amounts.
- 📞 **Owner phones and e-mails in the same run** (option): each match says how the person was found, so a namesake is never sold as the owner.
- 🏘️ **The owner's whole portfolio** (option): the other properties of each owner in the county — a namesake's property is never listed.
- 🚨 **A distress score you can check** (option): every point comes with the county's value that set it off, and the factors a record could not be checked for are listed — no black box, no AI guess.
- 🔔 **Monitoring built in**: tick **Only new records**, schedule the Actor, and each run returns (and charges) only the properties it has never delivered before.
- 🔌 API, scheduling, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape county property records

1. Create a free Apify account.
2. Open **US County Property Records Scraper** and pick the **Counties** (Miami-Dade by default).
3. Type **Addresses**, **Owner names** or **Parcel numbers** — or leave the three lists empty to list the whole county, then set the **Filters** (sold after, minimum price, owner type…).
4. Set **Max records** (100 by default, 0 = no limit) — and **Max records per search** when you run several searches — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape county property records?

This Actor uses **pay per event** pricing — see the **Pricing** tab. Price per 1,000, by Apify plan (Platinum and Diamond pay the Gold price):

| What you pay for | Event | Free | Bronze | Silver | Gold |
| --- | --- | --- | --- | --- | --- |
| Property record saved (the county's search row only, by default) | `apify-default-dataset-item` | **$0.35** | $0.34 | $0.33 | **$0.32** |
| **Full record** (option, off by default): a property delivered with the county's full record read, on top of the property price | `full-record` | **$0.59** | $0.56 | $0.52 | **$0.49** |
| **Add the owner's phones and e-mails**: a property delivered with a phone or an e-mail of its owner — nothing found, no charge | `owner-contact` | **$12.99** | $12.98 | $12.97 | **$12.96** |
| A record dropped by one of the Actor's own filters | `filter-check` | $0.065 | $0.06 | $0.055 | $0.05 |
| A full record read, then dropped by a filter that needs it | `detail-filter-check` | $0.59 | $0.58 | $0.57 | $0.56 |
| Run start | `apify-actor-start` | $0.0013 per GB of run memory (one start at the default 512 MB, $0.0026 at 2 GB) | | | |

Examples (Free plan): 1,000 Miami-Dade properties sold in the last 6 months, without their full record: **$0.351**; with their full record: **$0.941**; 100 of them with their full record and the owner's phones and e-mails (about 40 found): about **$0.61**. The full record is charged once per property delivered with it, never for a property saved without it; a lookup with a filter that needs the full record, or New York City's recent sales, reads it anyway and is charged for it. A record you keep never costs a filter fee, and a search that finds nothing is not charged. Platform usage (compute, proxy) is included in the price.&#x20;

### ⚙️ Input

Recent sales above $1M in Miami-Dade:

```json
{
    "counties": ["miami-dade"],
    "soldAfter": "3 months",
    "minSalePrice": 1000000,
    "maxItems": 200
}
```

Look up addresses, owner names and parcel numbers in the three counties:

```json
{
    "counties": ["miami-dade", "new-york-city", "los-angeles"],
    "addresses": ["350 W 50th St Apt 12B, New York, NY 10019", "1000 Main St, Los Angeles, CA 90012"],
    "ownerNames": ["ACME HOLDINGS LLC"],
    "parcelNumbers": ["02-4210-018-0050", "LA:4371-024-013"],
    "maxItemsPerQuery": 50
}
```

Every company-owned condo sold in Manhattan in the last 6 months, owners abroad only, as a weekly monitor:

```json
{
    "counties": ["new-york-city"],
    "boroughs": ["manhattan"],
    "soldAfter": "6 months",
    "propertyTypes": ["condo"],
    "ownerType": "company",
    "foreignOwnersOnly": true,
    "onlyNew": true,
    "stateKey": "manhattan-foreign-buyers"
}
```

| Field | Notes |
| --- | --- |
| `counties` | Miami-Dade, New York City (5 boroughs), Los Angeles. An address that names another county (state, ZIP, city) runs there only. |
| `addresses` | Street address with the unit (`1200 Brickell Bay Dr Unit 3101, Miami, FL 33131`). One record per property found. Only the address typed: a misspelt street, or an address that does not exist, gives no record, never a neighbour's (in New York City, add the borough: `350 5th Ave, Manhattan`). |
| `ownerNames` | Every property a name holds (`SMITH JOHN`, `ACME HOLDINGS LLC`). Not available in Los Angeles (the county publishes no owner names online). |
| `parcelNumbers` | Miami-Dade folio (`02-4210-018-0050`, 9 digits = a whole building), New York City BBL (`NYC:1-01030-1001`), Los Angeles AIN (`LA:4371-024-013`). |
| `maxItems` | Stop after this many records for the whole run (`0` = unlimited). |
| `maxItemsPerQuery` | Cap for EACH search (one lookup in one county, or one whole-county listing); `0` = no cap per search. |
| `includeDetails` | Read the full record of each property (sales history, values by year, exemptions, deeds and mortgages, features); default off. An address, owner or parcel lookup with a filter other than owner type, excluded words or borough reads it anyway. Charged once per property, see the pricing. |
| `includeOwnerContacts` | The owner's phones and e-mails (default off; people only, Miami-Dade and New York City; needs `includeDetails`, 10-60 s per property). Contacts found in public directories (the owner contact source column says which one). Charged by the owner-contact event when found, whichever directory gives it. |
| `includeOwnerPortfolio` | The owner's other properties in the same county, up to 100 (default off; Miami-Dade and New York City, not Los Angeles: no owner names; needs `includeDetails`, 1 to 3 more requests per property). A namesake's property is never listed: a business by its exact name, a person or a trust only at the same address. Priced separately (owner-portfolio event), only when one is found. |
| `includeDistressScore` | A 0-100 "motivated seller" score of each property from the county's own fields, no extra request (default off): owner deceased (with `includeOwnerContacts`), estate or heirs, foreclosure deed in the last 3 years, owner not living there, out-of-state owner, owned 10+ / 20+ years, value 1.5× / 2× the last sale price, vacant land. Each factor comes with its points and the value that set it off; the factors a record could not be checked for are listed. Tax arrears are not read. Los Angeles: 4 factors only (no owner names, Proposition 13 values). Priced separately (distress-score event), only when a factor is found. |
| `sortBy` | Order of a whole-county listing: newest sale, highest sale price, highest value, parcel number. Miami-Dade's highest value is the assessed value; Los Angeles knows the year of the last sale only (both sale orders = most recent year first); New York City without a sale filter lists by parcel number, with one by newest deed. |
| `soldAfter`, `soldBefore` | Last sale between two dates: `2026-01-01`, or a period before now (`30 days`, `3 months`, `1 year`). Los Angeles without the full record: compared on the year. |
| `minSalePrice`, `maxSalePrice`, `minValue`, `maxValue` | Last sale price, current market value (US dollars). |
| `propertyTypes`, `ownerType` | Single-family, condo, multi-family, commercial, industrial, land, other; companies (LLC, Inc., trust…) or people. |
| `absenteeOwnersOnly`, `outOfStateOwnersOnly`, `foreignOwnersOnly` | The owner's mailing address is not the property / is in another state / is abroad. |
| `homesteadOnly`, `excludeHomestead` | Primary residences only, or none (not published in New York City). |
| `zipCodes`, `boroughs` | Only these ZIP codes (`33109`); New York City boroughs. |
| `latitude`, `longitude`, `radiusMiles` | Whole-county listing around a point (`25.7617`, with longitude and radius), Miami-Dade and Los Angeles. |
| `minYearBuilt`, `maxYearBuilt`, `minBedrooms`, `maxBedrooms`, `minBathrooms`, `maxBathrooms` | Year built, bedrooms, full bathrooms (bedrooms and bathrooms not published in New York City). |
| `minLivingAreaSqFt`, `maxLivingAreaSqFt`, `minLotSizeSqFt`, `maxLotSizeSqFt`, `poolOnly` | Living area, lot size (square feet); with a pool (Miami-Dade). |
| `excludeKeywords` | Drop the properties whose owner name contains one of these words (`COUNTY`, `CITY OF`). |
| `onlyNew`, `stateKey`, `resetState` | Monitoring: only the properties never delivered under this memory key; `resetState` forgets the memory. |
| Advanced | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `socrataAppToken` (your free NYC Open Data app token, for very large New York City runs), `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

One record, shortened (one value of each list shown; names, address, phone and e-mail are examples):

```json
{
    "id": "miami-dade-0242100180050",
    "url": "https://apps.miamidadepa.gov/PropertySearch/#/?folio=0242100180050",
    "county": "miami-dade",
    "countyName": "Miami-Dade County, FL",
    "state": "FL",
    "countyFips": "12086",
    "parcelId": "0242100180050",
    "parcelIdFormatted": "02-4210-018-0050",
    "parentParcelId": "0242100180001",
    "propertyAddress": "100 SAMPLE ISLAND DR, UNIT 100, Miami Beach, FL 33109",
    "latitude": 25.7596,
    "longitude": -80.1367,
    "ownerName": "JANE Q SAMPLE",
    "owners": ["JANE Q SAMPLE", "JOHN Q SAMPLE"],
    "ownerType": "individual",
    "ownerMailingAddress": "100 SAMPLE ISLAND DR UNIT 100, MIAMI BEACH, FL 33109, USA",
    "ownerMailingCountry": "USA",
    "absenteeOwner": false,
    "outOfStateOwner": false,
    "foreignOwner": false,
    "homestead": true,
    "exemptions": [{ "name": "Homestead", "value": 25000, "year": 2026 }],
    "propertyType": "condo",
    "yearBuilt": 2016,
    "bedrooms": 3,
    "bathrooms": 3,
    "livingAreaSqFt": 3659,
    "taxYear": 2026,
    "marketValue": 10054142,
    "assessedValue": 5322568,
    "taxableValue": 5271157,
    "valueHistory": [{ "year": 2025, "marketValue": 10054142, "assessedValue": 5182637, "taxableValue": 5131915, "landValue": null, "improvementValue": null }],
    "lastSaleDate": "2016-04-25",
    "lastSaleYear": 2016,
    "lastSalePrice": 6770000,
    "lastSaleBuyer": "JANE Q SAMPLE TRUSTEES",
    "lastSaleSeller": "PDS DEVELOPMENT LLC",
    "lastSaleDocument": "30042-0456",
    "yearsOfOwnership": 10,
    "sales": [{ "date": "2016-04-25", "recordedDate": null, "price": 6770000, "buyers": ["JANE Q SAMPLE TRUSTEES"], "sellers": ["PDS DEVELOPMENT LLC"], "parties": [], "documentType": "Deed", "document": "30042-0456", "documentUrl": null, "qualified": true }],
    "mortgages": [],
    "extraFeatures": [],
    "query": "100 Sample Island Dr Unit 100, Miami Beach, FL 33109",
    "queryType": "address",
    "detailLevel": "full",
    "fieldNotes": [],
    "ownerContactLookup": "found",
    "ownerContactName": "Jane Quinn Sample",
    "ownerContactMatch": "address",
    "ownerContactSource": "fastpeoplesearch",
    "ownerPhone": "(305) 555-0142",
    "ownerPhones": [{ "number": "(305) 555-0142", "e164": "+13055550142", "type": "Wireless", "carrier": "T-Mobile", "firstReported": "March 2019", "isPrimary": true }],
    "ownerEmail": "jsample@example.org",
    "ownerEmails": ["jsample@example.org"],
    "ownerContactAddress": "100 Sample Island Dr, Miami Beach, FL 33109",
    "ownerAge": 58,
    "ownerDeceased": false,
    "ownerDeathDate": null,
    "ownerRelatives": ["John Q Sample"],
    "ownerContactUrl": "https://www.fastpeoplesearch.com/jane-sample_id_G-0000000000000000000",
    "ownerPortfolioLookup": "found",
    "ownerPortfolioCount": 1,
    "ownerPortfolio": [{ "parcelId": "3040320150690", "parcelIdFormatted": "30-4032-015-0690", "propertyAddress": "10375 N KENDALL DR Unit J5, Unincorporated County 33176", "marketValue": null, "assessedValue": 199370, "url": "https://apps.miamidadepa.gov/PropertySearch/#/?folio=3040320150690" }],
    "distressScore": 8,
    "distressLevel": "low",
    "distressFactors": [{ "factor": "longOwnership", "points": 8, "detail": "owned for 10 years, since 2016-04-25" }],
    "distressUnchecked": [],
    "scrapedAt": "2026-09-25T21:30:00.000Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 94 fields

| Fields | What you get |
| --- | --- |
| `id`, `url`, `county`, `countyName`, `state`, `countyFips` | **Property**: `miami-dade-0242100180050`, the county's own page, `miami-dade`, `Miami-Dade County, FL`, `FL`, `12086` |
| `parcelId`, `parcelIdFormatted`, `parentParcelId`, `borough` | folio / BBL / AIN, as the county writes it, the building of a condo unit, New York City borough |
| `propertyAddress`, `streetAddress`, `unit`, `propertyCity`, `propertyZip`, `latitude`, `longitude` | address of the property, coordinates |
| `ownerName`, `owners`, `ownerType` | **Owner**: first owner, every owner, `company` / `government` / `individual` |
| `ownerMailingAddress`, `ownerMailingStreet`, `ownerMailingCity`, `ownerMailingState`, `ownerMailingZip`, `ownerMailingCountry` | mailing address of the owner (New York City: the buyer's address on the last deed) |
| `absenteeOwner`, `ownerOccupied`, `outOfStateOwner`, `foreignOwner`, `homestead`, `exemptions` | **Owner flags**: mailing address vs property, primary residence, exemptions of the year |
| `propertyType`, `propertyUse`, `propertyUseCode`, `zoning`, `legalDescription`, `subdivision` | **Building**: `condo`, the county's land use and code, zoning, legal description, subdivision or neighborhood |
| `yearBuilt`, `bedrooms`, `bathrooms`, `halfBathrooms`, `livingAreaSqFt`, `buildingAreaSqFt`, `units`, `stories` | year built, rooms, areas in square feet, units, floors |
| `lotSizeSqFt`, `lotSizeAcres`, `lotWidthFt`, `lotDepthFt`, `extraFeatures` | lot size and dimensions, Miami-Dade features (pool, dock…) |
| `taxYear`, `marketValue`, `assessedValue`, `taxableValue`, `landValue`, `improvementValue`, `valueHistory` | **Values**: current values in US dollars, and the years before |
| `lastSaleDate`, `lastSaleYear`, `lastSalePrice`, `lastSaleBuyer`, `lastSaleSeller`, `lastSaleDocument`, `yearsOfOwnership` | **Sales**: last recorded sale — what the sold-date and price filters read |
| `sales`, `mortgages` | every recorded sale (date, price, buyers, sellers, parties, deed type and reference, link); New York City mortgages (lenders, amounts) |
| `ownerContactLookup`, `ownerContactName`, `ownerContactMatch`, `ownerContactSource` | **Owner contacts** (option): `found`, `not_found`, `not_a_person`, `no_owner_name`, `skipped`, `error`; the owner as the directory names them; found at the `address`, the `mailing` address, or by `name` (kept only when the property or the mailing address is among the person's known addresses); the directory the contact was read from: `thatsthem`, `fastpeoplesearch` or `cyberbackgroundchecks` |
| `ownerPhone`, `ownerPhones`, `ownerEmail`, `ownerEmails`, `ownerContactAddress`, `ownerAge`, `ownerDeceased`, `ownerDeathDate`, `ownerRelatives`, `ownerContactUrl` | phones (type, carrier and first reported date when the directory gives them: ThatsThem does not), e-mails, current address, age, whether the directory says the person passed away and when (an owner still on the county's roll: an estate — the phones are those listed for the person, often the family's; ThatsThem does not say, the field is then empty), relatives, the directory's page (for ThatsThem, the page of the address the person was read on) |
| `ownerPortfolioLookup`, `ownerPortfolioCount`, `ownerPortfolio` | **Owner's other properties** (option): `found`, `not_found`, `not_covered` (Los Angeles), `no_owner_name`, `government`, `skipped`, `error`; how many; each one's parcel, address, value and county link (up to 100) |
| `distressScore`, `distressLevel`, `distressFactors`, `distressUnchecked` | **Distress score** (option): 0-100; `high` (50+), `medium` (25+), `low`, `none`; each factor found with its points and reason (`owned for 27 years, since 1999-03-02`); the factors this record could not be checked for |
| `query`, `queryType`, `detailLevel`, `fieldNotes`, `sourceUpdatedAt`, `scrapedAt` | the search that found it (`address`, `owner`, `parcel`, `county`), `full` record or `list` row (its price), why a field is empty, date of the county's data, ISO timestamp |

### 💡 Tips

#### How to get more results

Leave **Addresses**, **Owner names** and **Parcel numbers** empty to list a whole county, and use the filters to narrow it: the counties apply most of them themselves, so only the records you want are read. Set `maxItems` to `0` for no limit.

#### How to reduce costs

The price is per record, so the levers are `maxItems`, `maxItemsPerQuery`, the filters and `onlyNew` for recurring runs (you never pay twice for the same property). Leaving `includeDetails` off (the default) makes runs faster and saves the full-record fee of each property.

#### Several searches in one run

Put several addresses, owner names or parcel numbers in the lists and pick several counties: each lookup runs in each county it can belong to (up to 3000 searches per run). A property found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap.

#### Monitoring: only the new records

Tick **Only new records** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the properties already delivered: they are not saved, not charged, and their full record is not even read. The memory lives in a named key-value store of your account (`us-county-property-records-scraper-seen`, up to 150,000 properties per key) and is only updated with records that really reached the dataset. Give each schedule its own `stateKey`, and tick `resetState` once to start over. A property already delivered is skipped even when it is sold again: to follow new sales, schedule a run with **Sold after** set to a period (`7 days` every week) instead.

- A search stops once 20 results pages in a row hold only properties already delivered (20,000 rows of a whole-county listing, 4,000 of a Miami-Dade lookup or of New York City's recent sales): the run does not read the rest of the county for nothing new.
- With **Only new records**, a property your filters drop is checked (and charged) once; the next runs with the same filters skip it for free. Change a filter, or tick **Reset the memory**, to check them again.

#### Filter by sale date

`soldAfter` and `soldBefore` take a date (`2026-09-01`, the whole day is included) or a period before now (`30 days`, `3 months`, `1 year`), counted on each county's local clock (Eastern time for Miami-Dade and New York City, Pacific time for Los Angeles), whatever the hour the run starts. The filter reads `lastSaleDate`; a property without a recorded sale is dropped as soon as a date bound is set. In Los Angeles without the full record, only the year of the last transfer is known (`lastSaleYear`): the bound is compared on the year.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per property record of Miami-Dade, New York City or Los Angeles. Actor id: `nice_dev/us-county-property-records-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/us-county-property-records-scraper`.

Smallest input, for a cheap first call:

```json
{
    "counties": ["miami-dade"],
    "addresses": ["1200 Brickell Bay Dr Unit 3101, Miami, FL 33131"],
    "maxItems": 5
}
```

Key output fields: `propertyAddress`, `ownerName`, `ownerMailingAddress`, `marketValue`, `lastSaleDate`, `lastSalePrice`, `homestead` and `sales` (with `includeDetails`).

Cost: $0.32 (Gold) to $0.35 (Free) per 1,000 records, plus $0.49 (Gold) to $0.59 (Free) per 1,000 full records when ticked, $12.96 (Gold) to $12.99 (Free) per 1,000 owner contacts found, plus $0.0013 per run start, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape county property records?

The Actor only reads what the counties publish to any anonymous visitor: the property appraiser of Miami-Dade, the open data of New York City and the assessor of Los Angeles. It logs in to nothing. Results contain personal data (owner names and mailing addresses): store and use them only for a legitimate purpose, in compliance with the counties' terms of use and applicable law. This Actor must not be used for tenant, employment, credit or insurance screening (FCRA).

With **Add the owner's phones and e-mails**, the Actor also reads public people-search directories (ThatsThem, FastPeopleSearch, CyberBackgroundChecks) as any anonymous visitor can:

- **FCRA**: this is not a consumer reporting agency. Never use the results to decide on credit, employment, tenant screening, insurance or any other purpose covered by the Fair Credit Reporting Act.
- **TCPA and Do Not Call**: calling or texting a mobile number with an autodialer or a prerecorded message needs the person's consent; check the numbers against the National Do Not Call Registry before any marketing call. The Actor does not flag them.
- **Data broker laws**: reselling data about people you have no direct relationship with can require a registration (California, Vermont, Texas, Oregon).
  Florida hides the owners the law protects (judges, police officers…) and California does not let its counties publish owner names online: those fields stay empty. For anything with legal weight, check the county's official record. This Actor is not affiliated with Miami-Dade County, the City of New York, Los Angeles County, ThatsThem, FastPeopleSearch or CyberBackgroundChecks.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request a server turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).

#### Why are the owner fields empty in Los Angeles?

California law keeps its counties from publishing owner names online. Los Angeles records give the address, values, land use, homeowners' exemption and the transfers (dates, document numbers, the price declared for the transfer tax), without names; `fieldNotes` says so on each record.

#### Is the data safe to open in Excel or to show on a web page?

Names and addresses are copied as the counties write them. A text can begin with `-`, `+`, `=` or `@`: Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. On a web page, escape every field like any other text.

#### Known limitations

- New York City's deeds come from the city's open data, up to about a month behind the recorder's office; its valuation roll is yearly.
- Los Angeles: no owner names or mailing addresses (see above); without the full record, only the year of the last transfer.
- Miami-Dade's whole-county listing reads the county's open data, updated about once a week; a looked-up address or parcel reads the county's live record.
- `onlyNew` remembers properties, not their sales: a property sold again is not returned again (see Monitoring).

**A run that reaches its timeout** stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with `onlyNew`, remembered, and the run ends *Succeeded* with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

**A run the platform stops without warning** (out of memory)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the records already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the records it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the records of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the records saved, filtered out and no longer known to the county (a retired or merged parcel), and the requests that failed after every retry. Those requests are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store; the `SEARCH_STATS` record gives, for each search, how many records it found (0 = the county has no such address, owner or parcel — never charged).

If a county changes its data, you are told instead of paying for blank rows. If the first 20 records read all lack their owner (Miami-Dade, New York City), their tax year or their value, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first records are charged. A record that an owner or value filter drops because it has no owner or value at all counts among those 20. A run of 5 to 19 records is checked at its end: its records are saved, and the run fails with the same message. Rows that never carry a year or a value are left out of the check: a search row read without its full record (Miami-Dade, a Los Angeles address) and Los Angeles' public and state-assessed parcels (lots 800-999, not on the county's roll).

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which requests failed and why.

# Actor input Schema

## `counties` (type: `array`):

Where to search. A lookup that names another county (state, ZIP code or city in the address) is only run there; the others are run in every county picked here. Los Angeles: the county does not publish owner names online, so owner names, mailing addresses and owner-name search are not available there.

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

Street addresses to look up, one per line, with the unit for an apartment (e.g. `1200 Brickell Bay Dr Unit 3101, Miami, FL 33131`, `350 W 50th St Apt 12B, New York, NY 10019`, `1000 Main St, Los Angeles, CA 90012`). One record per property found. Max 1 000.

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

Owner names to look up (person or company, e.g. `SMITH JOHN`, `ACME HOLDINGS LLC`): every property the name holds in the county. Word order does not matter (`JOHN SMITH` works too; New York City writes people `SMITH, JOHN`). Not available in Los Angeles. Max 500.

## `parcelNumbers` (type: `array`):

Miami-Dade folio (13 digits, dashes allowed: `02-4210-018-0050`; 9 digits = a whole building or subdivision: `024210018`), New York City BBL (10 digits, dashes allowed: `NYC:1-01030-1001`), Los Angeles AIN (10 digits, dashes allowed: `LA:4371-024-013`). Both NYC and LA use 10 digits: when both counties are picked, write NYC: or LA: before the number. Max 1 000.

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

Maximum number of property records to save for the whole run (after deduplication and filters). 0 = no limit. With the three lists above empty, the run lists the whole county: Miami-Dade has 943 550 parcels, New York City 1.18 million lots and apartments, Los Angeles 2.43 million parcels.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (one address, owner name or parcel in one county, or one whole-county listing), so that one big owner or county cannot use up the whole **Max records** budget. 0 = no per-search cap.

## `includeDetails` (type: `boolean`):

Read the full record of each property (1-4 extra requests): all recorded sales with buyer, seller and deed reference, 3 years of values, exemptions (homestead), New York City deeds and mortgages. Off by default = the fields of the county's search or open-data row only (owner, mailing address, last sale, current value): faster, and you skip the extra 'Full county record' fee of each property (see the Pricing tab). Tick it to get the full record. An address, owner or parcel lookup with a filter other than owner type, excluded words or borough reads the full record anyway (its search rows carry no sale, value or type).

## `includeOwnerContacts` (type: `boolean`):

For each property owned by a person (not a company or a government body), looks the owner up in public people-search directories: phones, e-mails, current address, age, relatives, and whether the person passed away (`ownerDeceased`: an owner still on the county's roll, an estate, when the directory says it); `ownerContactSource` says which directory gave the contact. Searched at the property first (the people listed there), then at the owner's mailing address, then by name in the state; `ownerContactMatch` says how the person was found (`address`, `mailing`, or `name` = name and state, kept only when the property or the owner's mailing address is among the person's known addresses). Miami-Dade and New York City (Los Angeles publishes no owner names). Needs 'Full record'. Slower (10-60 s per property). Charged as a separate `owner-contact` event, only for properties where a phone or an e-mail is found, whichever directory gives it.

## `includeOwnerPortfolio` (type: `boolean`):

For each property, lists the other properties its owner (the first owner named) holds in the same county: parcel, address, value and link to the county's record, up to 100. A namesake's property is never listed: a registered business (LLC, Inc., Corp., LP…) is matched by its exact name, anyone else (a person, a trust) only when the other property's owner address is this property or its mailing address. Miami-Dade (mailing address of every parcel) and New York City (valuation roll, and for a person the buyer's address on the deeds); not possible in Los Angeles (the county publishes no owner names). Needs 'Full record'. 1 to 3 more county requests per property. Priced separately (event `owner-portfolio`), only for properties where at least one other property is found.

## `includeDistressScore` (type: `boolean`):

For each property, a 0-100 score of signs that its owner may sell, computed from the county's own fields — no extra request, no AI model: owner deceased (needs 'Owner contacts'), owned by an estate or heirs, taken by a foreclosure deed in the last 3 years (bank-owned), owner not living there, owner out of state, owned for 10+ years, value 1.5× or 2× the last sale price, vacant land. Each factor found comes with its points and the value that set it off (distressFactors); the factors a row could not check are listed (distressUnchecked). Tax arrears are not read. Los Angeles publishes no owner names and its values are Proposition 13 bases: only 4 factors there. Works with or without 'Full record' (fewer factors without it). Priced separately (event `distress-score`), only for properties with at least one factor found; a score of 0 is free.

## `sortBy` (type: `string`):

Order of a whole-county listing: newest sales first, highest sale price, highest market value, or parcel number. Each county sorts on what it publishes: Miami-Dade's highest value is the assessed value; Los Angeles knows the year of the last sale only, so both sale orders give the most recent year first; New York City without a sale filter lists by parcel number (the valuation roll has no sales), and with a sale filter by newest deed. Lookups keep the county's order.

## `soldAfter` (type: `string`):

Only properties whose LAST recorded sale is on or after this date: `2026-01-01`, or a period before now such as `30 days`, `3 months`, `1 year`. Properties without a recorded sale are dropped. Los Angeles publishes the year of the last sale only: compared on the year.

## `soldBefore` (type: `string`):

Only properties whose last recorded sale is on or before this date (the whole day is included), or older than a period such as `10 years`.

## `minSalePrice` (type: `integer`):

Only properties whose last recorded sale price is at least this amount, in US dollars. Properties without a sale price are dropped.

## `maxSalePrice` (type: `integer`):

Only properties whose last recorded sale price is at most this amount, in US dollars.

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

Only properties whose current market value set by the county is at least this amount (Miami-Dade: assessed value in the open data, market value in the full record; Los Angeles: land + improvement roll value).

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

Only properties whose current market value is at most this amount.

## `propertyTypes` (type: `array`):

Only these property types (any of them), from the county's land-use code. Empty = all types.

## `ownerType` (type: `string`):

Companies (LLC, Inc., LP, trust, estate…) only, people only, or both. Read on the owner name. Not available in Los Angeles.

## `absenteeOwnersOnly` (type: `boolean`):

Only properties whose owner's mailing address is not the property address (rented, second home, investor). New York City: mailing address = buyer's address on the last deed (full record needed). Not available in Los Angeles.

## `outOfStateOwnersOnly` (type: `boolean`):

Only properties whose owner's mailing address is in another US state or abroad.

## `foreignOwnersOnly` (type: `boolean`):

Only properties whose owner's mailing address is outside the United States.

## `homesteadOnly` (type: `boolean`):

Only properties with a homestead / homeowners' exemption (the owner lives there). Miami-Dade: read in the full record. Not available in New York City.

## `excludeHomestead` (type: `boolean`):

Drop the properties with a homestead / homeowners' exemption (keeps rentals, second homes and investor-owned properties). Not available in New York City.

## `zipCodes` (type: `array`):

Only properties in these 5-digit ZIP codes (e.g. `33109`). Empty = the whole county.

## `boroughs` (type: `array`):

New York City only: only these boroughs. Empty = the 5 boroughs.

## `latitude` (type: `string`):

Whole-county listing around a point: latitude in decimal degrees (e.g. `25.7617`), with **Around: longitude** and **Radius**. Miami-Dade and Los Angeles only (the New York City valuation data has no coordinates).

## `longitude` (type: `string`):

Longitude in decimal degrees (e.g. `-80.1918`).

## `radiusMiles` (type: `number`):

Distance around the point, in miles (0.1 to 50).

## `minYearBuilt` (type: `integer`):

Only buildings built in or after this year.

## `maxYearBuilt` (type: `integer`):

Only buildings built in or before this year.

## `minBedrooms` (type: `integer`):

Only properties with at least this many bedrooms. Not available in New York City (the city does not publish bedrooms).

## `maxBedrooms` (type: `integer`):

Only properties with at most this many bedrooms. Not available in New York City.

## `minBathrooms` (type: `integer`):

Only properties with at least this many full bathrooms. Not available in New York City.

## `maxBathrooms` (type: `integer`):

Only properties with at most this many full bathrooms. Not available in New York City.

## `minLivingAreaSqFt` (type: `integer`):

Only properties with at least this living area, in square feet (New York City: gross building area).

## `maxLivingAreaSqFt` (type: `integer`):

Only properties with at most this living area, in square feet.

## `minLotSizeSqFt` (type: `integer`):

Only properties whose land area is at least this many square feet (1 acre = 43 560 sq ft).

## `maxLotSizeSqFt` (type: `integer`):

Only properties whose land area is at most this many square feet.

## `poolOnly` (type: `boolean`):

Miami-Dade only: only properties whose full record lists a pool. Not available in New York City and Los Angeles (not published).

## `excludeKeywords` (type: `array`):

Drop the properties whose owner name contains one of these words (case ignored), e.g. `COUNTY`, `CITY OF`, `HOUSING AUTHORITY`.

## `onlyNew` (type: `boolean`):

Skip the properties that a previous run (same **Memory key**) already delivered, even if they were sold since: they are not saved and not charged, and their full record is not even read. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new records**. Give each schedule / task its own key (e.g. `miami-sales-1m`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every record again. Untick it afterwards.

## `proxyConfiguration` (type: `object`):

Apify Proxy or your own proxies. Keep the default: it is included in the price. The residential Apify proxy is not available in this Actor.

## `socrataAppToken` (type: `string`):

Optional, New York City only: your free app token from data.cityofnewyork.us (Developer settings). It raises the open-data rate limit for very large runs. Stored encrypted.

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

Maximum number of requests processed in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Most requests to the county servers in any 60 seconds, all of them counted. A budget, not an even pace (spread them with the minimum delay below). Lower it if the log shows HTTP 429 / 403.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. Unlike the per-minute rate, this spreads the requests evenly instead of letting them go out in a burst. 0 = no gap.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed. Behind a proxy, a request the server turns away is also retried on a new proxy session up to 10 times without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "counties": [
    "miami-dade"
  ],
  "addresses": [],
  "ownerNames": [],
  "parcelNumbers": [],
  "maxItems": 20,
  "maxItemsPerQuery": 0,
  "includeDetails": false,
  "includeOwnerContacts": false,
  "includeOwnerPortfolio": false,
  "includeDistressScore": false,
  "sortBy": "newestSale",
  "soldAfter": "3 months",
  "minSalePrice": 1000000,
  "propertyTypes": [],
  "ownerType": "any",
  "absenteeOwnersOnly": false,
  "outOfStateOwnersOnly": false,
  "foreignOwnersOnly": false,
  "homesteadOnly": false,
  "excludeHomestead": false,
  "zipCodes": [],
  "boroughs": [],
  "poolOnly": false,
  "excludeKeywords": [],
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 4,
  "maxRequestsPerMinute": 120,
  "minRequestIntervalMs": 0,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# Actor output Schema

## `results` (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 = {
    "counties": [
        "miami-dade"
    ],
    "maxItems": 20,
    "soldAfter": "3 months",
    "minSalePrice": 1000000,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/us-county-property-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 = {
    "counties": ["miami-dade"],
    "maxItems": 20,
    "soldAfter": "3 months",
    "minSalePrice": 1000000,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/us-county-property-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 '{
  "counties": [
    "miami-dade"
  ],
  "maxItems": 20,
  "soldAfter": "3 months",
  "minSalePrice": 1000000,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/us-county-property-records-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/us-county-property-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/e2ulleNl1jCnepJRs/builds/hXfR7LZWXNdtvUgqv/openapi.json
