# Property Search API - US Property Records, Owners and MLS (`nabeelbaghoor/property-search-api`) Actor

Search 150M+ US property records by location, owner, equity and distress: absentee owner, high equity, vacant, pre-foreclosure, cash buyer and 150 more filters. Pull full county profiles, comparable sales, MLS listings with agent contacts, and verified standardised addresses.

- **URL**: https://apify.com/nabeelbaghoor/property-search-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Real estate, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $12.00 / 1,000 property record returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Property Search API - US Property Records, Owners and MLS

Build a targeted list from 150M+ US property records, then pull the full county profile, the comparable sales and the live MLS listing for every property on it.

### What this actor does

- **Build investor lists.** Filter by location, then narrow with the provider's own flags: absentee owner, high equity, free and clear, vacant, pre-foreclosure, foreclosure, auction, REO, inherited, cash buyer, corporate owned, trust owned, tired landlord by years owned, and forty more. Every flag you pick must match.
- **Full property profiles.** Owner names and separate mailing address, assessed land, improvement and total value, estimated value, estimated equity and equity percent, open mortgage balance and lender, last sale amount and date, suggested rent, flood zone, neighborhood and current MLS status.
- **Comparable sales.** Give a subject address and get comparables back, with the distance in miles on every row. Insist on the same beds, baths, ZIP, county or neighborhood, restrict to arms length sales, and set your own radius and lookback.
- **MLS listings.** Search what is on the market by status, price, days on market and property characteristics, and get the listing agent's name, email and phone with each row.
- **Address tools.** Autocomplete an address, city, county, neighborhood, ZIP or APN, and verify lists of addresses into standardised, ZIP+4 form with a confidence score.
- **A free match count before you spend.** Search mode asks how many properties match before it starts paging. The provider charges nothing for that, so you know the real size of your list up front.
- **Pay per result.** You are charged for rows that carry a real record. Searches that match nothing, and addresses the provider cannot match, are free.

### Bring your own key

This actor calls the provider with **your own API key**. Paste it into the API key field, or set it as the `DATA_API_KEY` secret. Nothing runs on anyone else's credentials, and a run without a key ends cleanly with an explanation rather than failing.

### Example output

```json
{
  "recordType": "property",
  "requested": "Arlington, VA",
  "found": true,
  "propertyId": "253175355",
  "apn": "16-024-108",
  "fullAddress": "13723 Neil Armstrong Ave Unit 308, Herndon, VA 20171",
  "city": "Herndon",
  "county": "Fairfax",
  "state": "VA",
  "zip": "20171",
  "propertyType": "CONDO",
  "bedrooms": 2,
  "bathrooms": 2,
  "squareFeet": 1323,
  "yearBuilt": 2015,
  "ownerName": "Attili Srinivas",
  "ownerOccupied": true,
  "absenteeOwner": false,
  "mailAddress": "13723 Neil Armstrong Ave Unit 308, Herndon, VA 20171",
  "assessedValue": 408590,
  "estimatedValue": 490308,
  "estimatedEquity": 189084,
  "equityPercent": 38,
  "openMortgageBalance": 313500,
  "lenderName": "One American Mtg",
  "lastSaleAmount": 418000,
  "lastSaleDate": "2020-07-23",
  "suggestedRent": 2070,
  "highEquity": false,
  "vacant": false,
  "preForeclosure": false,
  "floodZone": true,
  "floodZoneType": "X",
  "mlsStatus": "Active",
  "mlsDaysOnMarket": 101
}
```

### FAQ

#### How do I build a motivated seller list?

Use search mode with a county or ZIP code, then pick the flags that describe the seller you want. `pre_foreclosure`, `foreclosure`, `auction`, `reo`, `inherited`, `vacant`, `absentee_owner` and `out_of_state_owner` are the ones investors reach for most. Every flag you pick must match, so combining three or four narrows quickly. Add `high_equity` or an estimated equity range to keep only owners with room to negotiate.

#### What is the difference between search and detail?

Search returns an abbreviated record for every property matching your filters, which is what you want when building a list. Detail returns the full county and public record profile for one named property, including sale and mortgage history that the search record does not carry. The usual pattern is to search first, then run detail on the property ids that came back.

#### Can I find absentee and out-of-state owners?

Yes. `absentee_owner` means the owner does not live at the property, and `out_of_state_owner` narrows that to owners whose mailing address is in a different state. Every row also carries the mailing address separately from the property address, so you can see the distance for yourself.

#### How do comparables work?

