# Realtor.com Property Search & Change Monitor (`luminar/realtor-property-change-monitor`) Actor

Search public Realtor.com property cards, collect supported exact-property details, compare source values, or monitor verified changes.

- **URL**: https://apify.com/luminar/realtor-property-change-monitor.md
- **Developed by:** [Luka](https://apify.com/luminar) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

Collect public Realtor.com property data for research, lead lists, comparisons, and factual change monitoring. Start with a city, state-qualified place, ZIP code, public search URL, or exact public property URL; the safe default returns ten search-card rows.

The Actor collects only public first-party Realtor.com data. Login, private account data, CAPTCHA solving, and child Actors are excluded. Every run includes a free coverage row so a block, cap, filter, source drift, or confirmed empty result is never disguised as success.

![Realtor.com Properties Search & Change Monitor product preview](https://api.apify.com/v2/key-value-stores/DJgPR6wwS2tIaLDQW/records/realtor_property_change_monitor--6d6a388c927a5e3d-realtor-property-data.png)

### 🚀 Start in 60 seconds

1. Choose **Search properties**.
2. Enter a location such as `Austin, TX`.
3. Keep **Search cards - fastest** and the safe ten-property limit.
4. Run the Actor, then open the **Properties** and **Coverage** Dataset views.

```json
{
  "workflow": "search_properties",
  "location": "Austin, TX",
  "listingStatus": "for_sale",
  "maxProperties": 10,
  "detailLevel": "search_cards"
}
```

### 🎯 Choose the right workflow

| Workflow | Use it for | Verified boundary |
|---|---|---|
| **Search properties** | Build for-sale, rental, or sold-property datasets from a location. | Austin for-sale, for-rent, and sold search cards; one Austin for-sale search with full public details. |
| **Collect exact property URLs** | Enrich known public Realtor.com property URLs. | One exact Austin sale property completed all four declared public-detail groups. One public Austin rental community additionally exposed 5 floorplans and 24 unit-availability records through its anonymous first-party page data. |
| **Monitor market or properties** | Seed a baseline and compare later compatible snapshots. | One exact public property baseline and one unchanged repeat committed safely with zero false changes. |
| **Find comparables** | Compare fetched properties with source-backed reference values. | Two Austin candidates returned with deterministic arithmetic differences. No valuation is inferred. |

The same source operation accepts location and ZIP inputs, but only the boundaries above are included in the verified product promise. Other markets and combinations remain source-dependent.

### 📦 What you get

Every row has a stable identity, row type, idempotent delivery ID, and source-contract version. Source-dependent property fields can include:

- listing and property IDs, canonical URL, status, dates, and currency;
- list, sold, original, and reduced-price values plus deterministic price per square foot;
- property type, beds, baths, living area, lot size, year built, stories, units, garage, HOA, and zoning;
- address, coordinates, description, features, flags, source metadata, and search placement;
- public photos, verified virtual tours, and video links;
- rental-community floorplans with names, beds, baths, square feet, advertised prices, images, availability, and nested public unit records when the verified rental-page contract publishes them;
- agents, advertisers, offices, schools, neighborhoods, history, tax, permit, and environmental-risk records when published;
- field-level provenance and detail-layer coverage instead of silently filled nulls.

Dataset row types are `property`, `change`, `comparable`, and `coverage`. Named views select useful columns while `recordType` remains visible.

The Actor does **not** estimate value, predict appreciation, recommend an investment, or assign a subjective score.

#### Real public rental-detail example

This compact row retains values returned by an anonymous exact-property run. Large arrays and nested objects are omitted for readability.

```json
{
  "recordType": "property",
  "stableId": "realtor-property:7099312028",
  "deliveryId": "realtor-delivery:a676e2c091c467d5f41d3cdbe5df1d90090682fcd10c9dc0",
  "propertyId": "7099312028",
  "listingId": "2983804288",
  "status": "for_rent",
  "listPrice": null,
  "propertyType": "apartment",
  "yearBuilt": 1983,
  "units": 352,
  "address": {
    "line": "11411 Research Blvd",
    "city": "Austin",
    "stateCode": "TX",
    "postalCode": "78759",
    "country": "USA"
  },
  "rentalFloorplanCount": 5,
  "rentalUnitCount": 24,
  "sourceContractVersion": "realtor-public-first-party-v14",
  "detailCoverage": {
    "status": "COMPLETE",
    "completedLayers": [
      "property_details",
      "property_and_tax_history",
      "neighborhoods_and_schools",
      "environmental_risks",
      "rental_floorplans"
    ]
  }
}
```

### 🎛️ Input guide

#### Choose targets and depth

| Parameter | What it changes | Coverage or cost effect |
|---|---|---|
| `workflow` | Selects search, exact-property, monitoring, or comparable output. | Changes the source work and billable event pair. |
| `location` | Sets the primary city/state or ZIP target. | The safe default creates one target. |
| `additionalLocations` | Adds more location targets. | Each location adds source work and its own target receipt. |
| `listingStatus` | Selects `for_sale`, `for_rent`, or `sold`. | Becomes part of the monitoring scope. |
| `searchUrls` | Uses public Realtor.com search URLs instead of generated location targets. | Each URL is a separate target. |
| `propertyUrls` | Supplies exact public Realtor.com sale-detail or rental-detail URLs. | Each property requests the bounded detail contract; rental community pages can add public floorplans and unit availability. |
| `maxProperties` | Caps property, change, or comparable rows. | Main output and cost ceiling: 5,000 search-card rows or 2,000 full-detail rows. |
| `detailLevel` | Chooses fast search cards or full public details. | Full details use four bounded public operations; a public rental page can add one floorplan layer. |

#### Filter and order published values

| Parameter | What it changes | Important behavior |
|---|---|---|
| `propertyTypes` | Keeps selected normalized property types. | Missing source values do not become invented types. |
| `minPrice`, `maxPrice` | Sets a published-price range. | Rental minimum price remains distinct from a single listing price. |
| `minBeds`, `maxBeds` | Sets the bedroom range. | Applied only to published counts. |
| `minBaths`, `maxBaths` | Sets the bathroom range. | Applied only to published counts. |
| `minLivingAreaSqft`, `maxLivingAreaSqft` | Sets the living-area range. | Uses normalized square feet. |
| `minLotSizeSqft`, `maxLotSizeSqft` | Sets the lot-size range. | Uses normalized square feet. |
| `keywords` | Requires terms in published address, description, or features. | Can produce `FILTERED` coverage. |
| `sort` | Preserves source order or sorts by date or price. | Sorting changes the monitoring scope fingerprint. |

#### Monitoring, comparables, and guards

| Parameter | What it changes | Important behavior |
|---|---|---|
| `stateNamespace` | Separates compatible monitoring histories. | Keep it stable across repeats of the same scope. |
| `includeUnchanged` | Adds current unchanged property rows. | Unchanged context is not billed as a change. |
| `referenceProperty` | Supplies source-backed comparable values. | Output is arithmetic difference, never a valuation or score. |
| `maxBuyerChargeUsd` | Checks the maximum possible buyer charge before source work and stops when the requested ceiling is too low. | Buyer-spend guard. |
| `maxPagesPerTarget` | Limits pagination per target. | Reaching it produces `CAPPED`, not false completion. |
| `maxRequests` | Limits all source requests in the run. | Stops before uncontrolled request growth. |
| `maxSourceBytes` | Limits accepted source bytes. | Stops transfer growth. |
| `maxRuntimeSecs` | Limits source-work time. | Stops long source loops. |
| `maxEstimatedPlatformUsd` | Limits estimated platform usage for the run. | Stops before the declared guard is exceeded. |

### 💰 Pricing

`run charge = verified search/comparable targets × target price + one verified exact-property batch gate when that workflow is used + delivered rows × row price`

| Delivered work | Unit price |
|---|---:|
| Search/comparable target, or one exact-property batch | $0.0076 |
| Monitoring target | $0.0040 |
| Search-card property | $0.0012 |
| Full-detail property | $0.00075 |
| Comparable row | $0.0012 |
| Change event | $0.0006 |

For one completed search target, ten search-card properties would be `$0.0196`; one exact-property batch with ten complete full-detail properties would be `$0.0151` regardless of whether the batch contains one or several requested URLs; an unchanged monitoring scan would be `$0.0040`. Free coverage rows and incomplete detail rows do not add result charges. These values never override `maxBuyerChargeUsd`.

### ✅ Coverage you can trust

| Status | Exact fleet meaning |
|---|---|
| `COMPLETE` | Every requested target completed inside declared limits. |
| `PARTIAL` | At least one target or required layer did not complete; returned rows are only the truthful completed portion. |
| `FILTERED` | Source work completed, but deterministic buyer filters removed rows. |
| `CAPPED` | A row, page, request, byte, runtime, or spend guard stopped full coverage. |
| `BLOCKED` | A positively identified challenge or access block stopped public-source collection. |
| `FAILED` | The response did not match the expected first-party contract or another unattributed failure occurred. |
| `EMPTY_CONFIRMED` | The expected first-party response explicitly confirmed zero matching properties. |

Monitoring follows the shared fleet contract:

- the first run that reaches trustworthy coverage seeds a baseline without a false `NEW` flood;
- each repeat run must use the same targets, filters, order, limits, detail depth, and `stateNamespace` to remain comparable;
- `UPDATED` contains only exact normalized fields that changed;
- `ENDED` means only that a stable property identity was absent from **two consecutive complete, comparable scans**;
- `ENDED` never means deleted, sold, inactive, unavailable, or removed from Realtor.com;
- `PARTIAL`, `FILTERED`, `CAPPED`, `BLOCKED`, and `FAILED` runs never evaluate absence and never commit monitoring state;
- state commits only after atomic delivery is acknowledged, so a retry does not duplicate a paid row or event.

### ⚠️ Not yet supported

The product deliberately excludes anything outside the demonstrated supported scope:

- login-only, private, saved, personalized, or account data;
- CAPTCHA solving or continuation after a CAPTCHA;
- a guarantee that every Realtor.com market or every listing on the site is returned;
- floorplans or unit availability for every property: one public Austin rental community proved five floorplans and 24 units, while other properties may publish none;
- populated open-house rows: no live run has returned one;
- guaranteed beds, baths, or living area on every rental community card;
- a claim that a naturally occurring live `NEW`, `UPDATED`, or `ENDED` event has already been observed;
- treating disappearance from a bounded search window as deletion, sale, or unavailability;
- valuations, investment recommendations, popularity scores, sentiment, review analysis, or inferred contact data;
- a fixed source SLA: public source structures can change without notice.

### 🔌 API and automation

The Actor writes standard Apify Dataset and key-value-store output, so a released build can be called from the Apify API and connected to buyer-owned exports or automations. Public Tasks, schedules, webhooks, GitHub packages, n8n flows, and managed promotion are not yet included.

For monitoring, reuse the same input and `stateNamespace`. Changing targets, filters, ordering, limits, or detail depth creates a different scope fingerprint instead of mixing incompatible snapshots.

### ❓ FAQ and support

#### Does an empty Dataset prove there are no properties?

No. Read the free coverage row. Only `EMPTY_CONFIRMED` proves that the expected first-party response explicitly returned zero matching records.

#### Does `ENDED` mean sold or deleted?

No. It is a narrow observation after two complete comparable absences. Use the source-published listing status for business meaning.

#### Does the Actor log in or bypass protection?

No. Login is outside the product and CAPTCHA is a hard stop.

#### Are all listed fields guaranteed on every property?

No. Realtor.com publishes different fields by property and market. `fieldCoverage`, `fieldProvenance`, and `detailCoverage` show exactly what was present and which requested layers completed.

#### How should I report a problem?

Include the Actor run ID, input with secrets removed, coverage status, and the affected public target. Do not share credentials or private data.

Realtor.com and its marks belong to their owner. The bundled small icon is an unchanged official asset linked from Realtor.com's mobile page; it is not generated or redrawn. This independent Actor is not presented as endorsed by Realtor.com.

# Actor input Schema

## `workflow` (type: `string`):

Choose one buyer job. Exact URLs request the verified public detail contract. Monitoring seeds a baseline first and reports only factual source-field changes on later compatible runs.

## `location` (type: `string`):

Primary location for search, monitoring, or comparables. Examples: Austin, TX or 78701.

## `additionalLocations` (type: `array`):

Optional additional cities, state-qualified places, or ZIP codes. Each location becomes a separate coverage target.

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

Select the source market to search. It becomes part of the monitoring scope.

## `maxProperties` (type: `integer`):

Hard result ceiling. Search cards support up to 5,000 rows; full public details support up to 2,000 because each property uses four bounded official operations. Capped monitoring never commits incomplete state.

## `detailLevel` (type: `string`):

Search cards are the cheapest route. Full details additionally requests the public property, history/tax, neighborhood/school, and environmental-risk operations; incomplete detail rows are returned free and never committed to monitoring state.

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

Optional normalized source property types, such as single\_family, condo, or townhome.

## `minPrice` (type: `number`):

Keep properties at or above this source-published price.

## `maxPrice` (type: `number`):

Keep properties at or below this source-published price.

## `minBeds` (type: `number`):

Minimum published bedroom count.

## `maxBeds` (type: `number`):

Maximum published bedroom count.

## `minBaths` (type: `number`):

Minimum published bathroom count.

## `maxBaths` (type: `number`):

Maximum published bathroom count.

## `minLivingAreaSqft` (type: `number`):

Minimum published living area.

## `maxLivingAreaSqft` (type: `number`):

Maximum published living area.

## `minLotSizeSqft` (type: `number`):

Minimum published lot size.

## `maxLotSizeSqft` (type: `number`):

Maximum published lot size.

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

Optional case-insensitive terms checked in published description, address, and feature data.

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

Deterministic output order. Source order preserves the fetched search placement.

## `searchUrls` (type: `array`):

Optional public search pages. When supplied, they replace generated location targets and preserve their canonical URL as scope provenance.

## `propertyUrls` (type: `array`):

Used only by Collect exact property URLs. Only public Realtor.com URLs are supported; login and private account data are excluded.

## `stateNamespace` (type: `string`):

Stable name that separates monitoring snapshots. Changing targets, filters, limits, or sorting creates a different scope fingerprint.

## `includeUnchanged` (type: `boolean`):

Monitoring only. Adds free current property rows alongside paid change events. It does not turn unchanged rows into changes.

## `referenceProperty` (type: `object`):

Comparables only. Supply source-backed values. Output shows arithmetic differences and a declared deterministic order; it does not estimate value or investment quality.

## `maxBuyerChargeUsd` (type: `number`):

When event pricing is active, the run stops before source work if the maximum event vector could exceed this amount. Pricing is not active during private preparation.

## `maxPagesPerTarget` (type: `integer`):

Internal per-target pagination ceiling.

## `maxRequests` (type: `integer`):

Internal run-wide source request ceiling.

## `maxSourceBytes` (type: `integer`):

Internal run-wide source transfer ceiling.

## `maxRuntimeSecs` (type: `integer`):

Internal source-work runtime ceiling.

## `maxEstimatedPlatformUsd` (type: `number`):

Run-wide infrastructure planning ceiling; settled Cloud usage remains required before pricing.

## Actor input object example

```json
{
  "workflow": "search_properties",
  "location": "Austin, TX",
  "listingStatus": "for_sale",
  "maxProperties": 10,
  "detailLevel": "search_cards",
  "sort": "source_order",
  "stateNamespace": "default",
  "includeUnchanged": false,
  "maxBuyerChargeUsd": 1,
  "maxPagesPerTarget": 1,
  "maxRequests": 12000,
  "maxSourceBytes": 1500000000,
  "maxRuntimeSecs": 7200,
  "maxEstimatedPlatformUsd": 1
}
```

# Actor output Schema

## `dataset` (type: `string`):

Open every property, change, comparable, or coverage row.

## `properties` (type: `string`):

Open the mixed Dataset with property columns selected.

## `changes` (type: `string`):

Open the mixed Dataset with change columns selected.

## `comparables` (type: `string`):

Open transparent arithmetic comparison columns.

## `coverage` (type: `string`):

Open completion and cap columns.

## `runSummary` (type: `string`):

Open the authoritative buyer-safe coverage, state, billing, source, and resource summary.

# 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 = {
    "workflow": "search_properties",
    "location": "Austin, TX",
    "listingStatus": "for_sale",
    "maxProperties": 10,
    "detailLevel": "search_cards",
    "sort": "source_order",
    "stateNamespace": "default",
    "includeUnchanged": false,
    "maxBuyerChargeUsd": 1,
    "maxPagesPerTarget": 1,
    "maxRequests": 12000,
    "maxSourceBytes": 1500000000,
    "maxRuntimeSecs": 7200,
    "maxEstimatedPlatformUsd": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("luminar/realtor-property-change-monitor").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 = {
    "workflow": "search_properties",
    "location": "Austin, TX",
    "listingStatus": "for_sale",
    "maxProperties": 10,
    "detailLevel": "search_cards",
    "sort": "source_order",
    "stateNamespace": "default",
    "includeUnchanged": False,
    "maxBuyerChargeUsd": 1,
    "maxPagesPerTarget": 1,
    "maxRequests": 12000,
    "maxSourceBytes": 1500000000,
    "maxRuntimeSecs": 7200,
    "maxEstimatedPlatformUsd": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("luminar/realtor-property-change-monitor").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 '{
  "workflow": "search_properties",
  "location": "Austin, TX",
  "listingStatus": "for_sale",
  "maxProperties": 10,
  "detailLevel": "search_cards",
  "sort": "source_order",
  "stateNamespace": "default",
  "includeUnchanged": false,
  "maxBuyerChargeUsd": 1,
  "maxPagesPerTarget": 1,
  "maxRequests": 12000,
  "maxSourceBytes": 1500000000,
  "maxRuntimeSecs": 7200,
  "maxEstimatedPlatformUsd": 1
}' |
apify call luminar/realtor-property-change-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,luminar/realtor-property-change-monitor"
        }
    }
}

```

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/AxiuWjSJ1sd89vb3q/builds/XF8p1daS0aUardUUa/openapi.json
