# Realtor.com Scraper API — Listings, Prices & Agents (`dami_studio/realtor-com-scraper`) Actor

Scrape Realtor.com property listings at $0.68 per 1,000 — undercuts every established Realtor.com listings scraper on Apify. Address, price, beds, baths, sqft, lot size, type, year built, status, days on market, agent, broker, photos and coordinates. Search by city, ZIP, county or URL.

- **URL**: https://apify.com/dami\_studio/realtor-com-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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/platform/actors/running/actors-in-store#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 API

Pulls property listings from Realtor.com as structured JSON: address, price, beds, baths, square
footage, lot size, property type, year built, listing status, days on market, agent and broker,
photo URLs and coordinates.

Give it a place — `Austin, TX`, `78704`, `Travis County, TX`, `Zilker, Austin, TX` — or paste
Realtor.com URLs. It reads the same JSON gateway the Realtor.com website uses, so there is no
browser and no HTML parsing, and a page of 200 listings comes back in about a second.

### What you get

One row per listing, 65 fields. A real row from a live run:

```json
{
  "propertyId": "8496361588",
  "url": "https://www.realtor.com/realestateandhomes-detail/1606-Yoakum-St-254_Austin_TX_78748_M84963-61588",
  "address": "1606 Yoakum St Unit 254",
  "city": "Austin", "stateCode": "TX", "postalCode": "78748", "county": "Travis",
  "latitude": 30.165248, "longitude": -97.825649,
  "price": 365000, "pricePerSqft": 213,
  "beds": 3, "baths": 3, "sqft": 1714, "lotSqft": 2178,
  "propertyType": "single_family", "yearBuilt": 2007,
  "listingStatus": "for_sale", "mlsStatus": "Active",
  "listDate": "2026-08-08T19:44:34Z", "daysOnMarket": 0,
  "agentName": "MIKE MINNS", "brokerName": "Atlas Realty",
  "photoCount": 30, "primaryPhoto": "http://ap.rdcpix.com/...jpg"
}
```

Full field list: `propertyId`, `listingId`, `url`, `address`, `addressWithheld`, `city`, `stateCode`, `state`,
`postalCode`, `county`, `countyFips`, `latitude`, `longitude`, `price`, `priceMin`, `priceMax`,
`pricePerSqft`, `priceReducedAmount`, `lastPriceChangeAmount`, `lastPriceChangeDate`,
`lastSoldPrice`, `lastSoldDate`, `estimatedValue`, `hoaFee`, `beds`, `baths`, `bathsFull`,
`bathsHalf`, `sqft`, `lotSqft`, `yearBuilt`, `propertyType`, `propertySubType`, `stories`, `garage`,
`buildingName`, `listingStatus`, `mlsStatus`, `listDate`, `daysOnMarket`, `lastUpdateDate`,
`isNewListing`, `isPending`, `isContingent`, `isForeclosure`, `isPriceReduced`, `isNewConstruction`,
`agentName`, `agentEmail`, `agentMlsId`, `brokerName`, `brokerEmail`, `brokerPhone`, `mlsSourceId`,
`mlsSourceType`, `photoCount`, `primaryPhoto`, `photos`, `virtualTourUrl`, `hasMatterport`,
`openHouses`, `features`, `searchLocation`, `resolvedLocation`, `position`, `scrapedAt`.

Turn on **Include full property details** to also get `descriptionText`, `taxHistory`,
`priceHistory`, `schools`, `neighborhoods`, `propertyDetails` and `valueEstimates`. That costs one
extra request per listing, so the run is slower. It adds fields, not rows, so it does not change
what you are charged.

### Input

| Field | What it does |
|---|---|
| `location` | One or more places. `City, ST`, a 5-digit ZIP, a county, a neighborhood, or a state code. |
| `startUrls` | Realtor.com search or property URLs. Filters in the URL (`price-`, `beds-`, `type-`, `show-recently-sold`) are honoured. |
| `listingStatus` | `for_sale`, `for_rent`, `sold`, `off_market`, `ready_to_build`. |
| `propertyTypes` | `single_family`, `condos`, `townhomes`, `condo_townhome_rowhome_coop`, `multi_family`, `mobile`, `land`, `farm`. |
| `maxItems` | Hard cap on rows. You pay per row returned. |
| `sortBy` | `newest`, `oldest`, `price_low`, `price_high`, `sold_date`, `most_photos`. |
| Filters | price, beds, baths, sqft, lot size, year built, listed/sold within N days, open house, new construction, foreclosure, keywords. |

