# Redfin Scraper — Properties, Prices & Real Estate Data (`bovi/redfin-scraper`) Actor

Scrape public Redfin property listings from supported search URLs. Get structured price, size, status, and location fields. Run with Redfin URLs; no account or buyer API key. Pricing: $0.001 per property-item on Free.

- **URL**: https://apify.com/bovi/redfin-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Real estate, Lead generation
- **Features:** Limited permissions
- **Stats:** 7 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.97 / 1,000 property 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 City, ZIP, and County

Scrape public Redfin property listings from redfin.com by city, ZIP, county, or neighborhood, with structured price, size, status, and location fields. On the Free plan, `property-item` costs $0.001 per delivered property; each row with status `sold` also costs $0.0019 (`sold-listing`).

- Compare listing price, beds, baths, and square footage for a city or ZIP.
- Collect sold rows for comparable-sales analysis with `statusFilter: "sold"`.
- Review lot size, year built, coordinates, and days on market (returned when Redfin provides it) by county or neighborhood.
- Scrape multiple Redfin search URLs in one run without a Redfin account.
- Proxy configuration is optional.

### What you get

Each saved row is a property flattened from Redfin listing JSON. Prices are USD integers; square footage and lot size are square-foot integers. A field is `null` when the source does not provide the value.

| Field | Type | Description |
| --- | --- | --- |
| `property_id` | string | Redfin property ID; `null` when unavailable. |
| `address` | string | Street line, with the unit number appended when provided; `null` when unavailable. |
| `city` | string | City name; `null` when unavailable. |
| `state` | string | State; `null` when unavailable. |
| `zip` | string | ZIP or postal code; `null` when unavailable. |
| `price` | integer | Listing price in USD; `null` when unavailable. |
| `beds` | integer | Bedroom count; `null` when unavailable. |
| `baths` | number | Bathroom count; `null` when unavailable. |
| `sqft` | integer | Interior square feet; `null` when unavailable. |
| `lot_size` | integer | Lot size in square feet; `null` when unavailable. |
| `year_built` | integer | Year built; `null` when unavailable. |
| `property_type` | string | `house`, `condo`, `townhouse`, `multi-family`, `land`, `other`, `mobile`, or `co-op`; `null` when unavailable. |
| `status` | string | Lowercased source status such as `active`, `coming_soon`, `pre_on_market`, `pending`, `contingent`, `sold`, `off_market`, or `expired`; `null` when unavailable. |
| `days_on_market` | integer | Days on market; `null` when unavailable. |
| `latitude` | number | Latitude; `null` when unavailable. |
| `longitude` | number | Longitude; `null` when unavailable. |
| `url` | string | Absolute Redfin listing URL; `null` when unavailable. |
| `scraped_at` | ISO 8601 string | UTC run timestamp. |
| `parse_confidence` | number | Data-quality score after applicable deductions. |
| `warnings` | array of strings | Deduction codes; empty when no deductions apply. |

Missing property ID, address, city, price, coordinates, or URL lowers `parse_confidence` and adds a corresponding warning. A null `days_on_market` does not add a warning.

### Sample output

This sample is shortened by dropping `scraped_at` and `warnings`. Every remaining value is copied from the dataset record.

```json
{
  "property_id": "31443083",
  "address": "6508 Auburndale St",
  "city": "Austin",
  "state": "TX",
  "zip": "78723",
  "price": 556000,
  "beds": 4,
  "baths": 3,
  "sqft": 2110,
  "lot_size": 12205,
  "year_built": 1967,
  "property_type": "house",
  "status": "coming_soon",
  "days_on_market": null,
  "latitude": 30.3132008,
  "longitude": -97.6761242,
  "url": "https://www.redfin.com/TX/Austin/6508-Auburndale-St-78723/home/31443083",
  "parse_confidence": 1
}
```

### Pricing

Billing is pay per event: `property-item` for each saved row, `sold-listing` in addition for each saved row with status `sold`, and `apify-actor-start` for the run start.

| Plan | `property-item` | `sold-listing` | `apify-actor-start` |
| --- | --- | --- | --- |
| Free | $0.001 | $0.0019 | $0.00005 (Free plan) |
| Bronze | $0.00099 | $0.001881 | $0.0000495 |
| Silver | $0.00098 | $0.001862 | $0.000049 |
| Gold | $0.00097 | $0.001843 | $0.0000485 |
| Platinum | $0.00096 | $0.001824 | $0.000048 |
| Diamond | $0.00095 | $0.001805 | $0.0000475 |

`property-item` is charged once per saved property. On the Free plan, 1,000 properties cost $1.00 and 10,000 properties cost $10.00.

