# Zillow Scraper — Listings, Rentals, Sold & Agent Contacts (`nice_dev/zillow-listings-scraper`) Actor

Scrape Zillow homes for sale, rentals and sold homes by city, ZIP, neighborhood or search URL: price, Zestimate, beds, baths, area, photos, history, agent contacts. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/nice_dev/zillow-listings-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Real estate, Lead generation, MCP servers
- **Stats:** 2 total users, 1 monthly users, 66.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

### 🏠 What is Zillow Listings Scraper?

**Zillow Listings Scraper** extracts **homes for sale, rentals and recently sold homes from [Zillow](https://www.zillow.com)**: **price, Zestimate, rent Zestimate, beds, baths, living area, address, coordinates and photos**, and, when you tick them, the full property record, the listing agent's contact, listing views and saves, comparable homes, every unit of a rental building, climate risk and home highlights. It works as a **Zillow API alternative**: run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.

Type a **place** (`Seattle, WA`, a ZIP code, a neighborhood, a county), set the filters you know from Zillow, click **Start**, and download the listings in JSON, CSV or Excel. You can also paste Zillow search or property URLs, search around a map point and a radius, or give Zillow property IDs and street addresses. No login, nothing to set up. Tick **Only new listings** to follow a market: each run returns what you have not seen, and **Also return price and status changes** adds the listings whose price or status moved.

### 📋 What data can you extract from Zillow?

One item per listing, 149 fields:

| Category | What you get |
| --- | --- |
| 🏷️ **Listing and status** | Zillow ID, link, for sale / for rent / sold / pending / coming soon, listing type (agent, owner, new construction, foreclosure, auction) — `FOR_SALE`, `by_agent` |
| 💰 **Price and value** | price (monthly rent for rentals, sold price for sold homes), price per square foot, price cuts, Zestimate, rent Zestimate, tax assessed value, price against the Zestimate — `$1,395,000`, Zestimate `$1,338,500` |
| 🏡 **The property** | home type, bedrooms, bathrooms, living area, lot size, year built, stories, parking, heating, cooling, appliances, HOA fee, parcel number, every fact and feature Zillow lists |
| 📍 **Address and place** | full address, street, unit, city, state, ZIP, county, neighborhood, coordinates, time zone |
| 🕒 **Dates** | days on Zillow, date the listing went up (what the date filters read), sold date, move-in date, open houses |
| 📈 **History** | price history (with the agents of each sale), tax history, Zestimate history over up to 10 years, last sold price |
| 🖼️ **Photos and tours** | main photo, every photo (with property details), 3D tour, video flag, interactive floor plan, street view, description |
| 🎓 **Area** | nearby and assigned schools with ratings, students per teacher and themed ratings, Walk, Transit and Bike scores with their words (`Very Walkable`), mortgage rates, flood / fire / wind / air / heat risk, Zillow's home highlights |
| 🏢 **Rental buildings** | building name and link, every available unit with beds, baths, price, area and move-in date, floor plans, amenities, pet policy, building photos, 3D visits of the common areas |
| 👤 **Agent and broker** | listing agent name, phone, license and e-mail (when Zillow shows it), co-agent, brokerage phone, MLS, and for sold homes the buyer's agent; the owner's name and phone for sale-by-owner; the buyer's and seller's agent of each past sale in the price history |
| 📊 **Views and comparables** | times the listing was viewed and saved, up to 5 comparable homes, nearby homes |
| 🔔 **Monitoring** | what changed since the last delivery: new, price changed, status changed, previous price and status |

Every field, with an example, is listed in the **Output** section below.

The fields marked **detail** in the Output tab (description, price and tax history, schools, facts and features…) are filled when **Add property details** is on (off by default). The search itself already gives price, Zestimate, rent Zestimate, tax assessed value, beds, baths, area, coordinates and the broker. The agent, views, comparables, building, climate and highlight fields come with their own option, each off by default.

### ✅ Why use Zillow Listings Scraper?

- 🏘️ **Sale, rent and sold in one Actor**: one form, the same fields for the three.
- 📍 **Type the place, not a URL**: city, ZIP code, neighborhood, county or state; a whole big area is read, you do not cut it into pieces yourself. Or paste any Zillow search URL: its filters are kept.
- 🎛️ **Zillow's filters, and more**: price, beds, baths, area, lot, year, HOA, home and listing types, open houses, pools, garages, views, schools, rental filters (pets, laundry, furnished…), plus filters Zillow does not have: price against the Zestimate, excluded words, a distance around a point.
- 💡 **Zestimate and tax value straight from the search**: no extra page to read for the first valuation figures.
- 🧩 **Options à la carte**: property details, agent contact, listing stats, comparables, building units, climate risk and home highlights are separate, all off by default. You only pay for what you tick, and only for the listings where it brings data.
- 🔔 **Monitoring built in**: **Only new listings** returns (and charges) what a previous run did not deliver; **Also return price and status changes** adds the listings that moved.
- 🗂️ **Several searches in one run**: keywords × places, with a cap per search so that one big city cannot eat the whole budget.
- 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…), proxy rotation and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Zillow

1. Create a free Apify account.
2. Open **Zillow Listings Scraper**, type a **Location** (e.g. `Seattle, WA`) and choose **Listing status**: for sale, for rent or sold.
3. Set the filters you need (price, bedrooms, home types…). Or paste your own Zillow URLs into **Zillow URLs**: any search results page (all filters set on the site are kept), single property pages or building pages (`/apartments/…`, `/b/…`). Or give **Zillow property IDs** or **Addresses**.
4. Tick the options you want (**Add property details**, **Add agent and broker contact**…), set **Max listings** (100 by default, 0 = no limit) — and **Max listings per search** when you run several searches — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

### 💰 How much does it cost to scrape Zillow?

This Actor uses **pay per event** pricing: a small fee when a run starts, and a price per listing. The price per listing is higher when **Add property details** is on, because the property page is read too. Each option you tick adds its own price, only for the listings where it delivers data: agent contact for a listing where a phone number is found, listing stats where the counts are given, comparables where there are some, building units per building page, climate risk where scores exist, home highlights where there are some. Without any option, a listing costs the price of the search alone. The prices are on the Pricing tab of the Actor page, and the **Max listings** you set caps the bill. Filters that Zillow does not offer are applied by the Actor on every listing it reads (dates, excluded words, the distance around a point, the price against the Zestimate, a phone number, non-owner-occupied only, and the minimum parking spots on rentals): a listing you keep costs its normal price, a listing such a filter drops costs only a small filter check, never more than a kept listing. Platform usage (compute, proxy) is included in the price.