Give one or more subject addresses and the actor returns comparable properties for each, one row per comparable, with the distance from the subject in miles. You control the radius, how far back to look, how many to return, and whether a comparable has to share the subject's bedrooms, bathrooms, ZIP, county or neighborhood. Restricting to arms length sales excludes family transfers and other sales that do not reflect a real market price.

#### Does it include MLS listing data?

Yes, in MLS search mode. Rows carry the listing id, MLS number and board code, price, status, days on market, listing and sold dates, the agent's public remarks, and the listing agent's name, email and phone alongside the public record profile of the same property.

#### How does paging work?

The provider uses a cursor rather than a page number: each response carries a position that the actor feeds back into the next request. That means a long search stays consistent even while the underlying result set changes, which an offset-based approach cannot promise. The actor stops when your maximum rows setting is reached or the provider stops advancing the cursor.

#### What does it cost?

Pricing is pay per result: 0.012 USD per property record, 0.006 USD per comparable, 0.012 USD per MLS listing and 0.003 USD per address suggestion or verified address, with Apify platform usage included. Rows the provider found nothing for are not charged. You also need your own account with the data provider, which spends one credit per record it returns.

#### Does the actor fail if my key is wrong?

No. A missing key, a rejected key, an exhausted credit balance or an empty input all end the run cleanly with a message saying what to change. Only a real outage or a bug fails the run. Note that this provider validates the request body before it checks the key, so a rejected search is reported as a problem with that search rather than as a credential failure.

### Keyword map

property search API, US property records API, property data API, real estate data API, absentee owner list, high equity properties, vacant property list, pre-foreclosure leads, foreclosure data API, REO list, cash buyer list, property owner lookup, owner mailing address, estimated equity, open mortgage balance, comparable sales API, real estate comps API, MLS listing data API, listing agent contact, days on market, address verification API, address autocomplete API, APN lookup, real estate investor lead generation

# Actor input Schema

## `mode` (type: `string`):

Search builds a property list from the nationwide record set. Detail returns the full county profile for named addresses. Comps returns comparable properties for a subject. MLS search covers what is on the market. Autocomplete and address check are the address handling modes.

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

Search modes. The city to search, used together with the state, for example Arlington.

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

Search modes. The two letter state code, for example VA.

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

Search modes. The county name, used together with the state. A county is usually the right unit for an investor list, because it matches how the records are recorded.

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

Search modes. A five digit ZIP code.

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

Search modes. A single full address, for example "13723 Neil Armstrong Ave, Herndon, VA 20171".

## `apn` (type: `string`):

Search modes. The assessor's parcel number. Give the state or county with it, because APNs are only unique inside a county.

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

Search and autocomplete modes. The centre of a radius search, or the point to bias suggestions towards.

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

Search and autocomplete modes. The centre of a radius search, or the point to bias suggestions towards.

## `radius` (type: `string`):

Search modes. How far from the centre point to search, in miles.

## `propertyType` (type: `string`):

Search modes. Keeps only properties of this type.

## `flags` (type: `array`):

Search modes. The provider's own true or false property flags. Every flag you pick must match. These are what build an investor list: absentee\_owner, high\_equity, vacant and pre\_foreclosure are the four used most.

## `bedsMin` (type: `integer`):

Search modes. The fewest bedrooms a property may have.

## `bedsMax` (type: `integer`):

Search modes. The most bedrooms a property may have.

## `bathsMin` (type: `integer`):

Search modes. The fewest bathrooms a property may have.

## `bathsMax` (type: `integer`):

Search modes. The most bathrooms a property may have.

## `buildingSizeMin` (type: `integer`):

Search modes. The smallest living area in square feet.

## `buildingSizeMax` (type: `integer`):

Search modes. The largest living area in square feet.

## `lotSizeMin` (type: `integer`):

Search modes. The smallest lot size in square feet.

## `lotSizeMax` (type: `integer`):

Search modes. The largest lot size in square feet.

## `yearBuiltMin` (type: `integer`):

Search modes. The earliest year of construction.

## `yearBuiltMax` (type: `integer`):

Search modes. The latest year of construction.

## `valueMin` (type: `integer`):

Search modes. The lowest estimated market value in dollars.

## `valueMax` (type: `integer`):

Search modes. The highest estimated market value in dollars.

## `equityMin` (type: `integer`):

Search modes. The least estimated equity in dollars. Pair this with high\_equity to find owners with room to negotiate.

## `equityMax` (type: `integer`):

Search modes. The most estimated equity in dollars.

## `lastSalePriceMin` (type: `integer`):

Search modes. The lowest recorded last sale price in dollars.

## `lastSalePriceMax` (type: `integer`):

