# Redfin Scraper: US Real Estate Listings API (`barefoot_grade/redfin-us-scraper`) Actor

Redfin API for US homes for sale and sold homes. Paste any Redfin search URL or pick cities and ZIP codes; get one record per home with price USD, address, beds, baths, square feet, home type, photos and the listing URL, plus optional sale and tax history.

- **URL**: https://apify.com/barefoot_grade/redfin-us-scraper.md
- **Developed by:** [Philip Kirkbride](https://apify.com/barefoot_grade) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 95.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 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.

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: US Real Estate Listings API

Collect homes for sale and recently sold homes from Redfin (redfin.com)
across the United States. Paste any Redfin search URL with the filters
you already set on the site, or pick cities and ZIP codes. Each home
comes back as one clean record with price in USD, street address, city,
state, beds, baths, square feet, home type, photos and the listing URL.
For sold homes you can also add the sale history, the last sale price
and date, and the property tax history.

Use it as a simple Redfin API for spreadsheets, dashboards, valuation
models and scheduled market reports. No Redfin account is needed.

### What you can do with it

- **Track a local market.** Run the same Austin, Seattle or Denver search
  every morning and watch new listings, price changes and homes that
  leave the market.
- **Build comparable sales (comps).** Search homes sold in the last year
  in a ZIP code, add `includeHistory`, and get the real sale price and
  sale date for each home next to its beds, baths and square feet.
- **Feed a valuation or investment model.** Price, square feet and room
  counts come as numbers, so price per square foot is one formula away.
- **Find leads for agents, lenders and home services.** Export fresh
  listings in your service area with address and listing link.
- **Research housing trends.** Compare asking prices across cities,
  neighborhoods and home types with one input.
- **Reuse your Redfin searches.** Set price, beds, baths, home type or
  any other filter on redfin.com, copy the address bar, paste it here.

### Quick start

Search the default city (Austin, TX) with no input at all, or start
small with ten homes:

```json
{"cities": ["Austin, TX"], "maxPages": 1, "maxResults": 10}
```

Paste a Redfin search URL with your own filters:

```json
{
  "startUrls": [
    {"url": "https://www.redfin.com/city/30818/TX/Austin/filter/property-type=house,min-beds=3"}
  ],
  "maxResults": 20
}
```

### Input

| Name | Type | Default | What it does |
|---|---|---|---|
| `startUrls` | array | empty | Redfin search URLs to collect, each with its own filters. Up to 20. |
| `cities` | array | Austin, TX | Built-in cities: Austin, TX, Seattle, WA, San Francisco, CA, Los Angeles, CA, Chicago, IL. |
| `zipcodes` | array | empty | Five-digit US ZIP codes. |
| `searches` | array | empty | Redfin search paths or URLs, e.g. `/city/16832/CO/Denver`. |
| `propertyType` | string | empty | Optional home type added to every search: house, condo, townhouse, apartment, multi-family, land, mobile. |
| `sold` | boolean | `false` | Homes sold in the last year instead of homes for sale. |
| `includeHistory` | boolean | `false` | Opens each home's page (up to `maxDetails`) and adds `history`, `tax_history` and `last_sold`. |
| `maxDetails` | integer | `3` | Most home pages to open per run when `includeHistory` is on, 1-200. |
| `maxPages` | integer | `1` | Result pages per search, 1-10. A page usually lists 20 or more homes. |
| `maxResults` | integer | `50` | Most homes per run across all searches, 1-200. |
| `requestDelaySecs` | number | `1` | Pause between page requests, 0.5-10 seconds. |

When you give no city, ZIP code, search path or URL, the run searches
Austin, TX. As soon as you give any of them, only your searches run.
Homes that appear in more than one of your searches are returned once.

### Input recipes

**Pasted search URL.** Open redfin.com, search a city, ZIP code,
neighborhood or county, set your filters (price range, beds, baths,
home type, square feet, year built and so on), then copy the URL from
the address bar. Paste it as is; you do not need to remove page numbers
or tracking parameters:

```json
{
  "startUrls": [
    {"url": "https://www.redfin.com/zipcode/78704/filter/property-type=house,min-price=400k,max-price=900k"},
    {"url": "https://www.redfin.com/neighborhood/121/WA/Seattle/Ballard"}
  ],
  "maxPages": 2,
  "maxResults": 100
}
```

**Several ZIP codes in one run:**

```json
{"zipcodes": ["78704", "78702", "78745"], "maxPages": 2, "maxResults": 150}
```

**Condos only in two built-in cities:**

```json
{"cities": ["Seattle, WA", "San Francisco, CA"], "propertyType": "condo", "maxResults": 60}
```

**Any other city by its Redfin path.** Copy the part after
`redfin.com` from a Redfin city page:

```json
{"searches": ["/city/16832/CO/Denver"], "maxResults": 40}
```

**Sold comps with sale prices and tax history.** Sold search cards show
the last list price; `includeHistory` adds the actual sale price and
date from each home's page:

```json
{"zipcodes": ["98107"], "sold": true, "includeHistory": true, "maxDetails": 10, "maxResults": 10}
```

Some states, Texas among them, do not make sale prices public. There
the sale events keep their dates but have a null price.

**Daily market monitor.** Save any of the inputs above as an Apify task
and schedule it daily. Compare runs by `listing_key` to see new, changed
and removed homes.

### Output example

Each home is one dataset item with `listing_key`, `url`, `price_usd`,
`address`, `city`, `state`, `beds`, `baths`, `sqft`, `property_type`,
`images`, `source` and `scraped_at`. With `includeHistory` on, the
first `maxDetails` homes also carry `history`, `tax_history` and
`last_sold`.

Example record from a sold search in Seattle's 98107 ZIP code with
`includeHistory` on (collected 2026-10-20; history and tax rows
shortened to three each):

```json
{
  "listing_key": "redfin.com:12449",
  "url": "https://www.redfin.com/WA/Seattle/6042-Seaview-Ave-NW-98107/unit-404/home/12449",
  "price_usd": 950000,
  "address": "6042 Seaview Ave NW #404",
  "city": "Seattle",
  "state": "WA",
  "beds": 2,
  "baths": 2.0,
  "sqft": 1587,
  "property_type": "house",
  "images": [
    "https://ssl.cdn-redfin.com/photo/1/islphoto/905/genIslnoResize.2491905_0.webp",
    "https://ssl.cdn-redfin.com/photo/1/islphoto/905/genIslnoResize.2491905_1_0.webp"
  ],
  "source": "redfin.com",
  "scraped_at": "2026-10-20T04:05:00+00:00",
  "history": [
    {"date": "2026-06-02", "event": "Sold (MLS) (Closed) NWMLS as Distributed by MLS Grid #2491905", "price": 950000},
    {"date": "2026-05-05", "event": "Pending NWMLS as Distributed by MLS Grid #2491905", "price": null},
    {"date": "2026-03-27", "event": "Listed (Active) NWMLS as Distributed by MLS Grid #2491905", "price": 975000}
  ],
  "tax_history": [
    {"year": 2026, "property_tax_usd": 11334, "land_additions_usd": 157200},
    {"year": 2025, "property_tax_usd": 9359, "land_additions_usd": 157200},
    {"year": 2024, "property_tax_usd": 9577, "land_additions_usd": 157200}
  ],
  "last_sold": {"date": "2026-06-02", "price": 950000}
}
```

Without `includeHistory`, records stop at `scraped_at`.

Field notes:

- `listing_key` is stable for the same home across runs, so you can
  join or deduplicate on it.
- `price_usd`, `beds`, `baths` and `sqft` are numbers; any of them is
  null when the listing does not show it.
- `property_type` is the home type of your search when it filters on one
  type (`propertyType`, or a pasted URL with one home type). Redfin's
  search data labels most homes as single-family, so without a home type
  filter this field usually reads `house`, condos included. Filter by
  type when the type matters.
- `images` lists the photo links shown in the search results (often
  the first few photos; empty when the card has none).
- `history[].event` is the event label as Redfin shows it, including
  its source (for example `Sold Public Records`).
- `scraped_at` is the time the run collected the data, in UTC.

You can download the dataset as JSON, CSV, Excel or XML, or read it
from the Apify API in your own code.

### Use it as a Redfin API

Every run can be started over the Apify API with the same JSON input
shown above, from Python, JavaScript, Zapier, Make, n8n or a plain HTTP
call, and the results read back from the run's dataset. Saved tasks and
schedules make it a hands-off Redfin listings feed.

### FAQ

**How fresh is the data?** Every run reads Redfin at the moment it
starts. Nothing is cached between runs.

**Which Redfin URLs can I paste?** Search result pages: city, ZIP code,
neighborhood and county searches, with or without filters. A single
home page is not a search and is rejected with a clear message. Paste
the search that lists it instead.

**Do my Redfin filters carry over?** Yes. The filters in the pasted URL
are kept on every page of that search. If you also set `propertyType`
or `sold`, they are added to each search.

**What if my city is not in the built-in list?** Paste its Redfin
search URL in `startUrls`, or put its path in `searches`.

**How many homes can I get?** Up to 200 per run and up to 10 pages per
search. For a whole metro area, split it into ZIP codes or
neighborhoods and schedule several runs.

**What price do sold homes show?** Sold search results show the last
list price. Turn on `includeHistory` to get the sale price and date in
`last_sold` and `history`.

**Why does a sold event have no price?** Redfin hides some prices, for
example very old sales and sales in states that do not publish sale
prices, such as Texas. Those events keep their date and have a null
price.

**Does it return rentals?** It returns homes for sale and sold homes.
Monthly rents are never reported as sale prices.

**Does it return agent phone numbers or emails?** No. It returns the
listing data shown in Redfin search results.

**What happens if a request fails?** Temporary errors are retried. A
search page that does not exist is skipped and logged. A ZIP code
search that finds no homes stops the run with an error, so a mistyped
ZIP code is not reported as an empty success.

**Can I combine inputs?** Yes. Pasted URLs, cities, ZIP codes and search
paths can all be used in the same run.

For help, contact Apify Support and include the run URL.

### Pricing

You pay per home returned plus a small start event for each run.
The start event is charged per GB of memory, so the
default 512 MB run is one start event. See the Actor's Pricing tab on Apify for current rates. `includeHistory`
does not add a charge per home page, but it makes runs slower. Total
run cost depends on your limits and your Apify plan. Start with a small
`maxResults` value and check the run cost before scheduling larger
collections.

# Actor input Schema

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

Paste one or more redfin.com search page URLs (city, ZIP code, neighborhood or county pages) with any filters you set on Redfin: price, beds, baths, home type, square feet and more. Each URL keeps its own filters. Use this instead of, or alongside, Cities, ZIP codes and Custom search paths. Single home pages are not accepted.

## `cities` (type: `array`):

Built-in cities to search: Austin, TX, Seattle, WA, San Francisco, CA, Los Angeles, CA and Chicago, IL. For any other place, paste its Redfin search URL above or use Custom search paths. When no city, ZIP code, search path or URL is given, the run searches Austin, TX.

## `zipcodes` (type: `array`):

Five-digit US ZIP codes to search as /zipcode/{zip} pages (no region id needed).

## `searches` (type: `array`):

Redfin search paths or URLs for any place, e.g. /city/16832/CO/Denver or /city/30818/TX/Austin/filter/property-type=house. Page numbers and anything after ? are ignored; each search starts at page 1.

## `propertyType` (type: `string`):

Optional home type filter added to every search: house, condo, townhouse, apartment, multi-family, land or mobile.

## `sold` (type: `boolean`):

Search homes sold in the last year instead of homes for sale. Works with every search input and the home type filter. Sold search cards show the last list price, not the sale price; turn on includeHistory to get the sale price and date from each home's page.

## `includeHistory` (type: `boolean`):

After collecting the search results, open each home's page (up to maxDetails homes) and add history\[] (date, event and price rows, including Sold events; a hidden price is null), tax_history\[] and last_sold {date, price}.

## `maxDetails` (type: `integer`):

Most home pages to open when includeHistory is on, so a 50-result run does not open 50 home pages.

## `maxPages` (type: `integer`):

Result pages to read per search. A Redfin search page usually lists 20 or more homes.

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

Stop after this many homes across all searches.

## `requestDelaySecs` (type: `number`):

Pause between page requests, 0.5 to 10 seconds.

## Actor input object example

```json
{
  "startUrls": [],
  "cities": [],
  "sold": false,
  "includeHistory": false,
  "maxDetails": 3,
  "maxPages": 1,
  "maxResults": 50,
  "requestDelaySecs": 1
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("barefoot_grade/redfin-us-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 = { "startUrls": [] }

# Run the Actor and wait for it to finish
run = client.actor("barefoot_grade/redfin-us-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 '{
  "startUrls": []
}' |
apify call barefoot_grade/redfin-us-scraper --silent --output-dataset

```

## MCP server setup

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