# Realtor.com Scraper 🏡 $1/1K, No Start Fee (`trakk/realtor-scraper`) Actor

Scrape realtor.com for-sale, rental and sold listings with 145+ fields — price history, tax records, assigned schools, FEMA flood risk, mortgage breakdown, agent emails and office phones. Every listing is scored against its own city and county median. No start fee, no cookies, no browser.

- **URL**: https://apify.com/trakk/realtor-scraper.md
- **Developed by:** [Kelopr\_bk](https://apify.com/trakk) (community)
- **Categories:** Real estate, Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 results

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

## 🏡 Realtor.com Scraper — Listings, Agents & Market Data

Pull **for-sale, rental, sold and off-market listings** from realtor.com with the
fields the other Actors give you — and the ones they don't: **tax history,
assigned schools, FEMA flood risk, the mortgage breakdown, agent contacts**, and
every listing measured against **its own city and county market**.

No account. No cookies. No browser. Just a location and a run.

***

### ⚡ Quick start

1. Click **Try for free**.
2. Put a place in **📍 Locations** — `Austin, TX`, a ZIP like `78704`, a county
   like `Travis County, TX`, or paste a realtor.com search link.
3. Pick a **🏷️ Listing status** — *For sale* is the default, *Sold* opens the
   archive.
4. Press **Start**.

That's it. A 50-row run finishes in a few seconds.

```json
{
  "locations": ["Austin, TX"],
  "status": "for_sale",
  "mode": "listings",
  "maxResults": 50
}
```

Want the deep data? Switch **⚙️ What to collect** to
*Listings + property details*:

```json
{
  "locations": ["Austin, TX"],
  "mode": "listings_plus_details",
  "priceMin": 300000,
  "priceMax": 700000,
  "bedsMin": 3,
  "maxResults": 200
}
```

***

### 🎯 What makes this one different

Most realtor.com Actors hand you the listing and stop. **This one tells you what
the listing means.**

Every row can carry its own market context, computed from data collected in the
same run:

| Field | What it answers |
|---|---|
| `priceVsCityMedianPct` | Is this priced above or below the city? |
| `priceVsCountyMedianPct` | And above or below the whole county? |
| `pricePerSqftVsCityMedianPct` | Is the *space* priced fairly? |
| `estimateVsPricePct` | Is the asking price above or below realtor.com's own valuation? |
| `daysOnMarketVsCityMedian` | Has it been sitting longer than the local norm? |
| `priceCutCount` / `totalPriceCutPct` | Has the seller already blinked, and by how much? |
| `grossRentYieldPct` | What does the city's median rent imply for yield? |
| `monthlyPaymentEstimate` | What would it actually cost per month? |
| `dealScore` + `dealSignals` | All of the above, as one number and a plain-English reason list |

Nothing here is invented. When an input is missing, the field is **null** rather
than guessed, and `analysisConfidence` tells you how much of the analysis was
actually computable.

***

### 📦 What you get

**Always — 100+ fields per listing:**

- 🆔 `propertyId`, `listingId`, `url`, `permalink`, `status`, MLS id and type
- 💵 price, price per sqft, price cuts, last sold price and date
- 🛏️ beds, baths (full / half / three-quarter), sqft, lot size, year built,
  garage, stories, full listing text
- 📍 full address, unit, county + FIPS, latitude/longitude, Street View link
- 🚩 new listing, price reduced, new construction, foreclosure, contingent,
  pending, coming soon
- 🖼️ every photo, virtual tours, Matterport flag
- 🚪 open house dates, HOA fee, pet policy
- 📋 **feature groups** — appliances, interior, exterior, utilities, exactly as
  realtor.com groups them
- 🚫 **`suppressedFields`** — which values the MLS has forbidden this listing to
  publish, so an empty sold price reads as *withheld*, not *missing*
- 📊 city and county medians: list price, $/sqft, days on market, rent

**With *Listings + property details* — the deep layer:**

- 🧾 **Tax history** — annual tax, assessed land/building/total, market values
- 🏫 **Assigned schools** — name, rating, parent rating, grades, district,
  student count, distance
- 📈 **Price history** — every listing event with its date, price and source.
  realtor.com leaves this empty on for-sale search rows, so the per-property
  call is what fills it — and what makes `priceCutCount` and `totalPriceCutPct`
  real numbers rather than zeroes
- 🌊 **Flood risk** — flood-factor score and severity, FEMA zone, trend,
  environmental risk
- 💹 **Valuation** — current estimate with high/low, plus forecast and history
- 🏦 **Mortgage** — loan amount, monthly payment, total payment, down payment,
  rate and term, property-tax and insurance rates
- 📞 **Contacts** — agent name, e-mail, profile link, brokerage name and
  **office phone**

**With *Agents* mode — one row per listing agent:**

name, e-mail, office phone, brokerage, profile link, listing count, average and
total list price, and the cities they work.

> 📌 **About phone numbers:** realtor.com publishes the **brokerage office
> phone**, not a personal mobile number. `officePhone` is filled on essentially
> every listing; `agentPhone` is what the site itself almost always leaves
> empty. We report exactly what the source gives, and never fabricate a number.

***

### 🎛️ Filters

All of them are applied by realtor.com itself, so a narrow search costs no more
than a wide one:

💵 price · 🛏️ beds · 🛁 baths · 📐 sqft · 🌳 lot size · 📅 year built ·
🚗 garage · 🏘️ HOA fee or no HOA · 🏠 20 property types · 🏢 sub types ·
🔎 keywords (*pool*, *casita*, *waterfront*) · 🏗️ new construction ·
🏚️ foreclosures · 📉 short sales · 📝 contingent · ⏳ pending · 👵 55+ ·
🎥 virtual tour · 🧊 Matterport · 🐈🐕 pets (rentals) · 🚪 open-house window ·
🗓️ listed-date window · 💰 sold-date window

And nine sort orders, including **newest**, **price high/low**, **most photos**
and **recently sold**.

***

### 💰 Sold data is the sleeper feature

Set **🏷️ Listing status** to *Sold* and you are reading realtor.com's archive,
not the live market. Austin alone holds **over 126,000 sold records** — comps,
absorption rates, and a price history most listing scrapers never touch.

Pair it with `soldSince` / `soldUntil` to pull a specific quarter.

***

### ✅ Built to be predictable

- **Bad input never crashes the run.** Type a filter wrong and you get a plain
  sentence saying which field and why — not a stack trace.
- **Rows are written as they are found.** If a run stops early, everything
  collected up to that point is already in your dataset.
- **No start fee.** Most Actors in this niche charge $0.005–$0.01 just to press
  Start. This one charges for results.
- **Datacenter proxy is enough.** realtor.com needs a US address, not an
  expensive residential one — which is why this Actor is cheap to run.

***

### 🔧 Output example (trimmed)

```json
{
  "propertyId": "9332841646",
  "url": "https://www.realtor.com/realestateandhomes-detail/13409-Madrone-Mountain-Way_Austin_TX_78737_M93328-41646",
  "status": "for_sale",
  "price": 1359990,
  "priceSource": "propertyDetail",
  "searchPrice": 450000,
  "beds": 4,
  "baths": 4,
  "sqft": 3414,
  "address": "13409 Madrone Mountain Way",
  "city": "Austin",
  "stateCode": "TX",
  "postalCode": "78737",
  "county": "Hays",

  "priceVsCityMedianPct": 167.0,
  "estimatedValue": 1250400,
  "estimateVsPricePct": -8.1,
  "daysOnMarketComputed": 739,
  "grossRentYieldPct": 1.72,
  "monthlyPaymentEstimate": 8578,
  "dealScore": 31,
  "dealSignals": [
    "priced well above the city median",
    "on the market longer than the local median"
  ],
  "analysisConfidence": "high",

  "latestTaxYear": 2025,
  "latestTaxAmount": 7440,
  "schoolRatingAverage": 8.0,
  "floodFactorScore": 1,
  "floodFactorSeverity": "minimal",
  "femaZone": ["X (unshaded)"],

  "agentName": "Julie Gualandri",
  "agentEmail": "julieg@jbgoodwin.com",
  "officePhone": "(512) 901-9600",
  "officeName": "KW-Austin Portfolio Real Estate"
}
```

> The `searchPrice` line is not a mistake. realtor.com's own search sometimes
> returns one property twice at different prices; the Actor takes the canonical
> per-property price, keeps the search figure next to it, and says through
> `priceSource` which one you are looking at.

***

### 🏘️ More real-estate Actors

Working a whole market rather than one portal? These cover the rest of it:

- 🏠 [**Zillow Scraper** — Listings, Zestimate, Agents & Cash Flow](https://apify.com/trakk/zillow-scraper)
- 🏢 [**LoopNet Scraper** — Commercial listings, brokers & deal intel](https://apify.com/trakk/loopnet-commercial-real-estate-scraper)
- 🇪🇸 [**Idealista Scraper** — Property data, phones & e-mails](https://apify.com/trakk/idealista-scraper)
- 🛏️ [**Airbnb Scraper** — Host leads, e-mails, phones & revenue](https://apify.com/trakk/airbnb-scraper-v2)
- 🗺️ [**Google Maps Scraper** — 130+ fields, e-mails & reviews](https://apify.com/trakk/google-maps-business-intelligence-v2)

***

### ❓ FAQ

**Do I need a realtor.com account or cookies?**
No. Nothing is logged in and nothing is stored between runs.

**How many listings can one search return?**
realtor.com stops paging a single search at 10,000, and in practice starts
repeating rows before that — a measured Austin run asked for 6,000 and got
4,752 *unique* listings out of the 6,978 the site claims. Duplicates are
dropped rather than billed. To go deeper, split the search — by price band, by
property type, or by ZIP code — and run each as its own location.

**Why is `daysOnMarket` sometimes empty?**
realtor.com leaves that field blank on most search rows. The Actor fills
`daysOnMarketComputed` from the listing date instead, and
`daysOnMarketSource` tells you which of the two you are looking at.

**What does `dataCompleteness` mean?**
`listing` — search data only. `enriched` — contacts were added.
`full` — the property detail call succeeded and the deep fields are populated.

**Can I scrape a specific property?**
Yes. Paste its page link or numeric id into **🔗 Specific properties**.

# Actor input Schema

## `locations` (type: `array`):

Where to search. Write a city and state (Austin, TX), a ZIP code (78704), a county (Travis County, TX), or paste a realtor.com search link. One search reaches up to 10,000 listings per location.

## `status` (type: `string`):

For sale is the default. Sold reaches realtor.com's archive, which holds far more rows than the live market - Austin alone has over 126,000 sold records.

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

Listings is the fast mode and covers the full search record. Listings + property details calls each property for tax history, assigned schools, flood risk, valuation forecast, the mortgage breakdown and agent contacts. Agents rolls the same listings up into one row per listing agent.

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

How many rows to save for each location. In the agents mode this counts agents, not listings.

## `sort` (type: `string`):

The order realtor.com returns listings in.

## `propertyIds` (type: `array`):

Optional. Property page links or numeric property ids to look up directly, instead of - or in addition to - searching.

## `priceMin` (type: `integer`):

Lowest list price to include. For rentals this is monthly rent.

## `priceMax` (type: `integer`):

Highest list price to include.

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

Fewest bedrooms to include.

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

Most bedrooms to include.

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

Fewest bathrooms to include.

## `sqftMin` (type: `integer`):

Smallest interior area to include, in square feet.

## `sqftMax` (type: `integer`):

Largest interior area to include, in square feet.

## `lotSqftMin` (type: `integer`):

Smallest lot to include, in square feet.

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

Exclude homes built before this year.

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

Exclude homes built after this year.

## `garageMin` (type: `integer`):

Fewest garage spaces to include.

## `hoaFeeMax` (type: `integer`):

Monthly HOA fee ceiling, in dollars.

## `noHoaFee` (type: `boolean`):

Keep only listings with no homeowners association fee.

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

Leave empty for every type.

## `subTypes` (type: `array`):

Narrower categories realtor.com tracks separately from the main property type. Leave empty to ignore.

## `keywords` (type: `array`):

Words that must appear in the listing, for example pool, casita, waterfront.

## `newConstruction` (type: `boolean`):

Keep only newly built homes.

## `foreclosure` (type: `boolean`):

Keep only foreclosure listings.

## `shortSale` (type: `boolean`):

Keep only short sales.

## `contingent` (type: `boolean`):

Keep only listings marked contingent.

## `includePending` (type: `boolean`):

Leave unset for realtor.com's own default. Turn on to include pending sales, off to exclude them.

## `seniorCommunity` (type: `boolean`):

Keep only homes in 55+ communities.

## `hasVirtualTour` (type: `boolean`):

Keep only listings that offer a virtual tour.

## `has3dTour` (type: `boolean`):

Keep only listings with a Matterport 3D walkthrough.

## `catsAllowed` (type: `boolean`):

Rental listings only.

## `dogsAllowed` (type: `boolean`):

Rental listings only.

## `openHouseFrom` (type: `string`):

Only listings with an open house on or after this date.

## `openHouseTo` (type: `string`):

Only listings with an open house on or before this date.

## `listedSince` (type: `string`):

Only listings first published on or after this date.

## `listedUntil` (type: `string`):

Only listings first published on or before this date.

## `soldSince` (type: `string`):

Applies when the status is Sold.

## `soldUntil` (type: `string`):

Applies when the status is Sold.

## `includeMarketContext` (type: `boolean`):

Puts every listing next to its own market: median list price, price per sqft, days on market and rent, for both the city and the county. This is what powers priceVsCityMedianPct, grossRentYieldPct and dealScore. Costs one extra request per city, not per listing.

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

Turn off to keep only the main photo and make the dataset much smaller.

## `downPaymentPercent` (type: `integer`):

Used for the monthly payment estimate when realtor.com does not supply one of its own.

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

realtor.com only serves US addresses, so a US proxy is required. The default datacenter proxy is enough - residential is not needed and would only cost more.

## Actor input object example

```json
{
  "locations": [
    "Austin, TX"
  ],
  "status": "for_sale",
  "mode": "listings",
  "maxResults": 50,
  "sort": "relevant",
  "noHoaFee": false,
  "newConstruction": false,
  "foreclosure": false,
  "shortSale": false,
  "contingent": false,
  "seniorCommunity": false,
  "hasVirtualTour": false,
  "has3dTour": false,
  "catsAllowed": false,
  "dogsAllowed": false,
  "includeMarketContext": true,
  "includePhotos": true,
  "downPaymentPercent": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "BUYPROXIES94952"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `market_analysis` (type: `string`):

No description

## `property_detail` (type: `string`):

No description

## `agents` (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 = {
    "locations": [
        "Austin, TX"
    ],
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("trakk/realtor-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 = {
    "locations": ["Austin, TX"],
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("trakk/realtor-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 '{
  "locations": [
    "Austin, TX"
  ],
  "maxResults": 50
}' |
apify call trakk/realtor-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,trakk/realtor-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/WygbNYjouJu4QzSmU/builds/gPigfDhBLDSb7cFZE/openapi.json
