# Zillow Search Scraper - Listings by City or ZIP (`studioxl/zillow-search-scraper`) Actor

Get Zillow listings for any city, ZIP code, county or neighborhood: for sale, for rent or recently sold. Each row has price, Zestimate, rent estimate, beds, baths, sqft, lot, address, map coordinates and broker. Big cities come back in full. Export to CSV, JSON or Excel.

- **URL**: https://apify.com/studioxl/zillow-search-scraper.md
- **Developed by:** [Kamil Ertekin](https://apify.com/studioxl) (community)
- **Categories:** Lead generation, Automation, Real estate
- **Features:** Limited permissions
- **Stats:** 5 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 search results

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

## Zillow Search Scraper - Listings by City or ZIP

Type "Austin, TX" or "78731" and get every Zillow listing there as a flat row: price, Zestimate, rent estimate, beds, baths, size, lot, address, map coordinates, broker, price cuts and every photo. It covers homes for sale, for rent and recently sold. It's built for price monitoring, market reports, lead lists and investor screening, and it costs $1.50 per 1,000 listings with no start fee.

### What you get

Each listing is one row with 61 fields. The main ones:

| Field | Example | Notes |
|---|---|---|
| `zpid` | `64625418` | Zillow's property ID, a number. Joins directly with the detail scraper |
| `url` | `https://www.zillow.com/homedetails/11008-Sierra-Ridge-Ct-Austin-TX-78739/64625418_zpid/` | Listing page |
| `price` · `priceLabel` | `1375000` · `"$1,375,000"` | Number for sorting, plus the text Zillow shows. Monthly rent on rentals |
| `zestimate` · `rentZestimate` | `1339300` · `6769` | Zillow's own estimates, when Zillow publishes them |
| `taxAssessedValue` | `1153612` | County assessed value, where published |
| `pricePerSqft` | `313` | Price per sq ft of living area. On rentals it's monthly rent per sq ft, in dollars and cents (`2.15`) |
| `priceChange` · `priceChangeDate` · `priceChangeLabel` | `-25000` · `"2026-10-17"` · `"$25,000 (Oct 17)"` | The latest price change. A negative amount is a cut. Zillow writes the label for cuts only |
| `bedrooms` · `bathrooms` · `livingArea` | `5` · `4` · `4395` | Living area in sq ft |
| `lotAreaValue` · `lotAreaUnits` | `0.3826` · `"Acres"` | Lot size in the unit Zillow shows for that home (`Acres` or `Square Feet`) |
| `lotSize` | `16666` | Lot size in sq ft for every row, so you can sort and filter lots |
| `streetAddress` · `city` · `state` · `zipcode` | `"11008 Sierra Ridge Ct"` · `"Austin"` · `"TX"` · `"78739"` | Also a one-line `address` |
| `latitude` · `longitude` | `30.191551` · `-97.90368` | For mapping |
| `homeType` · `homeStatus` · `statusText` | `"SINGLE_FAMILY"` · `"FOR_SALE"` · `"Active"` | |
| `daysOnZillow` · `datePosted` | `11` · `"2026-10-08"` | Days since the listing went up, and that date. `datePosted` is empty on sold searches |
| `dateSold` | `"2026-10-19"` | Sale date, on recently sold searches |
| `isForSaleByAgent` · `isForSaleByOwner` · `isNewConstruction` · `isComingSoon` · `isForAuction` · `isForeclosure` · `isBankOwned` · `isPending` · `isOpenHouse` | `true` · `false` · … | Listing type, as true or false. Empty on apartment buildings |
| `brokerName` | `"Keller Williams Realty"` | Listing brokerage |
| `mainImage` | photo URL | Main listing photo |
| `photos` · `photoCount` | photo URLs · `27` | Every photo of the listing, full size (1536 px wide), in Zillow's order |
| `isBuilding` · `buildingName` · `priceMin` · `priceMax` · `bedroomsMin` · `bedroomsMax` · `unitCount` · `availableUnitCount` | | Apartment buildings on rental searches (see below) |
| `searchLocation` | `"Austin, TX"` | Which of your locations produced the row |
| `scrapedAt` | `"2026-10-20T14:03:12Z"` | When the row was collected, in UTC |

Other fields: `currency` (`"USD"`), `listingType`, `hasVideo`, `has3DModel` (the listing has a 3D tour), `isShowcaseListing`, `isZillowOwned`, `isFeaturedListing`, `isUndisclosedAddress`.

#### How often each field is filled

Measured on 5,000 unfiltered Austin, TX for-sale results (August 2026):

| Filled on | Fields |
|---:|---|
| 100% | `zpid`, `url`, `price`, `priceLabel`, address fields, `homeType`, `homeStatus`, `statusText`, `daysOnZillow`, `mainImage`, flags |
| 99% | `latitude`, `longitude`, `bedrooms`, `bathrooms` |
| 95% | `brokerName` |
| 83% | `livingArea`, `taxAssessedValue` |
| 27% | `rentZestimate` |
| 19% | `zestimate` |

Zillow only shows a Zestimate on about one active listing in five, on its own site too. When Zillow doesn't show one, the field is empty.

Columns added in October 2026, measured on one 41-listing Austin page: `photos`, `datePosted`, `pricePerSqft` and the listing type flags on 100%, `priceChange` on 29% (12 listings, 10 of them price cuts).

Search results don't include year built, HOA fee, description or the listing agent. [Zillow Property Detail Scraper](https://apify.com/studioxl/zillow-detail-scraper) adds those.

#### Rentals and apartment buildings

Most rental results are whole apartment buildings, not single homes. A building row has `isBuilding: true`, its `buildingName`, the rent range in `priceMin`/`priceMax`, the bedroom range in `bedroomsMin`/`bedroomsMax` and `availableUnitCount`. `price` holds the lowest rent and `priceLabel` reads like `$1,720 to $2,400/mo`, so you can still sort a mixed list by price. `bathrooms` and `livingArea` stay empty on building rows.

### How to use it

1. Type one or more locations: a city, ZIP code, county or neighborhood. You can also paste a Zillow search URL.
2. Pick **For sale**, **For rent** or **Recently sold**, and add filters if you want them.
3. Set **Maximum results** and click Start. Download the results as CSV, JSON or Excel, or read them through the API.

Minimal input that works as-is:

```json
{
  "locations": ["Austin, TX"],
  "listingType": "forSale",
  "maxItems": 100
}
```

That run returns 100 listings in a few seconds and costs $0.15.

#### More examples

Homes for sale with filters:

```json
{
  "locations": ["Austin, TX", "78731"],
  "listingType": "forSale",
  "minPrice": 400000,
  "maxPrice": 900000,
  "minBedrooms": 3,
  "hasPool": true,
  "maxItems": 500
}
```

Rentals between $1,500 and $2,500 a month (price filters work on rent):

```json
{
  "locations": ["Denver, CO"],
  "listingType": "forRent",
  "minPrice": 1500,
  "maxPrice": 2500,
  "maxItems": 200
}
```

Homes sold in one ZIP in the last 90 days:

```json
{
  "locations": ["78704"],
  "listingType": "sold",
  "daysOnZillow": "90",
  "maxItems": 1000
}
```

Houses and townhomes for sale by owner:

```json
{
  "locations": ["Austin, TX"],
  "homeTypes": ["house", "townhome"],
  "listingSubTypes": ["byOwner"],
  "maxItems": 200
}
```

Foreclosures and auctions, plus homes already under contract:

```json
{
  "locations": ["Maricopa County, AZ"],
  "listingSubTypes": ["foreclosure", "auction", "pending"],
  "maxItems": 500
}
```

New listings only, for a daily schedule:

```json
{
  "locations": ["Phoenix, AZ"],
  "daysOnZillow": "1",
  "maxItems": 0
}
```

### Input reference

| Field | What it does |
|---|---|
| **Locations** | Cities, ZIP codes, counties or neighborhoods, like `Austin, TX`, `78731` or `Brooklyn, NY`. Places Zillow doesn't recognize are listed in the log and skipped |
| **Zillow search URLs** | Paste a search you set up on zillow.com. It runs exactly as given |
| **What to look for** | For sale, for rent or recently sold |
| **Maximum results** | Your spend cap for the run. 0 means no cap. API callers can send `limit` or `maxResults` instead |
| **Maximum per location** | Caps each location separately, so one big city doesn't use up the whole run |
| **Filters** | Price (or monthly rent), beds, baths, living area, lot size, year built, listed within, and must-haves: pool, waterfront, single story, garage, air conditioning, basement, open house, 3D tour |
| **Home types** | Houses, townhomes, condos, apartments, multi-family, land, manufactured. Empty means every type. On rentals, apartments and condos count as one type |
| **Listing types** | For sale only: listed by an agent, for sale by owner, new construction, foreclosures and bank-owned, auctions, coming soon, and pending or under contract. Pick some to get only those. Empty means Zillow's usual mix, which leaves out pending homes |
| **Sort results by** | Newest, price high to low, price low to high, lot size, square footage or bedrooms. Only matters when your cap is lower than the number of matches |
| **Cover large areas in full** | On by default. Turn it off to stop at 820 results per location and spend less |

### Output example

A real row from an Austin, TX run (October 2026):

```json
{
  "zpid": 64625418,
  "url": "https://www.zillow.com/homedetails/11008-Sierra-Ridge-Ct-Austin-TX-78739/64625418_zpid/",
  "listingType": "forSale",
  "statusText": "Active",
  "homeStatus": "FOR_SALE",
  "homeType": "SINGLE_FAMILY",
  "price": 1375000,
  "priceLabel": "$1,375,000",
  "currency": "USD",
  "zestimate": 1339300,
  "rentZestimate": 6769,
  "taxAssessedValue": 1153612,
  "pricePerSqft": 313,
  "priceChange": null,
  "priceChangeDate": null,
  "priceChangeLabel": null,
  "lotAreaValue": 0.3826,
  "lotAreaUnits": "Acres",
  "lotSize": 16666,
  "bedrooms": 5,
  "bathrooms": 4,
  "livingArea": 4395,
  "streetAddress": "11008 Sierra Ridge Ct",
  "city": "Austin",
  "state": "TX",
  "zipcode": "78739",
  "address": "11008 Sierra Ridge Ct, Austin, TX 78739",
  "latitude": 30.191551,
  "longitude": -97.90368,
  "daysOnZillow": 11,
  "datePosted": "2026-10-08",
  "dateSold": null,
  "brokerName": "Keller Williams Realty",
  "isForSaleByAgent": true,
  "isForSaleByOwner": false,
  "isNewConstruction": false,
  "isComingSoon": false,
  "isForAuction": false,
  "isForeclosure": false,
  "isBankOwned": false,
  "isPending": false,
  "isOpenHouse": false,
  "isZillowOwned": false,
  "isFeaturedListing": false,
  "hasVideo": false,
  "has3DModel": true,
  "isShowcaseListing": true,
  "mainImage": "https://photos.zillowstatic.com/fp/1b972ea06e533e781a6f883814ae0438-p_e.jpg",
  "photoCount": 27,
  "photos": [
    "https://photos.zillowstatic.com/fp/1b972ea06e533e781a6f883814ae0438-cc_ft_1536.jpg",
    "https://photos.zillowstatic.com/fp/3f7c92c2fbd198bd1ca734ad3084572d-cc_ft_1536.jpg",
    "... 25 more"
  ],
  "isUndisclosedAddress": false,
  "isBuilding": false,
  "buildingName": null,
  "priceMin": null,
  "priceMax": null,
  "bedroomsMin": null,
  "bedroomsMax": null,
  "unitCount": null,
  "availableUnitCount": null,
  "scrapedAt": "2026-10-20T14:03:12Z",
  "searchLocation": "Austin, TX"
}
```

### Pricing

You pay per listing delivered to your dataset. There's no start fee, and platform usage is included.

| Your Apify plan | Price per listing | Per 1,000 listings |
|---|---:|---:|
| Free | $0.0015 | $1.50 |
| Starter (Bronze) | $0.0013 | $1.30 |
| Scale (Silver) | $0.0011 | $1.10 |
| Business (Gold and above) | $0.0009 | $0.90 |

You're not charged for retries, duplicates or listings that don't match your filters.

**Worked example.** Every for-sale home in Austin, TX (about 5,800 listings) on the Free plan: 5,800 × $0.0015 = **$8.70**. The same run on Starter costs $7.54. A daily "listed in the last 24 hours" feed for one city usually returns a few hundred rows, so it costs cents per day.

**Search, then details.** Filter wide here first, then send only the rows you keep to [Zillow Property Detail Scraper](https://apify.com/studioxl/zillow-detail-scraper) for agent phone, tax rate, year built and the full record. Pick this run's dataset in its **Search results dataset** field.

### FAQ

#### How many results can I get for a big city?

All of them. One Zillow search shows at most 820 results, even when it says there are 5,000 matches. With **Cover large areas in full** on (the default), you get the full set. Austin, TX returned 5,000 distinct listings in under 4 minutes. Turn the setting off to stop at 820 per location.

#### Why do some rows have no Zestimate?

Zillow doesn't publish one for every home. On for-sale listings it's about one in five. The field is empty whenever Zillow shows no estimate.

#### What order do results come in?

Zillow's own default order unless you pick a sort. It's not sorted by date, so pick **Newest first** if you cap the run and want the latest listings. The default order puts Showcase listings first, and those all come with a 3D tour, so a small unsorted run often has `has3DModel: true` on every row.

#### Will I get duplicates?

No. Each `zpid` appears once per run, even when you search overlapping locations. Duplicates are dropped before they reach your dataset and aren't charged.

#### Can I use my own Zillow search URL?

Yes. Paste it into **Zillow search URLs** and every filter in it is kept. Pasted URLs stop at 820 results, because they run exactly as given.

#### Can I schedule it or connect it to other tools?

Yes. Use Apify Schedules for a daily or weekly run, and send results to Google Sheets, Airtable, HubSpot, Slack, Zapier, Make, n8n or a webhook. You can also call it from the Apify API or MCP server.

### Limits

- US listings on Zillow only.
- One row per listing from the search results. Year built, HOA fee, listing agent and description come from [Zillow Property Detail Scraper](https://apify.com/studioxl/zillow-detail-scraper).
- `zestimate` and `rentZestimate` are empty when Zillow hasn't published them.
- `lotAreaValue` is in the unit Zillow shows for that home. Use `lotSize` (always sq ft) to compare lots.
- On sold searches, **Listed within** works as a sold-within window, up to 90 days.
- **Listing types** only apply to homes for sale. On rentals and sold searches they're ignored, and the log says so.
- Home types and listing types don't change a pasted Zillow search URL. Set them on zillow.com before you copy it.

Missing a filter or a field? Open an issue on the Issues tab. If Zillow's own search supports it, it can usually be added.

Related: [Zillow Property Detail Scraper](https://apify.com/studioxl/zillow-detail-scraper) for the full property record, and [Zillow Agent Scraper](https://apify.com/studioxl/zillow-agent-scraper) for the real estate agents working an area.

# Changelog

This Actor's version history is a separate document: https://apify.com/studioxl/zillow-search-scraper/changelog.md

# Actor input Schema

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

Cities, ZIP codes, counties or neighborhoods, for example "Austin, TX", "78731" or "Brooklyn, NY". Places Zillow doesn't recognize are listed in the log and skipped.

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

Paste the address bar from a search you set up on zillow.com, filters included. It runs exactly as given, so it stops at 820 results.

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

Homes for sale, for rent, or sold recently.

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

Your spend cap. The run stops once this many listings are delivered. 100 listings cost about $0.15. Set 0 for no cap.

## `maxItemsPerLocation` (type: `integer`):

Caps each location on its own, so one big city can't use up the whole run. Set 0 for no per-location cap.

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

Sale price for sale and sold searches, monthly rent for rentals. For example 400000.

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

Sale price for sale and sold searches, monthly rent for rentals. For example 900000.

## `homeTypes` (type: `array`):

Leave empty for every type. On rentals, Zillow treats apartments and condos as one type, so picking either gets both.

## `minBedrooms` (type: `integer`):

Fewest bedrooms, for example 3.

## `maxBedrooms` (type: `integer`):

Most bedrooms, for example 5.

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

Fewest bathrooms, for example 2.

## `minLivingArea` (type: `integer`):

Smallest interior size in sq ft, for example 1500.

## `maxLivingArea` (type: `integer`):

Largest interior size in sq ft, for example 3000.

## `minLotSize` (type: `integer`):

Smallest lot in sq ft. One acre is 43,560 sq ft.

## `maxLotSize` (type: `integer`):

Largest lot in sq ft. One acre is 43,560 sq ft.

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

Earliest year built, for example 2000.

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

Latest year built, for example 2020.

## `daysOnZillow` (type: `string`):

Only listings that went up within this window. On sold searches it's the sold-within window. Pick Last 24 hours for a daily new-listings feed.

## `listingSubTypes` (type: `array`):

Leave empty for Zillow's usual mix: agent and owner listings, new construction, foreclosures, auctions and coming soon, but not pending. Pick one or more to get only those. Pending adds homes that are pending or under contract.

## `hasPool` (type: `boolean`):

Only listings with a pool.

## `isWaterfront` (type: `boolean`):

Only listings on the water.

## `singleStoryOnly` (type: `boolean`):

Only single-story homes.

## `hasGarage` (type: `boolean`):

Only listings with a garage.

## `hasAirConditioning` (type: `boolean`):

Only listings with air conditioning.

## `hasBasement` (type: `boolean`):

Only listings with a basement.

## `mustHaveOpenHouse` (type: `boolean`):

Only listings with an open house scheduled.

## `mustHave3dTour` (type: `boolean`):

Only listings with a 3D tour.

## `sortBy` (type: `string`):

Which listings come first. Only matters when your cap is lower than the number of matches.

## `splitLargeAreas` (type: `boolean`):

On: big areas come back in full. Austin, TX has over 5,000 homes for sale and you get all of them. Off: stop at 820 results per location and spend less.

## `respectRobotsTxt` (type: `boolean`):

Leave off. When on, no search runs and the run ends with a message saying why.

## `maxConcurrency` (type: `integer`):

Leave at 10. Higher values don't make runs faster.

## `maxRequestsPerMinute` (type: `integer`):

Leave at 300. Higher values don't make runs faster.

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

Leave as is. Changing this usually returns no results.

## Actor input object example

```json
{
  "locations": [
    "Austin, TX",
    "78731"
  ],
  "searchUrls": [],
  "listingType": "forSale",
  "maxItems": 100,
  "maxItemsPerLocation": 0,
  "daysOnZillow": "",
  "hasPool": false,
  "isWaterfront": false,
  "singleStoryOnly": false,
  "hasGarage": false,
  "hasAirConditioning": false,
  "hasBasement": false,
  "mustHaveOpenHouse": false,
  "mustHave3dTour": false,
  "sortBy": "",
  "splitLargeAreas": true,
  "respectRobotsTxt": false,
  "maxConcurrency": 10,
  "maxRequestsPerMinute": 300,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Every matching Zillow listing found by the search, one row each, de-duplicated by zpid. Opens on the Listings view; switch views in Console to see Price vs Zestimate, Price cuts & listing type, Coordinates, or Rentals & buildings.

# 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": [
        "Austin, TX"
    ],
    "searchUrls": [],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("studioxl/zillow-search-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": ["Austin, TX"],
    "searchUrls": [],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("studioxl/zillow-search-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": [
    "Austin, TX"
  ],
  "searchUrls": [],
  "maxItems": 100
}' |
apify call studioxl/zillow-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studioxl/zillow-search-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/QgccYX0PYWOXmjVQH/builds/8RvdD2o6Jk2mK0JFg/openapi.json