### ⚙️ Input

A search for homes for sale in a price range:

```json
{
    "location": "Seattle, WA",
    "listingStatus": "for_sale",
    "minPrice": 500000,
    "maxPrice": 800000,
    "maxItems": 200
}
```

Rentals with a filter, sorted by price:

```json
{
    "location": "Austin, TX",
    "listingStatus": "for_rent",
    "minBedrooms": 2,
    "maxPrice": 3000,
    "petsAllowed": "small_dogs",
    "sortBy": "price_low",
    "maxItems": 100
}
```

Several searches, a cap per search, only recent listings, only the ones not delivered before:

```json
{
    "searchQueries": ["waterfront", "ADU"],
    "locations": ["Seattle, WA", "Austin, TX"],
    "maxItemsPerQuery": 50,
    "extractDetails": true,
    "postedAfter": "7 days",
    "onlyNew": true,
    "stateKey": "seattle-austin"
}
```

Homes sold in the last 30 days around a point:

```json
{
    "latitude": "47.6062",
    "longitude": "-122.3321",
    "radiusMiles": 3,
    "listingStatus": "sold",
    "daysOnZillow": "30",
    "maxItems": 300
}
```

Or with your own URLs, IDs and addresses:

```json
{
    "startUrls": [
        { "url": "https://www.zillow.com/seattle-wa/rentals/" },
        { "url": "https://www.zillow.com/homedetails/6220-2nd-Ave-NW-Seattle-WA-98107/49125964_zpid/" }
    ],
    "zpids": ["49125964"],
    "addresses": ["6220 2nd Ave NW, Seattle, WA 98107"],
    "maxItems": 500
}
```