### Numbers from real runs

- Austin, TX has 7,297 active for-sale listings and 126,304 recently sold. Both are reachable.
- 200 listings per request is the API's hard ceiling; 201 is rejected outright.
- **248 listings in 13.6 seconds** (Austin, TX, for sale). A 5-row run finished in 2.3 seconds.
- Duplicates are removed across pages, so asking for 250 can return 248. You are only charged for
  the rows you actually get.
- No proxy is used. Realtor.com's JSON gateway answers plain datacenter addresses, so proxy cost is
  zero. You can still point the actor at your own proxy if you want a specific exit.

### What this does not do

- **It cannot page deeper than 10,000 results in a single search.** That is the API's limit, not a
  choice. A search matching more than that emits an uncharged `RESULT_CAP` diagnostic telling you so.
  Split the area by ZIP code, or add filters, to get the rest.
- **`lastSoldPrice` is empty in non-disclosure states.** Sale prices are not public record in Texas,
  and a few other states. Measured on 20 sold listings per city: Miami 20/20 populated, Los Angeles
  20/20, Phoenix 20/20, Chicago 20/20 — **Austin 0/20**. `lastSoldDate` is present everywhere. This
  is how the data is; no scraper can return a price the MLS does not publish.
- **`agentEmail` and `brokerEmail` are usually empty.** Realtor.com rarely exposes them on listings.
  This is a listings scraper, not an agent-contact scraper.
- **Some listings withhold the street address.** Realtor.com sends the literal text
  "Address Not Available" for those. The actor returns `address: null` and `addressWithheld: true`
  rather than passing that string off as an address. Everything else on the row is still real.
- United States only. Realtor.com has no international inventory.
- No Zillow, no Redfin, no Realtor.ca (that is Canada, a different company).
- It does not log in, and it does not touch anything behind an account.

### Pricing

**$0.68 per 1,000 listings** ($0.00068 each), plus $0.001 each time a run starts — the lowest
per-listing price of any Realtor.com scraper on the Apify Store with an active user base; the next
cheapest, `solidcode/realtorcom-scraper` (20 monthly users), is $0.80 per 1,000 even on its cheapest
volume tier.

You are charged only for listings actually returned. Failed runs, blocked runs, empty searches and
every diagnostic row carry no per-listing fee, so a run that returns no listings costs the $0.001
start fee and nothing more.

### FAQ

**How do I scrape Realtor.com listings for a city?**
Set `location` to `Austin, TX` and run it. Use `maxItems` to decide how many rows you want.

**Can I scrape by ZIP code?**
Yes. Put the 5-digit ZIP in `location`, for example `78704`. County (`Travis County, TX`) and
neighborhood (`Zilker, Austin, TX`) also work.

**Can I get recently sold homes?**
Yes. Set `listingStatus` to `sold`, and optionally `soldWithinDays`. Sort with `sold_date` to get
the most recent sales first. Note the non-disclosure-state caveat above for the sale price itself.

**Can I get rentals?**
Yes, set `listingStatus` to `for_rent`.

**Does it return the listing agent and brokerage?**
Yes — `agentName`, `agentMlsId`, `brokerName`, and `brokerPhone` when Realtor.com publishes them.
Email addresses are rarely published.

**How many listings can I get from one search?**
Up to 10,000 per search. Beyond that, split by ZIP code or add filters — the actor tells you when
you have hit the ceiling instead of quietly stopping.

**Why did my property-type filter return nothing?**
Realtor.com's value is `condos`, plural. `condo` matches zero listings without raising an error.
The actor validates the value and warns you instead of returning an empty result.

**Do I need a proxy?**
No. None is used by default and none is needed.

**What happens if the search returns nothing?**
You get one diagnostic row explaining why, and it carries no per-listing fee. The run still pays the
$0.001 start fee, so an empty search costs $0.001.

**Is this the official Realtor.com API?**
No. This is an independent scraper. It is not affiliated with or endorsed by Move, Inc. or the
National Association of REALTORS®.

### Legal

