# Redfin Scraper — US Homes for Sale, Sold & Estimates (`tortuga/redfin-scraper`) Actor

Scrape Redfin homes for sale, for rent and recently sold from search URLs or any US city, ZIP or neighborhood: price, beds, baths, sqft, photos, agent, open houses, Redfin Estimate.

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

## Pricing

from $0.40 / 1,000 listing scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Homes for Sale, Sold & Estimates

Scrape **Redfin** listings for any US city, ZIP code, neighborhood, county or school district: homes **for sale**, **recently sold** and **for rent**. Paste a Redfin search URL with your filters, or type locations and choose filters here (price, beds, baths, home type, living area, lot size, year built, HOA, days on market, sold within, pending). Every listing comes with price, address, coordinates, beds, baths, sqft, lot, year built, status, days on market, HOA, price per sq ft, key facts, description, all photos, open houses, and the **listing agent and brokerage** as Redfin shows them. Turn on **details** to add the **Redfin Estimate**, the full description, the feature list, price and listing history, tax history, public records, Walk Score and schools.

No login, no browser, no Unblocker: the actor reads the same JSON service Redfin's own map uses, so runs are fast and cheap.

### What data does Redfin Scraper extract?

| Field | Example | Notes |
|---|---|---|
| `id`, `listingId`, `mlsListingId`, `url` | `179155548`, `224294751`, `6761659` | `id` is Redfin's property ID (stable across listings of the same home) |
| `status`, `listingStatus` | `Active`, `for_sale` | `listingStatus`: for_sale, coming_soon, contingent, pending, sold, for_rent |
| `price`, `originalPrice`, `pricePerSqft` | `875000`, `875000`, `382` | Sold homes: sale price, or the last list price where the sale price is not public |
| `soldPrice`, `soldDate`, `salePriceHidden` | `null`, `2026-10-08`, `true` | Texas, Utah and other non-disclosure states: Redfin hides sale prices, so does the actor |
| `lastSoldDate`, `lastSoldPrice` | `2008-05-28` | Previous sale of a home now for sale (price only where public, with details) |
| `estimate` / `redfinEstimate` | `192735` | Redfin Estimate when Redfin shows one (with details) |
| `daysOnMarket` | `1` | |
| `beds`, `baths`, `bathsFull`, `bathsHalf`, `sqft`, `lotSqft`, `yearBuilt`, `stories`, `garage`, `parkingSpaces` | `3`, `3.5`, ... | Rentals: `bedsMin`/`bedsMax`, `bathsMin`/`bathsMax`, `sqftMin`/`sqftMax` |
| `propertyType` | `condos` | single_family, condos, townhomes, multi_family, land, mobile, coop, other |
| `hoaFee` | `435` | Monthly |
| `address`, `unit`, `city`, `state`, `zip`, `neighborhood`, `latitude`, `longitude`, `timeZone` | `4405 Grotto Dr`, `Austin`, `TX`, `78731` | |
| `isNewConstruction`, `isHot`, `isRedfinListing`, `badges`, `keyFacts`, `tags` | `["New"]`, `["$435 HOA"]` | |
| `description` | text | From the search result (up to ~700 characters); full text with details |
| `openHouses` | `[{start, end, timeZone, description}]` | Local time with offset |
| `listingAgent`, `listingOffice`, `listingOfficePhone` | `Tomas Corzo`, `Keller Williams Realty`, `512-448-4111` | As shown on the listing ("Listed by ...") |
| `builder`, `community` | `D.R. Horton`, `Trails at Wildhorse` | New construction |
| `primaryPhoto`, `photos`, `photoCount`, `virtualTourUrl` | full-size photo URLs | |
| Rentals: `priceMin`, `priceMax`, `name`, `unitsAvailable`, `dateAvailable`, `leasingPhone` | `1375`, `1725`, `The Quest` | Rent range of a building or home |
| **With details:** `features`, `priceHistory`, `taxHistory`, `publicRecords`, `walkScore`, `bikeScore`, `transitScore`, `schools`, `mlsName`, `listingAgentPhone` | | Extra `detail` event |
| `changeType`, `previousValues` | `changed`, `{"price": 899000}` | Only with monitoring on |

### How to scrape Redfin listings