| Field | Notes |
| --- | --- |
| `startUrls` | Search results pages copied from your browser (every filter set on Zillow is kept, a map area you drew too), property pages or building pages (`https://www.zillow.com/apartments/seattle-wa/nordic-falk/5XjDkh/`, `https://www.zillow.com/b/escala-seattle-wa-CkMW6C/`: one result for the building, with its units when **Add building units** is on), e.g. `https://www.zillow.com/seattle-wa/rentals/`. When it is not empty, the location fields are ignored (zpids, addresses and the dataset still add to it). A search URL pasted at several pages (the end of the path, as in /seattle-wa/3_p/) is one search, read once from its first page. |
| `location`, `locations` | City, ZIP code, neighborhood, county or state, as typed in Zillow's search box: `Seattle, WA`, `98103`, `King County, WA`. `locations` adds more places. Every keyword is searched in every location (max 500 searches per run). |
| `zpids` | Zillow property IDs, the number in the property URL: `49125964`. Each one gives one result with the details. |
| `addresses` | Full street addresses: `6220 2nd Ave NW, Seattle, WA 98107`. Each one gives one result with the details. |
| `searchResultsDatasetId` | ID of an Apify dataset that holds Zillow listings (a previous run of this Actor, for instance): each listing is read again with its details. |
| `latitude` | Center of a search around a point instead of a named area, in decimal degrees: `47.6062`. Used with `longitude` and `radiusMiles`; it replaces the location. |
| `longitude` | Longitude of that center: `-122.3321`. |
| `radiusMiles` | Distance around the point, in miles. Listings farther than this are dropped. |
| `listingStatus` | `for_sale`, `for_rent` or `sold` (recently sold homes). |
| `query`, `searchQueries` | Zillow's own keyword filter, not a full-text search: `waterfront`, `ADU`. `searchQueries` adds more keywords (one search each). Empty = no keyword filter. |
| `maxItems`, `maxItemsPerQuery` | Stop after this many listings for the whole run (`0` = unlimited), or for EACH search (keyword × place, or search URL) so that the first search cannot use up the whole budget. |
| `sortBy` | Order Zillow returns the listings in: `newest`, `price_low`. Newest first is the one to use for monitoring; with a cap of up to 820 listings per search, it decides which listings you get (a run that asks for more than the list pages can give, 820 listings and fewer when your filters or Only new listings skip some, reads the map in parts, and the order is then no longer kept). |
| `extractDetails` | Add the full property record to each listing: description, all photos, price and tax history, schools, facts and features, HOA, parcel number, mortgage rates, scores. One extra light request per listing, charged as the dearer listing price. |
| `includeAgentContact` | Add the listing agent's name, phone and license number, the co-agent, the brokerage, the MLS, and for sold homes the buyer's agent. For sale-by-owner listings, the owner's name and phone as shown on Zillow. The agent's e-mail comes with them when Zillow shows it (Showcase listings). Charged per listing where a phone is delivered. |
| `includeListingStats` | Add how many times the listing was viewed and saved on Zillow. Charged per listing where the counts are delivered. |
| `includeComparables` | Add the comparable homes Zillow uses for the Zestimate (up to 5) and nearby homes. Charged per listing that has comparables. |
| `extractBuildingUnits`, `oneRowPerUnit` | Rentals and condos: open each building page to add every available unit, floor plans, building photos, amenities, 3D visits of the common areas and schools; charged per building. With `oneRowPerUnit`, one result per unit instead of one per building. |
| `includeClimateRisk` | Add flood, fire, wind, air and heat risk scores with the FEMA flood zone. Charged per listing with scores. |
| `includeHomeInsights` | Add Zillow's short highlights of the home. Charged per listing with highlights. |
| `minPrice`, `maxPrice` | Price in US dollars; for rentals, the monthly rent. |
| `minBedrooms`, `maxBedrooms`, `minBathrooms`, `maxBathrooms` | Number of bedrooms and bathrooms. |
| `minSqft`, `maxSqft` | Living area, in square feet. |
| `minLotSize`, `maxLotSize` | Lot size, in square feet (1 acre = 43,560 sqft). |
| `minYearBuilt`, `maxYearBuilt` | Year built. |
| `minHoaFee`, `maxHoaFee` | Monthly homeowners association fee, in US dollars. |
| `includeHomesWithNoHoaData` | With an HOA fee filter: also keep the homes whose HOA fee is unknown (on by default). |
| `minParkingSpots` | Minimum number of parking spots. For sale and sold listings Zillow applies it; on rentals this filter needs the property page: tick **Add property details** (or another option that reads the property page), otherwise it is ignored on the listings of a search and the run log says so (a listing asked by id, a zpid, a listing URL or an address, always has its page read, so it is filtered anyway); the Actor then drops the rentals below (a small filter check per dropped listing). |
| `homeTypes` | Keep only these types: `single_family`, `townhouse`, `condo`, `multi_family`, `apartment`, `land`, `manufactured`. Empty = all. |
| `listingTypes` | For sale searches. Ticking `by_agent`, `by_owner`, `new_construction`, `foreclosure`, `auction` or `coming_soon` narrows the search to the ticked ones; `pending`, `pre_foreclosure`, `foreclosed` and `accepting_backup_offers` are off by default and are added to the active listings when chosen. Empty = Zillow's default. |
| `daysOnZillow` | For sale and rent: listed in the last N days. For sold homes: sold in the last N days. `any`, `1`, `7`, `14`, `30`, `90`, `6m`, `12m`, `24m`, `36m`. |
| `openHousesOnly`, `virtualTourOnly`, `priceReducedOnly`, `showcaseOnly`, `onlyWithPhotos` | Only listings with an open house, a 3D tour, a price cut, Zillow Showcase photos, or photos. |
| `hasGarage`, `hasPool`, `hasAirConditioning`, `hasWaterView`, `hasBasement`, `hasUnfinishedBasement`, `isSingleStory`, `isWaterfront` | Only homes with that feature (`hasBasement` = finished basement). |
| `views` | Only homes with one of these views: `city`, `mountain`, `park`, `water`. Empty = any. |
| `ageRestricted55Plus` | Age-restricted (55+) communities: `include`, `exclude` or `only`. |
| `onlyNonOwnerOccupied` | Only homes Zillow marks as not occupied by their owner. This is Zillow's flag as it sends it, and Zillow sets it on almost every listing (for sale, for rent, sold, land, foreclosures, by owner, new construction), so this filter rarely drops anything. Applied by the Actor on every listing it reads: a dropped listing costs a small filter check. |
| `petsAllowed` | Rentals only, the kind of pet accepted: `any`, `cats`, `small_dogs`, `large_dogs`, `no_pets`. |
| `rentalSpace` | Rentals only: `any`, `entire_place` or `room`. |
| `moveInDate` | Rentals only: available by this date, e.g. `2026-11-01`. |
| `inUnitLaundryOnly`, `furnishedOnly`, `forRentByOwner`, `parkingAvailable`, `elevator`, `hardwoodFloors`, `highSpeedInternet`, `outdoorSpace`, `utilitiesIncluded`, `disabledAccess`, `controlledAccess`, `incomeRestricted`, `shortTermLease`, `acceptsZillowApplications`, `apartmentCommunity`, `instantTourOnly`, `hideNoMoveInDate` | Rentals only: keep the listings with that feature (laundry in the unit, furnished, rented directly by the owner, on-site parking, elevator, hardwood floors, internet, outdoor space, utilities included, accessible, controlled access, income restricted, short-term lease, applications through Zillow, managed apartment community, instant tour); `hideNoMoveInDate` drops the listings that give no availability date. |
| `schools` | Only homes near these kinds of schools: `elementary`, `middle`, `high`, `public`, `private`, `charter`. Empty = no school filter. |
| `schoolsRating` | With `schools`: minimum GreatSchools rating, from 1 to 10. |
| `includeUnratedSchools` | With `schools`: also count the schools that have no rating. |
| `postedAfter`, `postedBefore` | Date range of the listing date shown on Zillow (sold homes: the sold date): `2026-09-01`, or a period before now (`7 days`, `2 weeks`, `24 hours`). For sale and for rent the date is on the property page: tick **Add property details** (or another option that reads the property page), otherwise the filter is ignored on the listings of a search and the run log says so (a listing asked by id, a zpid, a listing URL or an address, always has its page read, so it is filtered anyway). |
| `excludeKeywords` | Drop the listings whose address, building name, card highlight or description contains one of these words (case and accents ignored). |
| `requirePhone`, `privateSellersOnly` | `requirePhone` drops the listings without an agent or owner phone number and turns on **Add agent and broker contact**; `privateSellersOnly` keeps the sale-by-owner listings. |
| `maxPriceVsZestimatePct` | Keep only the listings priced at most this percentage above the Zestimate: `-10` is at least 10 % under it. Listings without a Zestimate are dropped. For sale and sold only: not applied to rentals. |
| `onlyNew`, `stateKey`, `resetState`, `trackChanges` | Monitoring: only the listings never delivered under this memory key, e.g. `paris-rentals`; `resetState` forgets the memory; `trackChanges` also returns the delivered listings whose price or status changed. |
| Advanced | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `requestTimeoutSecs`, `debugLog`. |

### 📦 Output

One item per listing. Here is a real one for a home for sale, with **Add property details** on; it is shortened (the long texts and lists are cut, the other fields are listed below):

