# Zillow property listings scraper (`data_dino/zillow-listings-scraper`) Actor

💰 $1.00 per 1000 results ❗Collect Zillow property listings for sale, for rent, or sold with beds, baths, price, and map-area filters. Get one structured dataset record per listing for lead generation, market research, and real-estate analysis.

- **URL**: https://apify.com/data\_dino/zillow-listings-scraper.md
- **Developed by:** [Data Dino](https://apify.com/data_dino) (community)
- **Categories:** Real estate, Automation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Zillow Property Listings Scraper

Collect structured Zillow listings for properties **for sale**, **for rent**, or **sold**. Search by a city, neighborhood, ZIP code, or address, then narrow results with bedroom, bathroom, price, rental, and map-area filters. The actor pushes one dataset item per listing, flattening each listing's fields (price, address, beds, baths, coordinates, and more) into a single-level record for direct export and analysis.

### Best for

- Real-estate inventory and market research
- Price and availability monitoring
- Investment-property discovery
- Lead-generation datasets
- Rental listing collection
- Feeding Zillow listing IDs and URLs into a separate property-details workflow

This actor favors a simple typed input configuration instead of requiring users to construct Zillow's encoded `searchQueryState` URL.

### Features

- **Three listing modes:** `for_sale`, `for_rent`, and `sold`.
- **Typed property filters:** minimum and maximum beds, bathrooms, and price.
- **Rental filters:** optionally return entire-place rentals or room rentals.
- **Location search:** search by city, neighborhood, ZIP code, or address.
- **Custom map area:** specify north-east and south-west latitude/longitude bounds and map zoom.
- **Controlled output size:** cap the number of pushed records with `maxResults`.
- **Flat, export-ready fields:** each record exposes ZPID, price, address and its components, beds, baths, area, coordinates, home type/status, Zestimate, rent Zestimate, tax values, lot information, and other listing fields at the top level when Zillow supplies them.
- **Proxy and retry support:** provide an optional proxy when needed; blocked requests can be retried with a refreshed proxy session.

### Input

`mode` is required. All other fields are optional.

| Field | Type | Description | Default |
|---|---|---|---|
| `mode` | string | Listing group to collect: `for_sale`, `for_rent`, or `sold`. | `for_sale` |
| `searchValue` | string | City, neighborhood, ZIP code, or address search term. Leave empty for a map-area search using the bounds below. | Empty |
| `minBeds` | integer | Minimum number of bedrooms. | `1` |
| `maxBeds` | integer | Maximum number of bedrooms. | Empty |
| `minBathrooms` | integer | Minimum number of bathrooms. | `1` |
| `maxBathrooms` | integer | Maximum number of bathrooms. | Empty |
| `minPrice` | integer | Minimum listing price in USD. | Empty |
| `maxPrice` | integer | Maximum listing price in USD. | Empty |
| `isEntirePlace` | boolean | For `for_rent` mode, return entire-place rentals only. | `false` |
| `isRoom` | boolean | For `for_rent` mode, return room rentals only. | `false` |
| `neLat` | number | North-east latitude bound for the map-area search. | `38.602951833355434` |
| `neLong` | number | North-east longitude bound for the map-area search. | `-87.22283859375` |
| `swLat` | number | South-west latitude bound for the map-area search. | `23.42674607019482` |
| `swLong` | number | South-west longitude bound for the map-area search. | `-112.93084640625` |
| `zoom` | integer | Zillow map zoom value. Lower values cover a wider area. Allowed range: `1`–`20`. | `5` |
| `pagination` | integer | Pagination page passed to the Zillow search request. This actor requests one configured page; it does not automatically iterate through all pages. | `1` |
| `maxResults` | integer | Maximum number of listing records pushed to the dataset after the response is received. | All returned listings |
| `proxy` | string | Optional HTTP(S) proxy, for example `http://user:password@host:port`. Used for this run when provided. | Empty; managed fallback may apply |

#### Example: San Diego homes for sale

```json
{
  "mode": "for_sale",
  "searchValue": "San Diego, CA",
  "minBeds": 2,
  "minBathrooms": 1,
  "maxPrice": 1500000,
  "neLat": 33.4,
  "neLong": -116.7,
  "swLat": 32.5,
  "swLong": -117.6,
  "zoom": 11,
  "pagination": 1,
  "maxResults": 100
}
```

#### Example: Wisconsin listings with a proxy

```json
{
  "mode": "for_sale",
  "searchValue": "Wisconsin",
  "maxResults": 25,
  "proxy": "http://user:password@proxy.example.com:3000"
}
```

For production runs, prefer a proxy that you control and do not share proxy credentials publicly. Zillow may still challenge an exit IP even when a proxy is configured.

### Output

The actor pushes one record per listing. Each listing is flattened into a single-level record: top-level listing fields (ZPID, formatted price, combined address, beds, baths, area, status, images, detail URL) are emitted directly, while the nested `hdpData.homeInfo` fields (numeric price, address components, home type/status, Zestimate, rent Zestimate, living area, tax and lot values) are lifted to the top level. `mode`, `searchValue`, and `source` provide run context.

```json
{
  "mode": "for_sale",
  "searchValue": "Wisconsin",
  "source": "mapResults",
  "zpid": "40599602",
  "imgSrc": "https://photos.zillowstatic.com/fp/518d4eb3bfa93a3b270692c747d6bdb1-p_e.jpg",
  "hasImage": true,
  "detailUrl": "/homedetails/1303-Green-Valley-Dr-Neenah-WI-54956/40599602_zpid/",
  "statusType": "FOR_SALE",
  "statusText": "House for sale",
  "price": "$339,900",
  "unformattedPrice": 339900,
  "priceLabel": "$340K",
  "address": "1303 Green Valley Dr, Neenah, WI 54956",
  "streetAddress": "1303 Green Valley Dr",
  "city": "Neenah",
  "state": "WI",
  "zipcode": "54956",
  "beds": 3,
  "baths": 3,
  "area": 1800,
  "livingArea": 1800,
  "latitude": 44.197407,
  "longitude": -88.4915,
  "homeType": "SINGLE_FAMILY",
  "homeStatus": "FOR_SALE",
  "zestimate": 351800,
  "rentZestimate": 1825,
  "taxAssessedValue": 275200,
  "lotAreaValue": 0.28,
  "lotAreaUnit": "acres"
}
```

Field availability varies by listing, listing mode, and Zillow response. For example, Zestimate, rent Zestimate, tax values, lot values, open-house information, broker data, and listing flags may be absent from individual records.

If Zillow returns no `mapResults` or `listResults` array, the actor pushes one fallback record containing the raw result payload instead of silently dropping the response:

```json
{
  "mode": "for_sale",
  "searchValue": "San Diego, CA",
  "result": {
    "...": "raw Zillow response"
  }
}
```

### How result selection works

1. The actor loads the input from Apify.
2. It invokes the Zillow scraper with the selected filters and map settings.
3. If `mapResults` contains listings, those records are selected; otherwise, `listResults` is used.
4. `maxResults` is applied after the Zillow response is received.
5. Each selected listing is pushed as a separate dataset item.
6. If neither listing array is present, the raw response is pushed as one fallback item.

### Proxy and reliability

The scraper supports:

- An optional proxy supplied for the run.
- Automatic retries for request, response-shape, and parsing failures.
- Sticky-session rotation when the configured proxy supports it.

If you provide proxy credentials, keep them private. Zillow may still block or challenge an exit IP even when a proxy is configured.

### Limitations and coverage guidance

- **One configured request:** `pagination` selects a page but does not automatically crawl every page.
- **Map result limits:** Zillow limits the number of results returned for a map area. For dense regions, use narrower bounds or a higher zoom and run multiple searches.
- **No adaptive subdivision:** this actor does not currently split dense regions into quadrants or provide a `scrapeAll` mode.
- **No detail scraping:** this actor collects search-result data. It does not currently retrieve full property details such as year built, agent contact data, complete photo galleries, price history, or last sold price.
- **Raw response variability:** Zillow can add, remove, or omit fields between listings and over time. Treat optional fields as nullable.
- **Relative detail URLs:** observed Zillow search responses may provide a relative `detailUrl`; convert it to an absolute Zillow URL downstream when needed.
- **Legal and privacy use:** use collected data in accordance with Zillow's terms, applicable laws, and privacy/data-use requirements.

For larger coverage requirements, split searches by ZIP code, neighborhood, price range, or smaller map bounds. Use the emitted ZPID and detail URL as handoff keys for a separate property-detail enrichment process.

### Run steps

1. Open the actor in Apify.
2. Choose `mode`.
3. Set `searchValue` and any property filters.
4. Narrow the map bounds and increase `zoom` for dense locations.
5. Optionally set `maxResults` and a proxy.
6. Start the run.
7. Export the dataset as JSON, CSV, Excel, or another supported Apify format.

### Related workflows

Use this actor for broad listing discovery, then pass the resulting ZPIDs or detail URLs to a separate property-details scraper when you need deeper property-level enrichment. The current actor intentionally keeps search collection and detail enrichment separate so basic inventory runs remain predictable and bounded.

# Actor input Schema

## `mode` (type: `string`):

Which Zillow listing group to collect.

## `searchValue` (type: `string`):

City, neighborhood, ZIP, or address search term. Leave empty for a pure map-area search using the bounds below.

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

Minimum number of bedrooms.

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

Maximum number of bedrooms.

## `minBathrooms` (type: `integer`):

Minimum number of bathrooms.

## `maxBathrooms` (type: `integer`):

Maximum number of bathrooms.

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

Minimum listing price in USD.

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

Maximum listing price in USD.

## `isEntirePlace` (type: `boolean`):

For for\_rent mode: filter for entire-place rentals only.

## `isRoom` (type: `boolean`):

For for\_rent mode: filter for room rentals only.

## `neLat` (type: `number`):

North-east latitude bound of the map-area search.

## `neLong` (type: `number`):

North-east longitude bound of the map-area search.

## `swLat` (type: `number`):

South-west latitude bound of the map-area search.

## `swLong` (type: `number`):

South-west longitude bound of the map-area search.

## `zoom` (type: `integer`):

Map zoom value used by the Zillow search request. Lower values cover a wider area; Zillow caps map results at 500.

## `pagination` (type: `integer`):

Which pagination page to request. Map results are limited by Zillow, so prefer adjusting the map area over pagination.

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

Maximum number of listing records to push to the dataset. When empty, every listing returned by Zillow is pushed.

## `proxy` (type: `string`):

Optional proxy URL such as http://user:pass@host:port. When empty, the scraper uses its configured default proxy.

## Actor input object example

```json
{
  "mode": "for_sale",
  "searchValue": "San Diego, CA",
  "minBeds": 1,
  "minBathrooms": 1,
  "isEntirePlace": false,
  "isRoom": false,
  "neLat": 38.602951833355434,
  "neLong": -87.22283859375,
  "swLat": 23.42674607019482,
  "swLong": -112.93084640625,
  "zoom": 5,
  "pagination": 1,
  "proxy": ""
}
```

# Actor output Schema

## `dataset` (type: `string`):

Structured Zillow property listing records collected during the run.

# 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 = {
    "mode": "for_sale",
    "searchValue": "San Diego, CA"
};

// Run the Actor and wait for it to finish
const run = await client.actor("data_dino/zillow-listings-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 = {
    "mode": "for_sale",
    "searchValue": "San Diego, CA",
}

# Run the Actor and wait for it to finish
run = client.actor("data_dino/zillow-listings-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 '{
  "mode": "for_sale",
  "searchValue": "San Diego, CA"
}' |
apify call data_dino/zillow-listings-scraper --silent --output-dataset

```

## MCP server setup

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