`sold-listing` is charged when the saved status is exactly `sold`, in addition to `property-item` for the same row. The Free-plan price is $0.0019 per event. Example on the Free plan: 1,000 sold rows cost 1,000 × $0.001 = $1.00 for `property-item` plus 1,000 × $0.0019 = $1.90 for `sold-listing`, or $2.90 before the start event.

`apify-actor-start` is charged once per GB of run memory, with a minimum of one event. The Free-plan price is $0.00005 per event.

The Apify Free plan includes $5 of monthly platform usage credit. After one Free Actor Start and no `sold-listing` charges, the $5 credit covers 4999 `property-item` results.

You pay only for the events listed above. This Actor does not use the Pay per event + usage option, so the platform usage of your runs (compute, proxy traffic and storage) is not billed to you separately.

### How to use

1. Copy a full Redfin URL, such as `https://www.redfin.com/city/30818/TX/Austin`, `https://www.redfin.com/zipcode/78701`, `https://www.redfin.com/county/1361/TX/Travis-County`, or a neighborhood URL containing `/neighborhood/` and a numeric ID.
2. Paste one or more URLs into `locations`.
3. Choose `statusFilter` and optional property-type, price, or bedroom filters.
4. Set `maxResults` and `pageSize`, then start the run.
5. Download the dataset when the run finishes.
6. Repeat the run through Apify Schedules.

```json
{
  "locations": ["https://www.redfin.com/city/30818/TX/Austin"],
  "maxResults": 500,
  "propertyTypes": ["house", "condo"],
  "minPrice": 0,
  "maxPrice": 0,
  "minBeds": 0,
  "statusFilter": "active",
  "pageSize": 350
}
```

Export the dataset as JSON or CSV, or read items through the Apify dataset API.

### Input parameters

Filters are optional. If `locations` is omitted or empty, no rows are saved.

| Parameter | What it does | Default |
| --- | --- | --- |
| `locations` | Redfin search URLs for cities, ZIPs, counties, or neighborhoods. Multiple URLs run together; blank entries are skipped. | Empty |
| `maxResults` | Maximum records across all locations. `0` means no cap; the per-region maximum is set by Redfin and is not documented. | 500 |
| `propertyTypes` | Keeps matching lowercase property types. Accepted values: `house`, `condo`, `townhouse`, `multi-family`, `land`, `other`. Empty includes all types. | Empty |
| `minPrice` | Removes prices below this USD amount. `0` means no minimum. Rows with a missing price are kept. | 0 |
| `maxPrice` | Removes prices above this USD amount. `0` means no maximum. Rows with a missing price are kept. | 0 |
| `minBeds` | Removes listings below this bedroom count. `0` means no minimum. Rows with 0 or missing beds are kept. | 0 |
| `statusFilter` | `active` for for-sale, `sold` for sold, or `all` for both. | `active` |
| `pageSize` | Listings requested per API page; accepted range is 10–350. | 350 |
| `proxyConfiguration` | Optional Apify proxy configuration. | No proxy |
| `disableUsageStats` | Set to `true` to turn off the run summary described in Usage statistics. | `false` |

### Limits and edge cases

| Condition | What you see | What to do |
| --- | --- | --- |
| `locations` is missing or empty | An error is logged, no rows are saved, and `OUTPUT` is `{"error": "no_locations"}`. | Add a Redfin URL. |
| A URL is unsupported | It is skipped and added to `OUTPUT.failedDetails`; other URLs continue. | Use a city, ZIP, county, or neighborhood URL. |
| Redfin returns HTTP 429 | The URL is skipped with a `rate_limited` reason; pages already fetched for that URL are dropped, while rows of earlier URLs remain saved. The run finishes with the available dataset. | Retry later or configure an Apify proxy. |
| A request fails or returns a non-success status | The URL is skipped and its reason is trimmed to 300 characters. All pages of a URL are fetched before its rows are saved, so an error partway through drops that URL's already-fetched pages; rows of earlier URLs remain saved. The run finishes with the available dataset. | Check the URL and rerun. |
| A page is empty or shorter than `pageSize` | Paging for that status stops. | Try another area or status. |
| Filters remove every listing | The dataset can be empty; filtered-out rows are not charged. | Widen the filters. |
| `maxResults` is reached | Further pages and URLs are not requested. | Increase the cap or use `0` (the per-region maximum is set by Redfin and is not documented). |
| Filters are set with `maxResults` | The cap on rows fetched per location is applied before the property-type, price, and bedroom filters, so a filtered run can return fewer rows than `maxResults`. | Raise `maxResults` or use `0`. |
| `statusFilter` is `all` | Active and sold listings are both requested. | Run `active` and `sold` separately if you need separate caps. |
| More than 20 URLs fail | `OUTPUT` retains only the first 20 `failedDetails`. | Use the run log for later failures. |

Paging waits 0.5 seconds between pages of the same status.

### FAQ

#### How much does it cost to scrape Redfin listings?