```json
{
    "id": "49125964",
    "zpid": "49125964",
    "url": "https://www.zillow.com/homedetails/6220-2nd-Ave-NW-Seattle-WA-98107/49125964_zpid/",
    "homeStatus": "FOR_SALE",
    "statusType": "FOR_SALE",
    "statusText": "Active",
    "listingType": "by_agent",
    "price": 1395000,
    "currency": "USD",
    "pricePerSquareFoot": 412.72,
    "zestimate": 1338500,
    "rentZestimate": 5706,
    "taxAssessedValue": 1252000,
    "priceVsZestimatePct": 4.22,
    "homeType": "SINGLE_FAMILY",
    "bedrooms": 5,
    "bathrooms": 4,
    "livingArea": 3380,
    "lotSize": 4400,
    "yearBuilt": 1918,
    "address": "6220 2nd Avenue NW, Seattle, WA 98107",
    "city": "Seattle",
    "state": "WA",
    "zipcode": "98107",
    "neighborhood": "Phinney Ridge",
    "latitude": 47.67502,
    "longitude": -122.35918,
    "daysOnZillow": 6,
    "publishedAt": "2026-09-24T19:04:39.000Z",
    "brokerName": "Windermere Mercer Island",
    "isFsbo": false,
    "isOpenHouse": true,
    "openHouses": [{"start": "2026-10-02T23:00:00.000Z", "end": "2026-10-03T01:00:00.000Z"}],
    "has3DModel": true,
    "imgSrc": "https://photos.zillowstatic.com/fp/1596aac130a40a430068ff6a8c0fdc7b-p_e.jpg",
    "photos": ["https://photos.zillowstatic.com/fp/1596aac130a40a430068ff6a8c0fdc7b-uncropped_scaled_within_1536_1152.jpg", "https://photos.zillowstatic.com/fp/72855ae8d978c5557d0f8bba0e7e0291-uncropped_scaled_within_1536_1152.jpg"],
    "photoCount": 40,
    "description": "Perched above a favorite Phinney Ridge block, this beloved Craftsman has been home to the same owners for 46 yea…",
    "heating": ["Fireplace", "Baseboard", "Radiant", "Radiator", "Natural Gas"],
    "priceHistory": [{"date": "2026-09-24", "event": "Listed for sale", "price": 1395000, "pricePerSquareFoot": 413, "priceChangeRate": 0, "source": "NWMLS as distributed by MLS GRID", "buyerAgent": null, "sellerAgent": null}],
    "taxHistory": [{"year": 2025, "taxPaid": 13028.19, "taxIncreaseRate": 0.0651134, "value": 1252000, "valueIncreaseRate": -0.011058452}],
    "schools": [{"name": "West Woodland Elementary School", "rating": 9, "grades": "K-5", "distance": 0.3, "level": "Elementary", "type": "Public", "link": "https://www.greatschools.org/washington/seattle/1618-West-Woodland-Elementary-School/", "district": "Seattle Public Schools", "enrollment": 353, "studentTeacherRatio": 17.25, "studentCounselorRatio": 1132, "percentageOfFullTimeTeachersWhoAreCertified": 100, "themedRatings": [{"name": "Test scores rating", "rating": 10, "type": "testScores"}, {"name": "Student growth rating", "rating": 7, "type": "studentGrowth"}], "assigned": true}],
    "mortgageRates": {"thirtyYearFixed": 7.473, "fifteenYearFixed": 6.977, "arm5": 6.583, "source": "ZGMI", "updatedAt": "2026-10-01T15:59:58.362Z"},
    "mlsId": "2586847",
    "mlsName": "NWMLS as distributed by MLS GRID",
    "searchUrl": "https://www.zillow.com/seattle-wa/?searchQueryState=%7B%7D",
    "scrapedAt": "2026-10-01T18:00:00.000Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel. A column Zillow gives nothing for is `null` (an empty list for a list), never invented.

#### All 149 fields

| Fields | What you get |
| --- | --- |
| `id`, `zpid`, `url` | Zillow property ID, the same ID as `zpid` (for a rental building, the building key `47.617607--122.3312` and `zpid` is `null`), link to the Zillow page |
| `homeStatus`, `statusType`, `statusText`, `listingType` | `FOR_SALE`, `FOR_RENT`, `RECENTLY_SOLD`, `PENDING`, `COMING_SOON`, `OTHER`; status type `FOR_SALE`, `FOR_RENT`, `SOLD`; status as shown on the card; `by_agent`, `by_owner`, `new_construction`, `foreclosure`, `pre_foreclosure`, `auction`, `coming_soon`, `pending`, `rental`, `sold` |
| `price`, `currency`, `priceMin`, `priceMax`, `pricePerSquareFoot`, `priceChange`, `priceChangedAt` | price in US dollars (monthly rent, sold price; `null` when Zillow does not show it), `USD`, lowest and highest price of a building's units (as Zillow shows them: required monthly fees included when `listPriceIncludesRequiredMonthlyFees` is true), price per square foot, last price change (negative = cut) and its date |
| `zestimate`, `rentZestimate`, `zestimateLowPercent`, `zestimateHighPercent`, `zestimateMinus30`, `rentZestimateMinus30`, `zestimateHistory`, `taxAssessedValue`, `priceVsZestimatePct`, `lastSoldPrice` | Zillow's value and rent estimates, the range around the Zestimate, the estimates 30 days ago, the monthly Zestimate over up to 10 years, tax assessed value, (price - Zestimate) / Zestimate × 100, last sold price |
| `homeType`, `bedrooms`, `bathrooms`, `livingArea`, `lotSize`, `lotAreaValue`, `lotAreaUnit`, `yearBuilt`, `stories` | `SINGLE_FAMILY`, `TOWNHOUSE`, `CONDO`, `MULTI_FAMILY`, `APARTMENT`, `LOT`, `MANUFACTURED`; beds, baths, living area in square feet, lot in square feet (acres converted) and as Zillow shows it with its unit, year built, stories |
| `parkingSpots`, `garageSpots`, `heating`, `cooling`, `appliances` | parking and garage spots, heating and cooling types, appliances included |
| `monthlyHoaFee`, `annualHomeownersInsurance`, `propertyTaxRate`, `parcelId`, `resoFacts` | monthly HOA fee, Zillow's insurance estimate, property tax rate, county parcel number, every fact and feature of the listing as one object |
| `address`, `streetAddress`, `unit`, `city`, `state`, `zipcode` | `6220 2nd Avenue NW, Seattle, WA 98107` in one line, then in parts |
| `timeZone`, `county`, `neighborhood`, `countyFIPS`, `latitude`, `longitude` | `America/Los_Angeles`, `King County`, `Phinney Ridge`, `53033`, GPS coordinates |
| `daysOnZillow`, `timeOnZillow`, `publishedAt`, `dateSold`, `availabilityDate` | days and milliseconds since the listing went up, the date and time it went up (what the date filters read; for sold homes the sold date), sold date, rentals' move-in date |
| `openHouses`, `isOpenHouse`, `has3DModel`, `hasVideo` | scheduled open houses (start and end), has an open house, has a 3D tour, has a video tour |
| `brokerName`, `isFsbo`, `isNewConstruction`, `isForeclosure`, `isAuction`, `isPreforeclosureAuction`, `isNonOwnerOccupied`, `isComingSoon`, `isZillowOwned`, `isUndisclosedAddress`, `isShowcaseListing`, `isIncomeRestricted` | the listing brokerage and the yes / no flags Zillow gives (sale by owner, new construction, foreclosure, auction, not owner-occupied (Zillow's flag, set on almost every listing), coming soon, owned by Zillow, hidden address, Showcase, income-restricted) |
| `contingentListingType`, `newConstructionType`, `listPriceLow`, `lotPremium`, `specialOffer`, `sellingSoonPercentile` | `UNDER_CONTRACT` for a pending sale, new construction kind and its lowest list price and lot premium, promotion shown on the listing, Zillow's "selling soon" percentile from 0 to 1 |
| `isBuilding`, `buildingName`, `buildingUrl`, `availabilityCount`, `units`, `buildingUnits`, `floorPlans`, `hasFloorPlan` | rentals: a card that groups the units of one building, its name, the link of its Zillow page (also on a listing that is a unit of a building), units available, one summary per unit size, every available unit (unit, beds, baths, price, area, move-in date, link), floor plans |
| `buildingAttributes`, `buildingPhotos`, `buildingSchools`, `amenitiesVRModels`, `amenityType`, `marketingTreatments`, `listPriceIncludesRequiredMonthlyFees`, `isRentalWithBasePrice`, `requiredMonthlyFees` | building amenities, pet policy and parking, building photos, schools assigned to the building, the 3D visits of the common areas (label, viewer link, thumbnail, id), the amenity and badges shown on the card, whether the price includes the required monthly fees or is a base rent, those fees (min and max) |
| `imgSrc`, `photos`, `photoCount`, `flexFieldText` | main photo, photo URLs (every photo with details; the photos of the card otherwise, only the main photo on some rows), number of photos (empty when only the main photo is known), the short highlight on the card (`Fenced yard`) |
| `description`, `virtualTourUrl`, `interactiveFloorPlanUrl`, `streetViewImageUrl`, `staticMapUrl` | full listing description, links to the 3D tour, the interactive floor plan, a Street View image and a map image |
| `priceHistory`, `taxHistory`, `mortgageRates` | price events (date, event, price, source, and for a sale the buyer's and the seller's agent with name, profile link and photo), yearly tax paid and assessed value, the 30-year, 15-year and ARM rates shown on the page |
| `schools`, `walkScore`, `transitScore`, `bikeScore`, `walkScoreDescription`, `transitScoreDescription`, `bikeScoreDescription` | nearby and assigned schools (name, rating, grades, distance, type, link, students per teacher, students per counselor, share of certified teachers, test-score and growth ratings), Walk, Transit and Bike scores and the words next to each (`Very Walkable`, `Good Transit`, `Very Bikeable`) |
| `climateRisk`, `homeInsightsPhrases`, `homeInsightsModelId`, `homeInsightsTreatmentId` | flood, fire, wind, air and heat risk (score, label, FEMA zone), Zillow's short highlights of the home (`Updated kitchen`) and the ids Zillow gives them |
| `pageViewCount`, `favoriteCount`, `tourViewCount` | times the listing was viewed, saved, and its 3D tour viewed |
| `mlsId`, `mlsName`, `mlsDisclaimer`, `mlsLastChecked`, `mlsLastUpdated` | MLS listing number, the MLS that provides the listing, its notice, when Zillow last checked it and when the MLS last updated it |
| `agentName`, `agentPhoneNumber`, `agentEmail`, `agentLicenseNumber`, `coAgentName`, `coAgentNumber`, `coAgentLicenseNumber`, `brokerPhoneNumber`, `listedBy` | listing agent (for sale by owner, the owner's name and phone), the agent's e-mail when Zillow shows it (Showcase listings), co-agent, brokerage phone, who lists: `AGENT`, `OWNER`, `BUILDER`, `PROPERTY_MANAGER` |
| `buyerAgentName`, `buyerAgentLicenseNumber`, `buyerBrokerageName` | sold homes: the buyer's agent, license number and brokerage |
| `comparables`, `nearbyHomes` | up to 5 homes Zillow compares for the Zestimate and the nearby homes (zpid, address, price, beds, baths, area, link) |
| `changeType`, `previousPrice`, `previousStatus` | monitoring with **Also return price and status changes**: `new`, `price_changed` or `status_changed`, the price and the status at the previous delivery |
| `searchUrl`, `scrapedAt` | the Zillow search (or input) that found the listing, the time it was read (ISO 8601 UTC) |

The agent and broker columns, the views, the comparables, the building units, the climate risk and the home highlights are filled only when their option is ticked; the columns marked **detail** need **Add property details**. Everything else comes with the search.

### 💡 Tips

#### How to get more results

Set `maxItems` to `0` and use a broad place: a whole city, county or state is read in full. To split a market, run one search per place with `locations` and give each its own cap with `maxItemsPerQuery`. To keep a search narrow, use the filters rather than a smaller area.

#### How to reduce costs

The price is per listing, so the levers are `maxItems`, `maxItemsPerQuery`, the filters (a dropped listing costs only the filter check, lower than a listing) and `onlyNew` for recurring runs (you never pay twice for the same listing). The search alone already gives price, Zestimate, rent Zestimate, tax assessed value, beds, baths, area, coordinates and broker: tick **Add property details** and the options only when you need what they add.

#### Several searches in one run

Fill `searchQueries` and / or `locations`: the Actor runs one search per keyword × place (3 keywords × 4 cities = 12 searches, up to 500 per run). The single `query` and `location` fields still work and are added to the lists. A listing found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap: without it the first searches can use up the whole `maxItems` budget. You can also paste several search URLs into `startUrls`: each one is a search of its own, with the same cap. If your filters match almost nothing in one search (300 listings in a row dropped), that search stops and the run goes on with the next ones; the run stops only when every search is in that case.

#### Rentals and buildings

In a rental search, an apartment building is one row (`isBuilding`): its units are summed up in `units`, with the lowest and highest price in `priceMin` and `priceMax`, and `zpid` is `null`. Tick **Add building units** to get every available unit of the building with its own price, beds, baths and area; add **One row per unit** to have one result per unit instead.

#### Monitoring: only the new listings

Tick **Only new listings** (`onlyNew`) and schedule the Actor. The first run returns everything it is allowed to. With a **Max listings** cap it remembers only the listings it delivered: the next runs also return the older listings never delivered, none of them charged twice, until the whole search is covered. To watch a search, make the first run without a cap, or on a narrow search. Each later run skips the listings already delivered: they are not saved and not charged, and the property page of a listing found by a search is not opened. A listing your filters drop is checked (and charged the filter check) once: the next runs with the same filters skip it for free, even if its price changed since; change a filter, or tick `resetState`, to check them again. A listing that does not pass a time-dependent filter yet (a relative "posted before" date, for example `30 days`) is checked again on the next run, and charged the filter check again while it is still refused, so it is delivered as soon as it passes. A listing you asked for by id (`zpids`, `addresses`, a property URL, a dataset) is still read again, but neither saved nor charged. The memory lives in a named key-value store of your account (`zillow-listings-scraper-seen`, up to 150,000 listings per key) and is only updated with listings that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's listings), and tick `resetState` once to start over. Choose **Sort by** newest for monitoring. Tick **Also return price and status changes** (`trackChanges`) to get, besides the new listings, the ones already delivered whose price or status changed since: `changeType`, `previousPrice` and `previousStatus` say what moved.

#### Filter by listing date

`postedAfter` and `postedBefore` take a date (`2026-09-01`, the whole day is included, US time) or a period before now (`7 days`, `2 weeks`; via the API also `24 hours` or a full ISO date-time). The filter reads `publishedAt` (sold homes: the sold date); a listing without a date is dropped as soon as a date bound is set. Buildings (apartment communities) carry no listing date: a date bound drops them, a pasted building URL included (its page is not read, nothing is charged, the run log says so). Sold homes carry their date in the search; for the others the date is on the property page, so tick **Add property details** with a date filter (or any other option that reads the property page): without one, the date filter on those listings is ignored and the run log says so (a listing asked by id, a zpid, a listing URL or an address, always has its page read, so it is filtered anyway). Filtered-out listings are not saved and do not count in `maxItems` (each listing dropped costs the filter check, see Pricing); the run summary tells how many were filtered.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Zillow listing (for sale, for rent or sold). Actor id: `nice_dev/zillow-listings-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/zillow-listings-scraper`.

Smallest input, for a cheap first call:

```json
{
    "location": "Seattle, WA",
    "maxItems": 10
}
```

Key output fields: `url`, `address`, `price`, `homeStatus`, `bedrooms`, `bathrooms`, `livingArea`, `zestimate` and `publishedAt`; with **Add property details**, also `description`, `photos` and `priceHistory`.

Cost: pay per listing plus a small fee at run start, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape Zillow?

The Actor only reads what Zillow shows publicly to any anonymous visitor. It logs in to nothing. Results can contain personal data, which is protected by GDPR and by similar laws elsewhere: the name, phone number, e-mail and license number of an agent or of an owner selling without an agent come only with **Add agent and broker contact** (off by default), and the names of the agents of a past sale only with **Add property details** (off by default); do not store them without a legitimate reason. You are responsible for using the data in compliance with Zillow's Terms of Use and applicable law. This Actor is not affiliated with Zillow.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request the site turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 60 seconds, doubled at each retry up to 240 seconds).

#### Is the data safe to open in Excel or to show on a web page?

Addresses, descriptions and agent names are the sellers' and agents' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@` (a phone number, a description such as `-20% today`): Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- Site filters that are not in the input can still be used by pasting a filtered search URL into `startUrls`.
- Fields marked **detail**, such as `description`, price and tax history and schools, come from the property page: they are empty when **Add property details** is off.
- Prices are in US dollars. A listing that shows no price on Zillow (an auction, a state that does not disclose sold prices) has `price` at `null`.
- Without **Also return price and status changes**, `onlyNew` remembers listing ids, not their content: a listing whose price changed is not returned again.
- Two runs sharing the same `stateKey` at the same time may both return the same new listing.