1. Open [redfin.com](https://www.redfin.com), search a place, set filters, and copy the address bar into **Start URLs**. City, ZIP code, county, neighborhood and school-district searches work (`/city/30818/TX/Austin/filter/...`, `/zipcode/78704/...`), including recently sold (`include=sold-3mo`) and rentals (`/apartments-for-rent`, `/rentals`). Home pages (`.../home/31240372`) return that home with full details.
2. Or leave Start URLs empty and type **Locations** such as `Austin, TX`, `78704`, `South Congress, Austin`, `Travis County, TX` or `Brooklyn, NY`, then pick **For sale / For rent / Recently sold** and filters.
3. Set **Max items** and run. Download the results as JSON, CSV or Excel, or read them through the API.

### Input example

```json
{
  "locations": ["Austin, TX", "78704"],
  "listingType": "for_sale",
  "propertyTypes": ["single_family", "townhomes"],
  "minBeds": 3,
  "maxPrice": 600000,
  "maxDaysOnMarket": 30,
  "sort": "newest",
  "maxItems": 500,
  "includeDetails": false
}
```

Start URL example: `{"startUrls": [{"url": "https://www.redfin.com/zipcode/78704/filter/property-type=house,include=sold-3mo"}], "maxItems": 200}`. Filters set in the input are added on top of the URL's own filters; URL filter parts the actor does not understand are listed in the run's `SUMMARY` (`ignoredUrlParts`).

### Output example

```json
{
  "id": "109914003",
  "listingId": "224289749",
  "mlsListingId": "3863154",
  "url": "https://www.redfin.com/TX/Austin/1010-W-23rd-St-78705/unit-5/home/109914003",
  "status": "Active",
  "listingStatus": "for_sale",
  "price": 195000,
  "originalPrice": 195000,
  "pricePerSqft": 431,
  "daysOnMarket": 1,
  "propertyType": "condos",
  "beds": 1,
  "baths": 1,
  "sqft": 452,
  "lotSqft": 535,
  "yearBuilt": 1975,
  "hoaFee": 257,
  "address": "1010 W 23rd St #5",
  "city": "Austin",
  "state": "TX",
  "zip": "78705",
  "neighborhood": "Westwood Condo",
  "latitude": 30.287399,
  "longitude": -97.749076,
  "badges": ["New"],
  "keyFacts": ["Vinyl flooring", "Private brick patio", "Convenient access"],
  "description": "Discover an excellent investment opportunity in Austin's vibrant West Campus neighborhood! ...",
  "listingAgent": "Andrew Morris",
  "listingOffice": "Real Broker, LLC",
  "listingOfficePhone": "(855) 450-0442",
  "primaryPhoto": "https://ssl.cdn-redfin.com/photo/92/bigphoto/154/3863154_0.jpg",
  "photoCount": 15,
  "detailsFetched": true,
  "estimate": 192735,
  "features": [{"category": "Parking", "group": "Parking", "items": ["Features: Assigned, Asphalt, Parking Lot", "# of Parking (Total): 1"]}],
  "priceHistory": [{"date": "2026-10-09", "event": "Listed", "price": 195000, "mlsStatus": "Active", "source": "Unlock MLS", "sourceListingId": "3863154"}],
  "taxHistory": [{"year": 2026, "tax": 3904.33, "assessedLand": 802, "assessedBuilding": 189980, "assessedTotal": 190782}],
  "walkScore": 91,
  "schools": [{"name": "Bryker Woods Elementary School", "rating": 8, "parentRating": 4, "grades": "PreK-5", "fundingType": "Public", "distanceMiles": 1.2, "servesHome": true}],
  "search": "Austin, TX (for sale)",
  "scrapedAt": "2026-10-10T03:31:44Z"
}
```

### How many listings can I get per search?

Redfin's map returns at most 10,000 homes per search. When a search has more (Houston has ~16,600 homes for sale) and **Max items** asks for more than 2,000, the actor cuts it into price bands automatically and loads each band in one request, so every listing is reachable; bands come lowest price first. Results are de-duplicated by property ID across bands and searches. Whole states cannot be searched on Redfin (the site itself needs a city, county, ZIP or map area).

### Can I scrape sold homes and rentals?

Yes. Choose **Recently sold** (with **Sold in the last N days**: 7 days up to 5 years) or paste a URL with `include=sold-...`; sold homes come with the sale date and, where the state discloses it, the sale price. Choose **For rent** or paste an `/apartments-for-rent` URL for rentals: buildings come with a rent range (`priceMin`/`priceMax`), bed/bath/sqft ranges, units available and the leasing office phone. Details (history, schools, estimate) are for sale and sold homes only.

### Does it get the Redfin Estimate and the listing agent?

The listing agent, brokerage and brokerage phone shown on each listing are included in every result at no extra cost. The Redfin Estimate, full description, features, price/tax history, Walk Score and schools come with **Include full description, history, Redfin Estimate, schools and walk score** (four extra requests per home, charged as `detail`). Redfin does not show an estimate for every home (often not for active listings in some markets); `estimate` is then empty.

### Do I need a proxy? Does it work without login?

No login is needed. The default Apify datacenter proxy works: Redfin's web pages answer a "Human Verification" challenge to scripts, but the JSON service behind its map does not. Blocked requests are retried on a new IP. Residential proxies work too but are billed per GB (searches download about 3 MB per 1,000 listings).

### Monitor changes on a schedule

Turn on **Only new or changed items** to watch a search. Each run remembers what earlier runs returned and outputs only new listings and listings whose price, rent range or status changed (for example for sale to pending, pending to sold, or a price cut). Unchanged listings are dropped before agent lookups and detail requests, so they are not charged. **Max items** then sets how many listings are checked per run; keep the "Newest" sort, e.g. 100-300 for a ZIP code. Save the input as a task in Apify and add a Schedule (for example daily); give each watch its own **Monitoring key** if several schedules use the same search. Every output item gets `changeType` (`new` or `changed`), and changed items get `previousValues` with the old values, e.g. `{"price": 525000, "listingStatus": "for_sale"}`.

### Pricing

You pay per listing saved ($0.40 per 1,000), plus $2.50 per 1,000 for the optional home details; agent and brokerage, description, photos and open houses are included in the base price. There is no start fee. Apify platform usage is billed to you separately and is small (about $0.007 per 1,000 listings in tests; about $0.06 per 1,000 with details).

### Integrations and API

Run it from the Apify API, the Python or JavaScript client, Make, Zapier, n8n, or schedule it in Apify Console. Results can go to Google Sheets, a webhook or your database.

### Is it legal to scrape Redfin?

The actor collects listing data that anyone can see on Redfin without logging in: property facts, prices, photos and the agent and brokerage named on the listing with the phone number published for inquiries. It does not log in and leaves out what Redfin masks (for example sale prices in non-disclosure states). Agent names are personal data in some jurisdictions; you are responsible for having a legitimate purpose for processing them and for respecting Redfin's terms of use. If in doubt, ask a lawyer.

### Support

Found a bug or need a field that is not there? Open an issue on the Issues tab with the input you used and the run link.

# Actor input Schema

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

Redfin search URLs with filters set in the browser (copy the address bar, e.g. https://www.redfin.com/city/30818/TX/Austin/filter/property-type=house,min-beds=3, https://www.redfin.com/zipcode/78704/filter/include=sold-3mo or https://www.redfin.com/city/30818/TX/Austin/apartments-for-rent), or home URLs (.../home/31240372), which return that home with full details. Leave empty if you use Locations below.

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

US cities, ZIP codes, neighborhoods, counties or school districts, one per line, e.g. 'Austin, TX', '78704', 'South Congress, Austin', 'Travis County, TX', 'Brooklyn, NY'. Each is searched separately. Whole states cannot be searched on Redfin.

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

Which listings the Locations searches return (start URLs keep their own: /apartments-for-rent or /rentals = for rent, include=sold-... = sold).

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

For sold searches: how far back. Redfin offers 7, 30, 90, 180, 365, 730, 1095 and 1825 days; other values use the nearest longer one. Default 90.

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

Only these home types. Leave empty for all.

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

Minimum list price (sold searches: sale price; rentals: monthly rent) in US dollars.

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

Maximum list price (sold searches: sale price; rentals: monthly rent) in US dollars.

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

Minimum number of bedrooms.

## `maxBeds` (type: `integer`):

Maximum number of bedrooms.

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

Minimum number of bathrooms.

## `minSqft` (type: `integer`):

Minimum interior living area in square feet.

## `maxSqft` (type: `integer`):

Maximum interior living area in square feet.

## `minLotSqft` (type: `integer`):

Minimum lot size in square feet (1 acre = 43,560 sq ft).

## `maxLotSqft` (type: `integer`):

Maximum lot size in square feet (1 acre = 43,560 sq ft).

## `minYearBuilt` (type: `integer`):

Only homes built in or after this year.

## `maxYearBuilt` (type: `integer`):

Only homes built in or before this year.

## `maxHoaFee` (type: `integer`):

Maximum monthly HOA fee.

## `maxDaysOnMarket` (type: `integer`):

Only listings that have been on Redfin for at most this many days (e.g. 7 for new listings).

## `includePending` (type: `boolean`):

For-sale searches show active and coming-soon homes like the site does; tick to add homes under contract (pending / contingent).

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

Order of the results. Default: newest first (sold searches: most recently sold; rentals: Redfin's recommended order). Searches with more than 2,000 wanted results are loaded in price bands, lowest prices first.

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

Stop after this many listings (you pay per listing). With 'Only new or changed items' this is the number of listings checked per run.

## `includeDetails` (type: `boolean`):

Load each home's detail data (full description, features, price/listing history, tax history, public records, Redfin Estimate, Walk/Bike/Transit Score, schools). Four extra requests per home, charged as the 'detail' event. Not available for rentals.

## `onlyNewOrChanged` (type: `boolean`):

Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged.

## `monitoringKey` (type: `string`):

Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input.

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

Apify Proxy (datacenter) works for Redfin's API and is the cheapest option. Switch to RESIDENTIAL (US) only if runs report blocks.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.redfin.com/city/30818/TX/Austin"
    }
  ],
  "listingType": "for_sale",
  "maxItems": 100,
  "includeDetails": false,
  "onlyNewOrChanged": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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": [
        {
            "url": "https://www.redfin.com/city/30818/TX/Austin"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

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