Search modes. The highest recorded last sale price in dollars.

## `lastSaleDateFrom` (type: `string`):

Search modes. Keeps only properties whose last recorded sale is on or after this date, written as YYYY-MM-DD.

## `lastSaleDateTo` (type: `string`):

Search modes. Keeps only properties whose last recorded sale is on or before this date, written as YYYY-MM-DD.

## `yearsOwnedMin` (type: `integer`):

Search modes. The fewest years the current owner has held the property. A long hold is the usual signal for a tired landlord list.

## `yearsOwnedMax` (type: `integer`):

Search modes. The most years the current owner has held the property.

## `daysOnMarketMin` (type: `integer`):

Search modes. The fewest days the current listing has been on the market.

## `daysOnMarketMax` (type: `integer`):

Search modes. The most days the current listing has been on the market.

## `searchCriteria` (type: `object`):

Search modes, optional. Any further criteria in the provider's own format, merged over the fields above. The provider indexes more than 150 filters including census geography, construction, sewage, water source, loan and document type codes, so this is how to reach one the form does not cover.

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

Detail, comps and address check modes. One per line. A line of digits is treated as the provider's own property id and anything else as an address.

## `compMaxRadiusMiles` (type: `integer`):

Comps mode. How far from the subject to look for comparable properties.

## `compMaxDaysBack` (type: `integer`):

Comps mode. Ignores sales older than this many days. A tighter window tracks a fast moving market but finds fewer comparables.

## `compMaxResults` (type: `integer`):

Comps mode. How many comparable properties to return for each subject.

## `same_beds` (type: `boolean`):

Comps mode. Keeps only comparables with the same bedroom count as the subject.

## `same_baths` (type: `boolean`):

Comps mode. Keeps only comparables with the same bathroom count as the subject.

## `same_zip` (type: `boolean`):

Comps mode. Keeps only comparables in the subject's own ZIP code.

## `same_county` (type: `boolean`):

Comps mode. Keeps only comparables in the subject's own county.

## `same_neighborhood` (type: `boolean`):

Comps mode. Keeps only comparables in the subject's own neighborhood, which is tighter than a ZIP code.

## `arms_length` (type: `boolean`):

Comps mode. Keeps only sales between unrelated parties at market value, which excludes family transfers and other sales that do not reflect a real price.

## `compCriteria` (type: `object`):

Comps mode, optional. Any further comparable settings in the provider's own format, including the boost weights that decide how much bedrooms, bathrooms, size, lot and age each count towards the match.

## `searchTerm` (type: `string`):

Autocomplete mode. At least three characters of an address, city, county, neighborhood, ZIP or APN.

## `searchTypes` (type: `array`):

Autocomplete mode. Which kinds of suggestion to return. Leave empty for all of them.

## `strictAddressMatch` (type: `boolean`):

Address check mode. Requires a closer match before the provider will call an address verified, which trades recall for precision.

## `includePhotos` (type: `boolean`):

MLS search mode. Asks the provider to return photo URLs with each listing. This makes responses considerably larger.

## `skipCount` (type: `boolean`):

Search mode. Before paging, the actor asks how many properties match, which the provider does not charge credits for. Turn this off only if you want to save the one extra request.

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

The most rows this run will save and charge for. The provider spends one credit per record returned, so this is the spending control on both sides.

## `pageSize` (type: `integer`):

Search modes. How many records to ask for at a time, up to the provider's ceiling of 250. A wider page is not a cheaper one, because credits count records rather than requests.

## `requestsPerMinute` (type: `integer`):

How fast to call the provider. Lower this if your plan rate limits the run.

## `apiKey` (type: `string`):

Your own API key for the property data provider, taken from your account. This actor is bring your own key: it never uses anyone else's credentials, and the key is stored as a secret.

## Actor input object example

```json
{
  "mode": "search",
  "same_beds": false,
  "same_baths": false,
  "same_zip": false,
  "same_county": false,
  "same_neighborhood": false,
  "arms_length": false,
  "strictAddressMatch": false,
  "includePhotos": false,
  "skipCount": false,
  "maxResults": 1000,
  "pageSize": 250,
  "requestsPerMinute": 120
}
```

# Actor output Schema

## `records` (type: `string`):

One row per record, alongside the address, search term or search that produced it.

# 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("nabeelbaghoor/property-search-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/property-search-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call nabeelbaghoor/property-search-api --silent --output-dataset

```

## MCP server setup

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

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/LP9iLgaJeBJpCS6hV/builds/cNcHUnQxNi4FkdNol/openapi.json