**A run that reaches its timeout** stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with `onlyNew`, remembered, and the run ends *Succeeded* with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

**A run the platform stops without warning** (out of memory)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the listings already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the listings it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the listings of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the listings saved, filtered out and no longer on Zillow (removed while the run was reading them), and the requests that failed after every retry. Those requests and the removed listings are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause (a search URL that does not exist says so, instead of "run it again").

If Zillow changes its pages, you are told instead of paying for blank rows. A results page that counts listings but gives none the Actor can read is an error (listed in `FAILED_REQUESTS`), never a quiet "No listings found". If the first 20 listings read all lack their status type, their coordinates or their address, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first listings are charged. A listing that `postedAfter` / `postedBefore` drops because it has no date at all counts among those 20. A run of fewer listings (a scheduled `onlyNew` run that finds a few new ones, a small **Max listings**) is checked at its end, from 5 listings: its listings are already saved, and the run fails with the missing field instead of ending green.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which URLs failed and why.

# Actor input Schema

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

Zillow search URLs copied from your browser after setting filters on the map (`https://www.zillow.com/seattle-wa/rentals/?searchQueryState=…`), property pages (`https://www.zillow.com/homedetails/…_zpid/`) or building pages (`https://www.zillow.com/apartments/seattle-wa/nordic-falk/5XjDkh/`, `https://www.zillow.com/b/escala-seattle-wa-CkMW6C/`: one result for the building, one per unit with the option One row per unit). Filters written in a search URL are kept, including a map area you drew. When this list is not empty, the location fields below are ignored (zpids, addresses and the dataset still add to it); caps, post-filters and monitoring still apply. A search URL pasted at several pages (the end of the path, as in /seattle-wa/3_p/) is one search, read once from its first page.