On the Free plan, `property-item` costs $0.001 per saved property, `sold-listing` costs $0.0019 per event, and `apify-actor-start` costs $0.00005 per event. For example, 1,000 non-sold properties cost $1.00 on the Free plan, and 1,000 sold rows cost 1,000 × $0.001 + 1,000 × $0.0019 = $2.90, plus the applicable `apify-actor-start` event.

#### What happens when a location returns no results?

Paging stops for that status and no property rows are saved for the empty location. Later URLs still run, and no `property-item` charge applies to rows that were not saved.

#### What should I do if a location fails?

Unsupported URLs, HTTP 429 responses, and failed requests are skipped and recorded in `OUTPUT.failedDetails`; at most 20 failures are stored there. Correct the URL and retry, using `proxyConfiguration` when needed.

#### Do I need a Redfin account?

No. The Actor reads public listing data from redfin.com and does not require a Redfin account. Proxy configuration is optional.

#### Is scraping Redfin listings legal or allowed?

The Actor reads publicly available listing data from redfin.com. Whether your use is allowed depends on Redfin’s terms and the law applicable to your use case.

### Related actors

- [Redfin Sold Comps Scraper — ARV & Comp Analysis](https://apify.com/bovi/redfin-sold-comps-tracker) — a separate Actor focused on Redfin sold comps and ARV analysis.
- [Aruodas.lt Property Listings Scraper](https://apify.com/bovi/aruodas-scraper) — property listings from Aruodas.lt.
- [At Home Japan Rental Listings](https://apify.com/bovi/athome-scraper) — Japan rental listings from a different source.

### Usage statistics

This Actor creates a small, content-free summary at the end of each run, used only to monitor reliability and improve this Actor. No input values, credentials or scraped data are sent.

A copy of the exact record for your run is saved as `USAGE_STATS` in your own Apify key-value store.

To opt out, set `disableUsageStats` to `true` in the input. Nothing is sent then.

[Full list of collected fields](https://api.apify.com/v2/key-value-stores/v9rgHjMKLDGtHf8tD/records/index.html)

# Actor input Schema

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

Full Redfin search URLs to scrape — city, ZIP, county, or neighborhood. Go to redfin.com, navigate to any area, copy the URL. Examples: https://www.redfin.com/city/30818/TX/Austin or https://www.redfin.com/zipcode/78701. Add multiple URLs to scrape several areas in one run.

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

Maximum number of property records to return across all locations. 0 = no limit (up to Redfin API maximum per region). Default 500.

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

Filter by property type. Accepted values: house, condo, townhouse, multi-family, land, other. Leave empty to include all types.

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

Minimum listing price filter. 0 = no minimum.

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

Maximum listing price filter. 0 = no maximum.

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

Minimum number of bedrooms. 0 = no minimum.

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

Optional Apify proxy. Most Redfin regions do not require a proxy — the stingray API returns JSON directly. Use a proxy only if you encounter blocks in restricted regions.

## `statusFilter` (type: `string`):

Filter by listing status. active: for-sale only; sold: recently sold; all: both active and sold.

## `pageSize` (type: `integer`):

Number of listings fetched per API call (max 350). Reduce if you see errors. Default 350.

## `disableUsageStats` (type: `boolean`):

See the README Usage statistics section for details.

## Actor input object example

```json
{
  "locations": [
    "https://www.redfin.com/city/30818/TX/Austin"
  ],
  "maxResults": 500,
  "propertyTypes": [],
  "minPrice": 0,
  "maxPrice": 0,
  "minBeds": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "statusFilter": "active",
  "pageSize": 350,
  "disableUsageStats": false
}
```

# Actor output Schema

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

Dataset containing Redfin Scraper records (address, city, state, price, beds, baths, sqft, days_on_market, status, property_type, url, parse_confidence).

# 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"
    ],
    "maxResults": 500,
    "propertyTypes": [],
    "minPrice": 0,
    "maxPrice": 0,
    "minBeds": 0,
    "proxyConfiguration": {
        "useApifyProxy": false
    },
    "statusFilter": "active",
    "pageSize": 350
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/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 = {
    "locations": ["https://www.redfin.com/city/30818/TX/Austin"],
    "maxResults": 500,
    "propertyTypes": [],
    "minPrice": 0,
    "maxPrice": 0,
    "minBeds": 0,
    "proxyConfiguration": { "useApifyProxy": False },
    "statusFilter": "active",
    "pageSize": 350,
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/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 '{
  "locations": [
    "https://www.redfin.com/city/30818/TX/Austin"
  ],
  "maxResults": 500,
  "propertyTypes": [],
  "minPrice": 0,
  "maxPrice": 0,
  "minBeds": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "statusFilter": "active",
  "pageSize": 350
}' |
apify call bovi/redfin-scraper --silent --output-dataset

```

## MCP server setup

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