# Redfin Scraper - For Sale, Sold Comps & Every Listing (`webdata_labs/redfin-scraper`) Actor

\[$0.50 / 1K listings] Scrape Redfin for-sale listings and sold comps from any search URL or ZIP code, past the 350-per-search cap, with listing agent, days on market and badges. New-only monitoring. No start fee.

- **URL**: https://apify.com/webdata\_labs/redfin-scraper.md
- **Developed by:** [WebData Labs](https://apify.com/webdata_labs) (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

from $0.40 / 1,000 listings

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 - For Sale, Sold Comps & Every Listing

**Paste any Redfin search and get every matching home as a clean row, for sale or recently sold, past Redfin's 350-per-search cap, at $0.50 per 1,000 listings with no start fee.**

Redfin shows at most 350 homes for one search, so a scraper that just reads the search results quietly stops at 350 while Austin alone has around 6,000 homes for sale. This Actor asks Redfin how many homes match first, splits big searches into price bands until each one fits, and stitches them back together without duplicates. You keep every filter you set on Redfin, get sold comps with their sale dates, and can schedule it to return only the listings that are new since the last run.

### ✅ What you get / ❌ what this isn't

| ✅ What you get | ❌ What this isn't |
|---|---|
| Every listing in a search, split into price bands automatically when Redfin has more than 350 | Not a hard stop at the first 350 |
| The filters from your Redfin URL, applied exactly (price, beds, baths, type, sold window, sort) | Not a scraper that ignores half the URL |
| Sold comps with sale price and sale date, from 1 week to 5 years back | Not active listings only |
| Days on market, listing date, price per sq ft, HOA, lot size, year built | Not just price and address |
| Redfin's own badges (Price Drop, Open House, Coming Soon, New) and key facts | Not a bare listing list |
| Only-new mode that remembers what it already returned | Not paying again for the same listings every day |
| $0.50 per 1,000 listings, no start fee | Not a per-run fee before any row exists |

### 🔎 Why use this Actor

- **Complete coverage.** Before fetching, the Actor asks Redfin how many homes match. When the answer is above 350, it splits the price range in half and asks again, until each band holds 350 or fewer, then fetches every band. In testing, a search for Austin condos matching 1,429 homes returned 1,428.
- **Your Redfin filters, not an approximation.** Paste the URL from your browser after setting filters on Redfin. The filter part of the URL is translated by Redfin itself into its search parameters, so what you get is what the website shows.
- **Sold comps.** Switch **Listings** to **Sold**, or paste a Redfin URL that already shows sold homes, and every row carries `soldDate` and the sale price. Useful for comparable-sales analysis and price-per-square-foot studies.
- **New-listing monitoring.** Turn on **Only new listings since the last run** and schedule it. Each search remembers the listings it already returned, so every run delivers only what is new, and you are only charged for those.
- **ZIP codes too.** No URL handy? Give ZIP codes and set price, beds, baths and property type in the form.
- **Fast and light.** It reads Redfin's own search data rather than rendering pages: 350 listings in about 4 seconds, 1,400 in under 30.

### 👥 Who it's for

Real-estate investors, agents and brokerages, proptech and data teams, and anyone pricing or tracking a US housing market.

- Pull every active listing in a city or ZIP and screen by price per square foot, days on market or HOA.
- Build a comps set: all homes sold in a ZIP in the last 3 or 6 months, with sale price, size and date.
- Get a daily feed of new listings matching your buy box, and act before other buyers.
- Track which listings show a Price Drop badge in a market.
- Map listings with latitude and longitude for a market study.

### ⚙️ How to scrape Redfin

1. Open [Redfin](https://www.redfin.com), search a city, ZIP code, county or neighborhood, and set any filters you want (price, beds, home type, sold).
2. Copy the URL from the address bar into **Redfin search URLs**. Add as many as you like.
3. Or put **ZIP codes** in instead and use the filter fields below them.
4. Choose **For sale** or **Sold (comps)**, and set **Maximum listings per search** (`0` = every listing).
5. Click **Start**. Export the results from the **Output** or **Storage** tab as JSON, CSV or Excel.

#### Get only new listings every day

Turn on **Only new listings since the last run**, save the input as a task, and add a daily schedule. The first run returns everything that matches; each run after that returns only listings it has not returned before, so you pay only for new ones. The memory is kept per search, so different URLs or filters never mask each other.

### 📥 Input

```json
{
  "searchUrls": ["https://www.redfin.com/city/30818/TX/Austin/filter/property-type=house,min-price=400k,max-price=800k,min-beds=3"],
  "zipCodes": ["78704"],
  "listingType": "for-sale",
  "maxResultsPerSearch": 0,
  "onlyNewListings": false
}
```

- `searchUrls` - Redfin search pages (city, ZIP code, county or neighborhood), with or without filters.
- `zipCodes` - US ZIP codes to search.
- `listingType` - `for-sale` (default) or `sold`. A URL that already has a sold filter keeps it.
- `soldWithinDays` - for sold listings, how far back. Default `90`. Redfin's windows are 7, 30, 90, 180, 365, 730, 1095 and 1825 days; other values round up.
- `maxResultsPerSearch` - listings per URL or ZIP. Default `100`. `0` returns every listing, splitting large searches automatically.
- `propertyTypes` - any of `house`, `condo`, `townhouse`, `multifamily`, `land`, `manufactured`, `co-op`, `other`.
- `minPrice`, `maxPrice`, `minBeds`, `minBaths` - filters for ZIP codes, and for URLs that do not set their own.
- `onlyNewListings` - return only listings not returned by an earlier run of the same search.

`startUrls`, `urls`, `maxResults` and `maxItems` are accepted as aliases, so input written for another Redfin Actor usually runs as is.

### 📤 Output

| address | city | price | beds | baths | sqft | status | daysOnMarket | badges |
|---|---|---|---|---|---|---|---|---|
| 2825 22nd Ave W | Seattle | 1,950,000 | 6 | 3.75 | 3,538 | Coming Soon | 2 | Coming Soon, 3D Walkthrough |
| 4502 Avenue H | Austin | 799,000 | 3 | 2 | 1,560 | Coming Soon | 1 | Early Access, Sotheby's Realty Coming Soon |

Each row also carries `propertyId`, `listingId`, `url`, `unit`, `state`, `zip`, `neighborhood`, `propertyType`, `lotSqft`, `pricePerSqft`, `yearBuilt`, `hoaMonthly`, `listedAt`, `soldDate` (sold rows), `latitude`, `longitude`, `listingAgentName`, `listingAgentRedfinId`, `brokerName`, `mlsNumber`, `keyFacts`, `listingTags`, `description` (the listing remarks), `isNewConstruction`, `isHot`, `hasVirtualTour`, `openHouseStart`, and `searchUrl` / `searchLabel` to say which search produced it. The run summary (`OUTPUT` in the key-value store) lists, per search, the region, the filter applied, how many homes matched on Redfin and how many were returned.

#### All output fields

| Field | What it is |
|---|---|
| `propertyId` | Redfin property id |
| `listingId` | Redfin listing id |
| `url` | Listing page on Redfin |
| `status` | MLS status: Active, Coming Soon, Pending, Closed and so on |
| `listingType` | for-sale or sold |
| `price` | List price, or sale price for sold listings, USD |
| `soldDate` | Sale date for sold listings, ISO 8601 |
| `address` | Street address |
| `unit` | Unit number |
| `city` | City |
| `state` | State |
| `zip` | ZIP code |
| `neighborhood` | Neighborhood as Redfin names it |
| `propertyType` | house, condo, townhouse, multi-family, land, manufactured, co-op or other |
| `beds` | Bedrooms |
| `baths` | Bathrooms |
| `sqft` | Interior square feet |
| `lotSqft` | Lot size, square feet |
| `pricePerSqft` | Price per square foot, USD |
| `yearBuilt` | Year built |
| `hoaMonthly` | HOA dues per month, USD |
| `daysOnMarket` | Days on market |
| `listedAt` | When the listing appeared on Redfin, ISO 8601 (for-sale listings) |
| `latitude` | Latitude |
| `longitude` | Longitude |
| `listingAgentName` | Listing agent |
| `listingAgentRedfinId` | Listing agent's Redfin id, when they have one |
| `brokerName` | Listing brokerage, when Redfin shows it |
| `mlsNumber` | MLS number, when the MLS allows Redfin to show it |
| `badges` | Redfin badges on the card: Price Drop, Open House, New, Coming Soon, 3D Walkthrough and so on |
| `keyFacts` | Redfin's highlighted features |
| `listingTags` | Feature tags extracted from the listing |
| `description` | Listing remarks |
| `isNewConstruction` | New construction |
| `isHot` | Redfin marks the home as hot (likely to sell fast) |
| `hasVirtualTour` | Has a 3D, video or virtual tour |
| `openHouseStart` | Next open house start, ISO 8601 |
| `searchUrl` | The search the row came from |
| `searchLabel` | Region name of that search |
| `scrapedAt` | When the row was collected, ISO 8601 |

### 💵 How much does it cost?

**$0.50 per 1,000 listings** on the Free plan, down to $0.40 on higher Apify plans, charged per listing returned as `listing-scraped`. There is **no start fee**, so a search that matches nothing costs nothing, and in only-new mode you pay only for new listings. Every listing for sale in Austin (around 6,000 homes) costs about $3.

### 🔁 Run it on the Apify platform

Save a search as a task and schedule it daily or weekly, call it from the Apify API, and export as JSON, CSV, Excel or XML. Webhooks and the Make, Zapier and n8n integrations can push new listings into a sheet, a CRM or a Slack channel as they appear.

#### Use with AI agents via MCP

Add Apify's MCP server to Claude Code, Claude Desktop or Cursor and ask the agent to run `webdata_labs/redfin-scraper` on a Redfin URL, then analyze the rows: median price per square foot by ZIP, days on market by price band, or the cheapest three-bedroom houses near a point. Keep your Apify token in the client's secret settings, not in a prompt.

#### Use this Actor in n8n

Call the Actor's run endpoint from an HTTP Request node (or `run-sync-get-dataset-items` for small searches), store the Apify token in n8n credentials, and map the dataset items onward. A typical flow: daily schedule, a run with only-new mode on over your buy-box URL, and an email or Slack message per new listing.

### ⚠️ Limits and caveats

- **US listings on Redfin only.** Redfin's Canadian pages are not supported.
- **Rentals are not included.** This Actor covers homes for sale and sold homes; Redfin's rental search is a separate system.
- **Listing agent coverage depends on the MLS.** Some MLSs let Redfin show the listing agent on search results (Seattle: nearly every listing) and some do not (Austin: a small share). When Redfin does not show it, `listingAgentName` is empty; agent phone numbers and emails are not in Redfin's search data.
- **Some fields depend on the MLS too.** `mlsNumber`, `brokerName` and a few sold prices are hidden by some MLSs and come back empty rather than guessed.
- **Identical prices can exceed the cap.** If more than 350 homes in one search share exactly the same price, the band cannot be split further and the extra ones are counted in the run summary as `missedAtIdenticalPrice`. This is rare.
- **Search pages for ZIP codes are read once per ZIP** to find Redfin's internal region id; city, county and neighborhood URLs need no page at all.
- **`listedAt` is derived** from Redfin's time-on-site counter, so it is accurate to the minute of the run, not the MLS listing timestamp.

### 🧩 Related Actors

- **[Idealista Scraper](https://apify.com/webdata_labs/idealista-scraper)** - the same job for Spain, Italy and Portugal.
- **[Idealista Price Drop Scraper](https://apify.com/webdata_labs/idealista-price-drop-scraper)** - price-drop tracking on European listings.
- **[Craigslist Scraper](https://apify.com/webdata_labs/craigslist-scraper)** - for-sale-by-owner homes and rentals that never reach Redfin.
- **[Google Maps Business Scraper](https://apify.com/webdata_labs/google-maps-business-scraper)** - find the brokerages and agents behind the listings.
- **[Website Email Scraper](https://apify.com/webdata_labs/website-contact-extractor)** - turn a brokerage website into contact details.

### ❓ FAQ

#### Can I really get more than 350 listings per search?

Yes. Set **Maximum listings per search** to `0`. Searches with more matches are split into price bands, each fetched in full, and duplicates removed.

#### Does it keep the filters from my Redfin URL?

Yes. Everything after `/filter/` in the URL is translated by Redfin's own search into the same parameters the website uses, including sort order and sold windows.

#### How do I get sold comps?

Set **Listings** to **Sold (comps)** and pick **Sold within (days)**, or paste a Redfin URL that already shows sold homes. Each row carries `soldDate`.

#### How does only-new mode know what is new?

It keeps the ids of listings it returned, per search, in a named store on your Apify account. The next run of the same search skips those ids. Listings beyond your result limit are not marked as seen, so a capped run never hides them.

#### Am I charged when nothing matches?

No. There is no start fee; you pay only per listing returned.

#### Is it legal to scrape Redfin?

Scraping publicly available data can be lawful in many situations, but it depends on your jurisdiction, purpose and Redfin's terms. This Actor reads only what Redfin shows any logged-out visitor, and does not log in or bypass access controls. Listing data can be subject to MLS rules, so check them for commercial redistribution, and get legal advice for high-risk use.

#### Is this a Redfin API?

Effectively yes: run it over the Apify API and read structured JSON, CSV or Excel with stable field names.

### Changelog

- **2026-09-26** - First release: search URLs with their own filters, ZIP codes with filter fields, for-sale and sold listings, automatic price-band splitting past the 350-per-search cap, only-new monitoring, and pay-per-listing pricing with no start fee.

### 🛠️ Support

Something wrong or missing? Open an Actor issue with the run URL, the input you used and what you expected. That is the fastest route to a fix.

### ⭐ Rate this Actor

If this saved you time, please leave a rating on the **Reviews** tab. Review count is the main trust signal buyers have on the Store, and reviews decide which Actors get improved next. If something is broken, please open an issue first so it can be fixed.

# Actor input Schema

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

Paste any Redfin search page: a city, ZIP code, county or neighborhood, with or without filters, for example https://www.redfin.com/city/30818/TX/Austin/filter/property-type=house,min-beds=3. Every filter you set on Redfin (price, beds, type, sold window, sort) is kept.

## `zipCodes` (type: `array`):

US ZIP codes to search, for example 78701. The filters below apply to them.

## `listingType` (type: `string`):

"For sale" returns active and coming-soon listings. "Sold" returns recently sold homes (comps) within the window below. A search URL that already has its own sold filter keeps it.

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

For sold listings: how far back to look. Redfin offers 7, 30, 90, 180, 365, 730, 1095 and 1825 days; other values round up to the next one.

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

How many listings to return for each URL or ZIP code. Set 0 for every listing in the area: searches with more than 350 matches are split into price bands automatically, so you are not limited to Redfin's 350-per-search cap.

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

Only these property types. Leave empty for all. Applies on top of any type filter in a search URL only if the URL has none.

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

Only listings at or above this price.

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

Only listings at or below this price.

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

Only listings with at least this many bedrooms.

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

Only listings with at least this many bathrooms.

## `onlyNewListings` (type: `boolean`):

Remember every listing already returned for each search and skip it next time, so a scheduled run returns only new listings (or new sales) and you pay only for those.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.redfin.com/city/30818/TX/Austin"
  ],
  "zipCodes": [],
  "listingType": "for-sale",
  "soldWithinDays": 90,
  "maxResultsPerSearch": 100,
  "propertyTypes": [],
  "onlyNewListings": false
}
```

# Actor output Schema

## `listings` (type: `string`):

One row per home with price, size, status, days on market and listing agent.

## `agents` (type: `string`):

The same rows, arranged around the listing agent and brokerage.

## `summary` (type: `string`):

Per search: region, filter applied, matches on Redfin and listings returned.

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

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

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,webdata_labs/redfin-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/iDotaFpXwLAMV38YY/builds/9AdCu8jFBQEJ66Zbn/openapi.json