## `location` (type: `string`):

City, ZIP code, neighborhood, county or state, as typed in Zillow's search box (e.g. `Seattle, WA`, `98103`, `Capitol Hill, Seattle, WA`, `King County, WA`). The whole area is read: large areas are split into map tiles automatically, past Zillow's 500 / 820 results cap. Empty = only the locations listed below.

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

More locations searched in the same run (same format as Location). They add to the field above.

## `zpids` (type: `array`):

Read these properties directly by Zillow ID (`49125964`, the number in `…/49125964_zpid/`). Each one gives one result with the details. Can be combined with a search.

## `addresses` (type: `array`):

Read these properties directly by full street address (`6220 2nd Ave NW, Seattle, WA 98107`). Each one gives one result with the details. Can be combined with a search.

## `searchResultsDatasetId` (type: `string`):

ID of an Apify dataset that holds Zillow listings (with `url` or `zpid`), e.g. from a previous run of this Actor: each listing is read again with its details.

## `listingStatus` (type: `string`):

Which listings to search: for sale, for rent, or recently sold.

## `query` (type: `string`):

Words Zillow must find in the listing (its own keyword filter, e.g. `waterfront`, `ADU`). Empty = no keyword filter.

## `searchQueries` (type: `array`):

More keyword searches in the same run. Each one is searched in every location (keywords × locations ≤ 500 searches).

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

Maximum number of listings to save for the whole run (after deduplication and filters). 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (keyword × location, or search URL), so that the first search cannot use up the whole **Max listings** budget. 0 = no per-search cap.

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

Order Zillow returns the listings in. Newest first is the one to use for monitoring; with a cap of up to 820 listings per search, it decides which listings you get (a run that asks for more than the list pages can give, 820 listings and fewer when your filters or Only new listings skip some, reads the map in parts, and the order is then no longer kept).

