# Redfin Scraper & New Listings Monitor - Price Drop Alerts (`neverempty/redfin-listings-monitor`) Actor

For investors, agents and home buyers who want new-listing alerts: Redfin homes for sale by city, ZIP, neighborhood or county, newest first, with price, beds, baths, sqft, lot, year built, HOA, days on market and photos. Watch mode returns only new listings and price drops. Export as CSV or Excel.

- **URL**: https://apify.com/neverempty/redfin-listings-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 listing returneds

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

## Redfin Scraper & New Listings Monitor

**A Redfin scraper with alerts for new listings and price drops.** Get Redfin homes for sale in any US city, ZIP code, neighborhood or county, **newest on Redfin first**, as clean rows: price in USD, beds, baths, square feet, price per square foot, lot size, year built, property type, HOA fee, days on market, address, coordinates, open house times and photos. Turn on **watch mode** and schedule it: each run returns only the homes that appeared on Redfin since your last check and the homes whose price went down.

Built for real estate investors who want new deals before others see them, agents watching their farm area, and home buyers who do not want to refresh Redfin all day.

Export as JSON, CSV or Excel, or push new homes to Slack, email or a sheet with an Apify integration.

### What you get

One row per home for sale:

| Field | Example | Notes |
|---|---|---|
| `listingId`, `propertyId`, `url` | `224265850`, `31078537`, `https://www.redfin.com/TX/Austin/.../home/31078537` | Redfin's own IDs and link |
| `listingStatus` | `Active`, `Coming Soon`, `Price Change` | As Redfin labels it |
| `price`, `currency`, `pricePerSqft` | `2995000`, `USD`, `641` | List price. Homes without a shown price get `null` (never 0) |
| `beds`, `baths`, `fullBaths`, `partialBaths` | `4`, `4.5`, `4`, `1` | As listed |
| `sqft`, `lotSizeSqft`, `yearBuilt`, `stories` | `4673`, `8925`, `2010`, `2` | |
| `propertyType`, `propertyTypeCode` | `house`, `1` | house, condo, townhouse, multi-family, land, other, manufactured, co-op |
| `hoaFee` | `295` | When the listing shows one |
| `address`, `unit`, `city`, `state`, `zip`, `subdivision`, `latitude`, `longitude` | `6932 Cielo Azul Pass`, `Austin`, `TX`, `78732` | |
| `daysOnMarket`, `listedAt` | `1`, `2026-10-09T15:49:00.000Z` | `listedAt` is the time the home appeared on Redfin, worked out from Redfin's own "time on Redfin" when the page was read (to the minute) |
| `openHouseStart`, `openHouseEnd` | | Next open house, when there is one |
| `badges`, `keyFacts` | `["New", "Open House"]`, `["Pool", "2 garage spots"]` | The labels and key facts Redfin shows on the home card |
| `isComingSoonOrEarlyAccess`, `isNewConstruction`, `hasVirtualTour` | | |
| `remarksPreview` | | The start of the listing remarks as Redfin shows it in search results (up to about 700 characters). Phone numbers and e-mails are replaced with `[phone removed]` / `[email removed]` |
| `photoCount`, `imageUrl`, `imageUrls` | `39` | Main photo and up to 20 photo links |
| `changeType`, `previousPrice`, `priceChange` | `new`, `price-drop` | Watch mode only |
| `positionInSearch`, `listingsInSearch`, `searchPlace` | `1`, `5939`, `Austin, TX` | Where the home was in the search, and how many homes Redfin counts for it |

In a sample of 2,031 homes from Austin, Dallas, Houston, New York (10001), San Francisco (94110), Chicago (60614) and two Austin ZIP codes (2026-10-10): price was present in 2,023; beds in 1,984; baths in 1,948; square feet in 1,833; lot size in 1,714; year built in 1,901; days on market in 1,935; a main photo in 1,982. The median home had 26 photos.

### How to use it

**Plain search**: put places in `locations`, one per line. Use a 5-digit ZIP code, or open the place on redfin.com and copy the address of its page (a city, ZIP code, neighborhood or county page), without the `/filter/...` part.

```json
{ "locations": ["https://www.redfin.com/city/30818/TX/Austin", "78704"], "maxResultsPerSearch": 100 }
```

Filters: `propertyTypes`, `minPrice`, `maxPrice`, `minBeds`, `minBaths`. Redfin applies them, and every row is checked again against your values before it is returned.

```json
{ "locations": ["https://www.redfin.com/city/30794/TX/Dallas"], "propertyTypes": ["house", "townhouse"], "minPrice": 300000, "maxPrice": 550000, "minBeds": 3 }
```

**Watch mode** (`onlyNew: true`): run the same input on a schedule (for example every hour).

1. The first run returns the newest homes (up to `maxResultsPerSearch`) and remembers every home it read as the starting point.
2. Every later run returns only:
   - `new`: homes that appeared on Redfin after the watch started and were not returned before;
   - `price-drop`: remembered homes whose list price is now lower, with `previousPrice` and `priceChange`.
3. If nothing changed, you get one free row `no-new-listings` saying so.

Use `watchName` to keep two separate watches of the same search, and `resetMonitoringState` to start a watch again.

### Output rows that cost nothing

Every problem comes back as a row with `status` and a plain-English `note`, and is never charged:

| `status` | Meaning |
|---|---|
| `no-results` | Redfin lists no home for sale for this place |
| `none-matching-filters` | Homes exist, but none match your filters |
| `no-new-listings` | Watch mode: nothing new and no price drop since the last check |
| `watch-coverage` | Watch mode, first run: how much of the search the watch covers |
| `more-not-returned` | More homes exist than were returned, and why |
| `not-found` | The ZIP code or page does not exist on Redfin, or the address names a different place than its number |
| `blocked` | Redfin showed a check page on every connection tried. This Actor does not solve check pages |
| `unreadable` | The page could not be read or did not show your filters; nothing is guessed |
| `budget-reached` | The run reached the maximum total charge you set |
| `bad-input` | The input could not be used |

### Pricing

You pay per home returned (`listing-returned`). In watch mode, a check that finds nothing new for a place costs one `search-checked` event. Reason rows are free.

### How it works

The Actor opens Redfin's public search page for each place, sorted by newest, and reads the list of homes the page itself carries. It follows Redfin's robots.txt, does not log in, and does not solve CAPTCHAs. It waits between pages.

### Good to know

- **Redfin shows at most 350 homes per search.** This Actor reads the newest 350. For a big city, a watch run every hour or two is enough to catch every new listing; a price drop on an older home that is not among the newest 350 is not seen. Use a ZIP code, a price range or a property type to make a search smaller.
- For sale only. Rentals and sold homes are not included.
- No personal data: listing agents' names, phone numbers and e-mails are not collected. The brokerage name is only on each home's own page, which this Actor does not open.
- When Redfin has only a few homes for a search, its page also shows "nearby homes" outside the place. Those are never returned.
- Rows are the homes Redfin itself lists for the place. Near a border, the postal `city` or `zip` of a few homes can differ from the place searched (in a Dallas search on 2026-10-10, 316 of 350 had the postal city Dallas; the rest were Dallas-area addresses such as Rowlett or Mesquite).
- Redfin decides the place by the number in the address. If the name in your address does not match that number (for example `/city/30818/TX/Dallas`, which is Austin), you get a free `not-found` row instead of the wrong city.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

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

One per line: a 5-digit ZIP code (78704) or the address of a Redfin city, ZIP, neighborhood or county page, such as https://www.redfin.com/city/30818/TX/Austin (open the place on redfin.com and copy the address without /filter/). Up to 20 places per run. If empty, Austin, TX is searched.

## `maxResultsPerSearch` (type: `integer`):

How many homes for sale to return for each place, newest on Redfin first (1 to 350; Redfin shows at most 350 per search). Empty means 50. In watch mode this caps what one run returns; the rest comes in later runs.

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

Optional. Only these property types, as Redfin classifies them. Empty means all types.

## `minPrice` (type: `integer`):

Optional. Only homes listed at or above this price in US dollars. Homes without a shown price are left out when this is set. Empty means no minimum.

## `maxPrice` (type: `integer`):

Optional. Only homes listed at or below this price in US dollars. Empty means no maximum.

## `minBeds` (type: `integer`):

Optional. Only homes with at least this many bedrooms (1 to 10). Homes that do not state bedrooms are left out when this is set. Empty means any.

## `minBaths` (type: `integer`):

Optional. Only homes with at least this many bathrooms (1 to 10; half baths count as 0.5). Empty means any.

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

Run the same input on a schedule. The first run returns the newest listings and remembers them; later runs return only homes that appeared on Redfin since then and remembered homes whose price went down. Empty means off (a plain search).

## `includePriceDrops` (type: `boolean`):

In watch mode, also return remembered homes whose list price went down, with the previous price. Empty means on.

## `watchName` (type: `string`):

Optional. Keeps separate memories for separate watches of the same place and filters (letters, digits, dot, dash, underscore). Empty means the default watch.

## `resetMonitoringState` (type: `boolean`):

Forget what this watch remembered and treat this run as the first check. Empty means off.

## Actor input object example

```json
{
  "locations": [
    "https://www.redfin.com/city/30818/TX/Austin"
  ],
  "maxResultsPerSearch": 50,
  "onlyNew": false,
  "includePriceDrops": true,
  "resetMonitoringState": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per Redfin home for sale, newest on Redfin first: listing ID, link, status, price in USD, beds, baths, square feet, price per square foot, lot size, year built, property type, HOA fee, address, ZIP, coordinates, days on market, listing time, open house, badges, key facts, the start of the listing remarks and photos. Watch mode marks rows first-check, new or price-drop (with the previous price). A place with no homes, nothing new, an unknown place, a check page or a run that hit its maximum charge comes back as a free row that says why.

# 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": [
        "https://www.redfin.com/city/30818/TX/Austin"
    ],
    "maxResultsPerSearch": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/redfin-listings-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 = {
    "locations": ["https://www.redfin.com/city/30818/TX/Austin"],
    "maxResultsPerSearch": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("neverempty/redfin-listings-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 '{
  "locations": [
    "https://www.redfin.com/city/30818/TX/Austin"
  ],
  "maxResultsPerSearch": 50
}' |
apify call neverempty/redfin-listings-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/redfin-listings-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/I33hNoVDbMnb1LKey/builds/2RWCvs5zsXIyMRDsP/openapi.json