Realtor.com's `robots.txt` opens with a notice that scraping is unauthorized without written
permission from Move Sales, Inc., and its Terms of Service say the same. `robots.txt` does not list
the JSON gateway this actor uses, and it explicitly disallows deep pagination of the HTML search
pages (`/realestateandhomes-search/*/*/pg-`). Listing data on Realtor.com originates from MLS feeds
and is usually subject to IDX attribution and redistribution rules set by the individual MLS.

You are responsible for how you use the output. Check your own obligations — including MLS
attribution, and privacy law where agent details are involved — before republishing or redistributing
anything this returns.

# Actor input Schema

## `location` (type: `array`):

Where to search on Realtor.com. One per line. Accepts "City, ST" (Austin, TX), a 5-digit ZIP (78704), a county ("Travis County, TX"), a neighborhood ("Zilker, Austin, TX") or a state code (TX). United States only.

## `startUrls` (type: `array`):

Optional. Paste Realtor.com search pages (https://www.realtor.com/realestateandhomes-search/Austin\_TX) or single property pages (https://www.realtor.com/realestateandhomes-detail/...\_M84963-61588). Filters written into the URL (price-, beds-, type-, show-recently-sold) are honoured. Works alongside "location".

## `listingStatus` (type: `string`):

Which listings to return. "sold" covers recently sold homes; "off\_market" covers homes no longer listed.

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

Optional. Leave empty for every type. Note that Realtor.com's own value is "condos" (plural) — "condo" matches nothing.

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

Hard cap on rows returned across every location and URL. You are charged once per listing returned. Realtor.com's API cannot page deeper than 10,000 results per search — split by ZIP code to go beyond that.

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

Order the listings come back in.

## `includePropertyDetails` (type: `boolean`):

Adds the listing description text, tax history, price history, nearby schools and value estimates to every row. Costs one extra request per listing, so the run is slower. It adds fields, never extra rows, so it does not change what you are charged.

## `maxPhotos` (type: `integer`):

How many photo URLs to keep per listing (0-50). Realtor.com returns up to 50.

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

Optional lowest list price.

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

Optional highest list price.

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

Optional.

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

Optional.

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

Optional.

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

Optional.

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

Optional.

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

Optional. 1 acre = 43,560 sqft.

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

Optional.

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

Optional.

## `listedWithinDays` (type: `integer`):

Optional. Only listings first posted in this window. Use with status "For sale".

## `soldWithinDays` (type: `integer`):

Optional. Only homes sold in this window. Use with status "Recently sold".

## `hasOpenHouse` (type: `boolean`):

Optional.

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

Optional.

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

Optional.

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

Optional. Words that must appear in the listing, for example "pool", "waterfront", "garage".

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

Optional. This actor talks to Realtor.com's own JSON gateway, which answers plain datacenter addresses, so no proxy is needed and none is used by default. Supply your own proxy URLs only if you want the traffic to exit somewhere specific.

## Actor input object example

```json
{
  "location": [
    "Austin, TX"
  ],
  "startUrls": [],
  "listingStatus": "for_sale",
  "propertyTypes": [],
  "maxItems": 50,
  "sortBy": "newest",
  "includePropertyDetails": false,
  "maxPhotos": 30,
  "hasOpenHouse": false,
  "newConstruction": false,
  "foreclosure": false,
  "keywords": [],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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 = {
    "location": [
        "Austin, TX"
    ],
    "startUrls": [],
    "listingStatus": "for_sale",
    "propertyTypes": [],
    "maxItems": 50,
    "sortBy": "newest",
    "maxPhotos": 30,
    "keywords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/realtor-com-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 = {
    "location": ["Austin, TX"],
    "startUrls": [],
    "listingStatus": "for_sale",
    "propertyTypes": [],
    "maxItems": 50,
    "sortBy": "newest",
    "maxPhotos": 30,
    "keywords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/realtor-com-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 '{
  "location": [
    "Austin, TX"
  ],
  "startUrls": [],
  "listingStatus": "for_sale",
  "propertyTypes": [],
  "maxItems": 50,
  "sortBy": "newest",
  "maxPhotos": 30,
  "keywords": []
}' |
apify call dami_studio/realtor-com-scraper --silent --output-dataset

```

## MCP server setup

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