## `extractDetails` (type: `boolean`):

Add the full property record to each result: description, all photos, price history, tax history, nearby schools, facts and features, HOA, parcel number, mortgage rates, walk / transit / bike score. One extra light request per listing, charged as a separate event (`result-with-details` instead of `result`). Off = the search card only, which already carries price, Zestimate, rent Zestimate, tax assessed value, beds, baths, area, GPS and broker name.

## `includeAgentContact` (type: `boolean`):

Add the listing agent's name, phone and license number, the co-agent, the brokerage and its phone, the MLS name and ID, and for sold homes the buyer's agent and brokerage. For sale-by-owner listings, the owner's name and phone as shown on Zillow. Read from the same request as the details. Charged per listing where a phone is delivered (`agent-contact`); listings without one are not charged for it.

## `includeComparables` (type: `boolean`):

Add the comparable homes Zillow uses for the Zestimate (up to 5: address, price, beds, baths, area, status) and nearby homes. One more small request per listing, charged per listing that has comparables (`comparables`).

## `extractBuildingUnits` (type: `boolean`):

Rentals and condos: open each building / community page to add every available unit (unit, beds, baths, price, area, move-in date), floor plans, building photos, amenities and assigned schools. One extra page per building, charged per building (`building-units`).

## `oneRowPerUnit` (type: `boolean`):

With Add building units: one result per unit instead of one per building.

## `includeClimateRisk` (type: `boolean`):

Add flood, fire, wind, air and heat risk scores (First Street, shown on Zillow), with the FEMA flood zone. One more small request per listing, charged per listing with scores (`climate-risk`).

## `includeHomeInsights` (type: `boolean`):

Add Zillow's short highlights of the home (e.g. `Updated kitchen`, `Fenced yard`). One more request per listing, charged per listing with highlights (`home-insights`).

## `includeListingStats` (type: `boolean`):

Add how many times the listing was viewed and saved on Zillow. Read from the same request as the details. Charged per listing where the counts are delivered (`listing-stats`).

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

Listing price, in US dollars. For rentals this is the monthly rent.

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

Listing price, in US dollars. For rentals this is the monthly rent.

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

Minimum number of bedrooms.

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

Maximum number of bedrooms.

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

Minimum number of bathrooms.

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

Maximum number of bathrooms.

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

Minimum living area, in square feet.

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

Maximum living area, in square feet.

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

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

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

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

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

Minimum year built.

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

Maximum year built.

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

Maximum monthly homeowners association fee, in US dollars.

## `minHoaFee` (type: `integer`):

Minimum monthly homeowners association fee, in US dollars.

## `includeHomesWithNoHoaData` (type: `boolean`):

With an HOA fee filter: also keep homes whose HOA fee is unknown.

## `minParkingSpots` (type: `integer`):

Minimum number of parking spots. For sale and sold listings Zillow applies it. On rentals this filter needs the property page: tick Add property details (or another option that reads the property page), otherwise it is ignored on the listings of a search and the run log says so (a listing asked by id, a zpid, a listing URL or an address, always has its page read, so it is filtered anyway); the Actor then drops the rentals below (a small filter check is charged for each dropped listing).

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

Keep only these property types. Empty = all types.

## `listingTypes` (type: `array`):

For sale searches. Empty = Zillow's default (agent, owner, new construction, foreclosure, auction, coming soon). Ticking agent, owner, new construction, foreclosure, auction or coming soon narrows the search to the ticked ones; pending / under contract, pre-foreclosure, foreclosed and accepting backup offers are off by default and are added to the active listings when ticked.

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

For sale and rent: listed in the last N days. For sold homes: sold in the last N days (Zillow's own filter).

## `openHousesOnly` (type: `boolean`):

Only listings with an open house scheduled.

## `virtualTourOnly` (type: `boolean`):

Only listings with a 3D home tour.

## `priceReducedOnly` (type: `boolean`):

Only listings whose price was reduced.

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

Only homes with a garage.

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

Only homes with a pool.

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

Only homes with air conditioning.

## `hasWaterView` (type: `boolean`):

Only homes with a water view.

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

Only homes with a finished basement.

## `isSingleStory` (type: `boolean`):

Only single-story homes.

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

Only waterfront homes.

## `hasUnfinishedBasement` (type: `boolean`):

Only homes with an unfinished basement.

## `views` (type: `array`):

Only homes with one of these views. Empty = any.

## `showcaseOnly` (type: `boolean`):

Only Zillow Showcase listings (premium photos and tours).

## `onlyWithPhotos` (type: `boolean`):

Only listings that have photos.

## `ageRestricted55Plus` (type: `string`):

Include, exclude or keep only age-restricted (55+) communities.

## `onlyNonOwnerOccupied` (type: `boolean`):

Only homes Zillow marks as not occupied by their owner. This is Zillow's flag as it sends it, and Zillow sets it on almost every listing (for sale, for rent, sold, land, foreclosures, by owner, new construction), so this filter rarely drops anything. Applied by the Actor on every listing it reads: a listing it drops costs a small filter check.

## `petsAllowed` (type: `string`):

Rentals only: keep listings that accept this kind of pet.

## `inUnitLaundryOnly` (type: `boolean`):

Rentals only: keep listings with a washer / dryer in the unit.

## `furnishedOnly` (type: `boolean`):

Rentals only: keep furnished listings.

## `forRentByOwner` (type: `boolean`):

Rentals only: homes the owner rents out directly (Zillow's « for rent by owner »), no agent or manager.

## `parkingAvailable` (type: `boolean`):

Rentals only: keep listings with on-site parking.

## `elevator` (type: `boolean`):

Rentals only: buildings with an elevator.

## `hardwoodFloors` (type: `boolean`):

Rentals only: hardwood floors.

## `highSpeedInternet` (type: `boolean`):

Rentals only: high-speed internet available.

## `outdoorSpace` (type: `boolean`):

Rentals only: balcony, patio or yard.

## `utilitiesIncluded` (type: `boolean`):

Rentals only: utilities included in the rent.

## `disabledAccess` (type: `boolean`):

Rentals only: accessible to people with disabilities.

## `controlledAccess` (type: `boolean`):

Rentals only: controlled building access.

## `incomeRestricted` (type: `boolean`):

Rentals only: income-restricted housing.

## `shortTermLease` (type: `boolean`):

Rentals only: short-term lease available.

## `acceptsZillowApplications` (type: `boolean`):

Rentals only: landlord accepts applications through Zillow.

## `apartmentCommunity` (type: `boolean`):

Rentals only: apartment communities (managed buildings).

## `instantTourOnly` (type: `boolean`):

Rentals only: tours can be booked instantly.

## `rentalSpace` (type: `string`):

Rentals only: entire places, rooms for rent, or both.

## `moveInDate` (type: `string`):

Rentals only: available by this date (`2026-11-01`).

## `hideNoMoveInDate` (type: `boolean`):

Rentals only: drop listings that give no availability date.

## `schools` (type: `array`):

Only homes near these kinds of schools (Zillow's school filter). Empty = no school filter.

## `schoolsRating` (type: `integer`):

With Schools nearby: minimum GreatSchools rating (1-10).

## `includeUnratedSchools` (type: `boolean`):

With Schools nearby: also count schools with no rating.

## `latitude` (type: `string`):

Search around a point instead of a named area: latitude in decimal degrees (e.g. `47.6062`). Used with longitude and radius; overrides Location.

## `longitude` (type: `string`):

Longitude in decimal degrees (e.g. `-122.3321`).

## `radiusMiles` (type: `integer`):

Distance around the point, in miles. Listings farther than this are dropped.

## `postedAfter` (type: `string`):

Keep listings put on Zillow after this date (the listing date shown on Zillow, US time): `2026-09-01`, a full ISO date, or `7 days` / `24 hours` / `2 weeks` back from now. Sold homes: the sold date. For sale and for rent the date is on the property page: tick Add property details (or another option that reads the property page), otherwise this filter is ignored on the listings of a search and the run log says so (a listing asked by id, a zpid, a listing URL or an address, always has its page read, so it is filtered anyway).

## `postedBefore` (type: `string`):

Keep listings put on Zillow before this date (same date and formats as above). Same condition: for sale and for rent it needs the property page (Add property details or another option that reads it), otherwise it is ignored on the listings of a search and the run log says so (a listing asked by id is filtered anyway).

## `excludeKeywords` (type: `array`):

Drop the listings whose address, building name, card highlight or (with Add property details) description contains one of these words (case and accents ignored).

## `requirePhone` (type: `boolean`):

Drop listings without an agent or owner phone number. Turns on Add agent and broker contact.

## `privateSellersOnly` (type: `boolean`):

For sale searches: only listings posted by the owner (FSBO).

## `maxPriceVsZestimatePct` (type: `integer`):

Keep only listings priced at most this percentage above the Zestimate (e.g. `-10` = at least 10 % under the Zestimate). Listings without a Zestimate are dropped. For sale and sold only: not applied to rentals. Empty = no filter.

## `onlyNew` (type: `boolean`):

Skip the listings that a previous run (same **Memory key**) already delivered: they are not saved and not charged, and the property page of a listing found by a search is not opened. A listing asked by id (zpid, address, property URL, dataset) is still read again, but neither saved nor charged. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new listings**. Give each schedule / task its own key (e.g. `paris-rentals`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every listing again. Untick it afterwards.

## `trackChanges` (type: `boolean`):

With New listings only: also return listings already delivered whose price or status changed since (with `changeType`, `previousPrice`, `previousStatus`).

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

Apify Proxy or your own proxies. Keep the default: it is included in the price. The residential Apify proxy is not available in this Actor.

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

Maximum number of requests processed in parallel.

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

Most requests to the site in any 60 seconds, all of them counted: results pages, listing pages and the extra page read for a listing. A budget, not an even pace: up to this many can leave at once when the minute starts (spread them with the minimum delay below). Lower it if the site answers HTTP 429 / 403 in the log.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. Unlike the per-minute rate, this spreads the requests evenly instead of letting them go out in a burst. 0 = no gap.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed. Behind a proxy, a request the site turns away is also retried on a new proxy session up to 10 times without using up these retries.

## `requestTimeoutSecs` (type: `integer`):

Seconds before a request to Zillow is given up and retried.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "startUrls": [],
  "location": "Seattle, WA",
  "locations": [],
  "zpids": [],
  "addresses": [],
  "listingStatus": "for_sale",
  "searchQueries": [],
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "sortBy": "newest",
  "extractDetails": false,
  "includeAgentContact": false,
  "includeComparables": false,
  "extractBuildingUnits": false,
  "oneRowPerUnit": false,
  "includeClimateRisk": false,
  "includeHomeInsights": false,
  "includeListingStats": false,
  "includeHomesWithNoHoaData": true,
  "homeTypes": [],
  "listingTypes": [],
  "daysOnZillow": "any",
  "openHousesOnly": false,
  "virtualTourOnly": false,
  "priceReducedOnly": false,
  "hasGarage": false,
  "hasPool": false,
  "hasAirConditioning": false,
  "hasWaterView": false,
  "hasBasement": false,
  "isSingleStory": false,
  "isWaterfront": false,
  "hasUnfinishedBasement": false,
  "views": [],
  "showcaseOnly": false,
  "onlyWithPhotos": false,
  "ageRestricted55Plus": "include",
  "onlyNonOwnerOccupied": false,
  "petsAllowed": "any",
  "inUnitLaundryOnly": false,
  "furnishedOnly": false,
  "forRentByOwner": false,
  "parkingAvailable": false,
  "elevator": false,
  "hardwoodFloors": false,
  "highSpeedInternet": false,
  "outdoorSpace": false,
  "utilitiesIncluded": false,
  "disabledAccess": false,
  "controlledAccess": false,
  "incomeRestricted": false,
  "shortTermLease": false,
  "acceptsZillowApplications": false,
  "apartmentCommunity": false,
  "instantTourOnly": false,
  "rentalSpace": "any",
  "hideNoMoveInDate": false,
  "schools": [],
  "includeUnratedSchools": false,
  "excludeKeywords": [],
  "requirePhone": false,
  "privateSellersOnly": false,
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "trackChanges": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 8,
  "maxRequestsPerMinute": 120,
  "minRequestIntervalMs": 0,
  "maxRequestRetries": 5,
  "requestTimeoutSecs": 30,
  "debugLog": false
}
```

# 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 = {
    "location": "Seattle, WA",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/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 = {
    "location": "Seattle, WA",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/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 '{
  "location": "Seattle, WA",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/zillow-listings-scraper --silent --output-dataset

```

## MCP server setup

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