# Zillow Scraper: Homes for Sale, Rent and Sold (`automation_craft/zillow-scraper`) Actor

Scrape Zillow homes for sale, for rent and recently sold by place, ZIP code, map area or search link, no login, past the 984 home cap. Each home gives price, Zestimate, rent Zestimate, beds, baths and days on Zillow; details add price history, tax history and schools. CSV, Excel, API; pay per home.

- **URL**: https://apify.com/automation_craft/zillow-scraper.md
- **Developed by:** [Automation Craft](https://apify.com/automation_craft) (community)
- **Categories:** Real estate, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.85 / 1,000 homes

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 Scraper: Homes for Sale, Rent and Sold

**Zillow scraper** for US homes for sale, for rent and recently sold: search by place, ZIP code, map area or a pasted Zillow
search link, or look up single homes by link, zpid or street address, and get one row per home with its price, Zestimate, rent
Zestimate, beds, baths, living area, lot, home type, address, coordinates, days on Zillow, broker and photos. With **Home
details**, each row adds the full Zillow record: description, price history, tax history, schools, facts and features, HOA,
MLS id, parcel id, county, nearby homes, climate risk and every photo. With **Home insights**, it adds the Walk Score, Transit
Score and Bike Score, 10 years of Zestimate and rent Zestimate history and the comparable homes behind the Zestimate. No login,
no Zillow API key, no browser. Searches bigger than the 984 homes Zillow shows are split by price, and a coverage row per search says whether it was read to
its end.

Who uses it: real estate investors and wholesalers building deal lists (price cuts, days on Zillow, price against the
Zestimate, gross rent yield, absentee owners), agents, brokers and lenders studying a market, landlords and property managers
comparing rents, proptech, valuation and data teams that need bulk rows for their models, and analysts and journalists.

### Quick start

1. Open the **Input** tab and type a place in **Places**, for example `Austin, TX`, `78704`, `Travis County, TX`,
   `Brooklyn, NY` or `Texas`. Or paste a Zillow search link into **Zillow search links**, ZIP codes into **ZIP codes**, or a
   circle such as `30.27,-97.74,3` into **Map areas**.
2. Pick the **Listing status**: for sale, for rent, recently sold, or all three.
3. Add filters if you like: price or rent, beds, baths, home types, living area, lot size, year built, days on Zillow, keywords,
   HOA and the rest of the **Filters** group.
4. Turn on **Home details** or **Home insights** if you need the full record or the scores and value history.
5. Set **Maximum homes (whole run)** and click **Start**. Download the rows as JSON, CSV or Excel, or read them through the
   Apify API.

To look up single homes instead, put Zillow home links, zpids or full street addresses into **Homes**.

### What you get

One row per home (`type: "home"`), one free coverage row per search (`type: "search"`), free status rows for anything that could
not be delivered (`type: "status"`), and a free run summary (`type: "summary"`).

Fill rates below were measured on the Actor's own platform runs of 2026-10-27 (build 0.1.8): 1,000 Austin, TX homes for sale
from search pages (run uIdkjgAfH7K4EYfNn) and 200 Dayton, OH homes for sale with Home details (run 6vL14tHZgskJBe2zW).

| Field | What it is | Filled on (Austin, 1,000 search rows) |
|---|---|---|
| `id`, `zpid`, `buildingId`, `url` | the row's id, Zillow's property id (a string), an apartment building's id instead of a zpid, the home's Zillow link | every row |
| `listingStatus`, `homeStatus`, `statusText`, `marketingStatus` | `forSale`, `forRent`, `sold`, `pending`, `foreclosure` or `offMarket`; Zillow's own status words | every row |
| `listingType` | Zillow's listing type flags: `byAgent`, `byOwner`, `newConstruction`, `comingSoon`, `pending`, `auction`, `foreclosure`, `bankOwned`, `openHouse` | every row |
| `price`, `priceText`, `currency` | list price, the monthly rent for rentals, or the sold price for sold homes | 100 percent |
| `soldPrice`, `soldDate` | for recently sold homes, where Zillow shows them | sold homes only (no sold search in the measured runs) |
| `priceChange`, `priceChangeDate`, `priceReduction` | the latest price change, its day, and Zillow's price cut text | 51.0 percent |
| `zestimate`, `rentZestimate` | Zillow's value estimate and monthly rent estimate | 18.4 and 28.1 percent (Texas search cards rarely show a Zestimate; 62.5 and 89.0 percent on the 200 Dayton rows) |
| `taxAssessedValue` | the tax assessed value | 69.9 percent |
| `beds`, `baths` | bedrooms and bathrooms | 99.6 and 99.9 percent |
| `livingArea`, `livingAreaUnit`, `lotArea`, `lotAreaUnit` | living area in square feet; the lot in the unit Zillow gives (`sqft` or `acres`) | living area 94.7, lot 86.0 percent |
| `homeType` | `SINGLE_FAMILY`, `CONDO`, `TOWNHOUSE`, `MULTI_FAMILY`, `APARTMENT`, `MANUFACTURED`, `LOT` | 100 percent |
| `address` (`full`, `street`, `city`, `state`, `zipcode`), `isUndisclosedAddress` | the home's address and its parts | ZIP code 100 percent |
| `latitude`, `longitude` | coordinates (left out on a by owner home with the personal data switch off) | 99.9 percent |
| `daysOnZillow`, `timeOnZillowMs`, `availabilityDate` | days on Zillow, the time on Zillow in milliseconds, a rental's move in date | days on Zillow 100 percent |
| `hasPool`, `hasAirConditioning`, `instantTourAvailable` | a pool, air conditioning and an instant tour, where a rental's search card says so (yes or no) | rental cards that carry them |
| `brokerName` | the listing brokerage (business data, always delivered) | 87.1 percent |
| `mainPhotoUrl`, `photos`, `photoCount`, `has3DModel`, `hasVideo` | the main photo, the search card's photo links, a 3D tour, a video | photos 99.9 percent |
| `isFeatured`, `isShowcase`, `isZillowOwned`, `isNonOwnerOccupied`, `flexText` | Zillow's flags: a featured listing, a Showcase listing, Zillow owned, not owner occupied (absentee owner); the card's note | where Zillow sets them |
| `deal` (`pricePerSqft`, `priceToZestimatePercent`, `grossRentYieldPercent`) | computed from the row's own figures: price per square foot, price as a percent of the Zestimate, rent Zestimate times 12 over the price | where the figures exist |
| `building` | an apartment building's name, units available, lowest and highest base rent, required monthly fees, and its unit list (beds, price, room for rent) | building rows of rental searches |
| `summary` | one plain sentence about the home, for people and AI agents | every row |
| `search` (`key`, `input`, `page`, `position`) | which search, page and place delivered the row | every row |
| `details`, `detailsStatus` | the Home details block (below); `delivered`, `not_requested` or why it is missing | with Home details |
| `insights`, `insightsStatus` | the Home insights block (below) | with Home insights |
| `scrapedAt` | when the row was written | every row |

A sample row (shortened, from run 3ULINcZru7een493X, Include personal data off):

```json
{
  "type": "home",
  "zpid": "114163452",
  "url": "https://www.zillow.com/homedetails/195-Colonial-Ln-Dayton-OH-45429/114163452_zpid/",
  "listingStatus": "forSale",
  "statusText": "House for sale",
  "price": 615000,
  "priceChange": -35000,
  "priceChangeDate": "2026-10-14",
  "priceReduction": "$35,000 (Oct 14)",
  "zestimate": 596700,
  "rentZestimate": 2384,
  "taxAssessedValue": 389710,
  "beds": 3,
  "baths": 3,
  "livingArea": 3200,
  "lotArea": 1.7144,
  "lotAreaUnit": "acres",
  "homeType": "SINGLE_FAMILY",
  "address": { "full": "195 Colonial Ln, Dayton, OH 45429", "city": "Dayton", "state": "OH", "zipcode": "45429" },
  "latitude": 39.67271,
  "longitude": -84.1679,
  "daysOnZillow": 34,
  "brokerName": "Howard Hanna Real Estate Serv",
  "photoCount": 47,
  "deal": { "pricePerSqft": 192, "priceToZestimatePercent": 103.07, "grossRentYieldPercent": 4.65 },
  "summary": "3 bd, 3 ba, 3,200 sqft single family home for sale at $615,000 in Dayton, OH 45429 (Zestimate $596,700), 34 days on Zillow.",
  "detailsStatus": "delivered",
  "details": {
    "yearBuilt": 1972,
    "county": "Montgomery County",
    "parcelId": "O67037120042",
    "mlsId": "967417",
    "mlsName": "DABR MLS",
    "priceHistory": [{ "date": "2026-10-14", "event": "Price change", "price": 615000, "source": "DABR MLS" }],
    "taxHistory": [{ "year": 2025, "taxPaid": 9139.93, "assessedValue": 136400 }],
    "schools": [{ "name": "Driscoll Elementary School", "rating": 8, "grades": "2-5", "distanceMiles": 1.3 }],
    "brokerage": { "name": "Howard Hanna Real Estate Serv", "phone": "937-433-1776" },
    "listingAgent": null
  },
  "scrapedAt": "2026-10-27T02:17:06.050Z"
}
```

#### Home details (add-on)

With **Home details** on, `details` carries the home's full Zillow record:

| Field | What it is | Filled on (Dayton, 200 rows with Home details) |
|---|---|---|
| `description` | the listing description, exactly as Zillow serves it | 100 percent |
| `yearBuilt`, `county`, `countyFips`, `neighborhood` | year built, county, county FIPS code, neighbourhood | year built 100, county 100, neighbourhood 77.0 percent |
| `parcelId`, `mlsId`, `mlsName` | the parcel id, the MLS number and the MLS's name | parcel id 96.0, MLS id 97.5 percent |
| `priceHistory` | every price event: day, event, price, price per square foot, change rate, source | 99.0 percent |
| `taxHistory` | per year: tax paid, assessed value and their change rates | 94.5 percent |
| `schools` | nearby schools: name, GreatSchools rating, grades, distance in miles, link | 100 percent |
| `hoaFee`, `hoaFeeText`, `propertyTaxRate` | the HOA fee as a number and as Zillow writes it, the property tax rate | HOA fee 9.0 percent |
| `facts` | Zillow's facts and features (heating, cooling, parking, appliances, construction and many more) | 100 percent |
| `nearbyHomes` | nearby homes with zpid, price, beds, baths, area, status, address and coordinates | 100 percent |
| `photos`, `photoCount`, `virtualTourUrl`, `hasPublicVideo` | every photo at its largest size, a virtual tour link, a video | photos 100 percent |
| `climateRisk` | First Street's flood, fire, heat, wind and air quality risk as Zillow serves it | 95.5 percent |
| `brokerage` (`name`, `phone`), `buyerBrokerage` | the listing brokerage and its phone, the buyer's brokerage (business data, always delivered) | brokerage phone 98.0 percent |
| `datePosted`, `timeOnZillow`, `homeStatus`, `price`, `lastSoldPrice`, `zestimate`, `rentZestimate`, `zestimateLowPercent`, `zestimateHighPercent` | the record's own dates, status, prices and Zestimate range | where Zillow has them |
| `pageViews`, `saves`, `viewsStatus` | how many times the home's Zillow page was viewed and how many people saved it, as Zillow counts them; read last for each home and skipped (`viewsStatus` says so) when a slow run needs its time for the paid reads | page views and saves 100 percent |
| `openHouseSchedule`, `foreclosure`, `downPaymentAssistance`, `tourViewCount` | open house times, foreclosure facts, down payment assistance, tour views | where Zillow has them |
| `listingAgent`, `coAgent`, `buyerAgent`, `listingContactPhone`, `listedBy` | persons: only with **Include personal data** (below) | with the switch on |

For an apartment building row, Home details reads the building's own page instead: `buildingName`, address, `phone` (the
building's), `amenities`, `floorPlans` (beds, baths, square feet, prices, deposits and fees, pets) and every unit in `units`
(unit number, beds, baths, square feet, rent, available from).

#### Home insights (add-on)

With **Home insights** on, `insights` carries `walkScore`, `transitScore` and `bikeScore` (score and description),
`zestimateHistory` and `rentZestimateHistory` (monthly points over 10 years) and `zestimateComparables` (the comparable homes
behind the Zestimate, with price, beds, baths, area, address and link). `insightsStatus` says `delivered` when at least one of
them was read. On a run of 60 homes (build 0.1.8) in ZIP 78752 (run jSJ0Bc26eQaThVakU): Walk Score 100, Transit Score
100, Bike Score 53.3, Zestimate history 81.7, rent Zestimate history 100 and comparables 81.7 percent.

#### Buildings, units and new construction communities

A rental search lists apartment buildings as one row each, with `building`. With **One row per apartment unit**
(`expandBuildingUnits`), each unit type of a search card becomes its own Home row with a `unit` field instead (one row per beds
count, the same row in every search of the run); a building link in **Homes** gives one row per unit of the building's page, each
with its own status, link, price and sold date (a building can list rentals, homes for sale and sold homes together). A new
construction community link in
**Homes** gives one Home row per builder plan and move in ready home, each with a `community` field (name, plan name,
construction type, move in ready, year built).

#### The coverage row

Each search gets one free row (`type: "search"`) with Zillow's total for it (`totalResults`), the homes met (`homesSeen`; for
rentals also `listingsSeen`, an estimate in Zillow's own unit: a building card counts its available units; Zillow's rental total
need not match it exactly, so a rental search is complete when every page of it was read to the list's end) and
delivered (`homesDelivered`), repeats (`duplicates`), homes left out by reason (`skipped`), pages read and failed, price bands,
whether the search was read to its end (`complete`) and why it stopped (`stoppedBy`), with a plain `note`. A place Zillow does
not know, or a text several Zillow places match (listed in `candidates`), is a free row too.

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

You pay per event, with Apify's store discounts by plan:

| Event | Free plan | Bronze | Silver | Gold |
|---|---|---|---|---|
| Home (one home row) | $1.19 per 1,000 | $1.08 per 1,000 | $0.98 per 1,000 | $0.85 per 1,000 |
| Home details (add-on, per home whose full record was read) | $1.40 per 1,000 | $1.28 per 1,000 | $1.16 per 1,000 | $1.00 per 1,000 |
| Home insights (add-on, per home with at least one part read) | $1.68 per 1,000 | $1.54 per 1,000 | $1.39 per 1,000 | $1.20 per 1,000 |
| Actor start (once per run, charged on every run) | $0.0075 | $0.0075 | $0.0075 | $0.0075 |

Platinum and Diamond plans pay the Gold price.

The Store pricing card shows these same prices per 1,000 events: "$0.85 / 1,000" on the Home row means one home costs USD 0.00085.

- Never billed: homes outside your search area, status or filters (paid placements included), a home met twice in one run,
  places, addresses and homes Zillow does not have, Home details or Home insights that could not be read, homes a minimum school
  rating leaves out, coverage rows, status rows and the summary. The Actor start event is charged on every run, whatever it
  delivers: an input with nothing usable delivers nothing, and only the run's start fee is charged.
- The run obeys the maximum cost you set for it: a home whose events the limit cannot pay is not delivered, and neither is any
  home after it.
- Example on the Gold plan: 1,000 homes from one search cost $0.0075 (start) + $0.85 (1,000 homes) = about $0.86. With Home
  details, add $1.00: about $1.86. With Home insights as well, add $1.20: about $3.06.
- The same runs on the Free plan: $0.0075 + $1.19 = about $1.20; with Home details about $2.60; with both add-ons about $4.28.
- Example: 200 homes with Home details on the Gold plan cost $0.0075 + $0.17 + $0.20 = about $0.38.

### Input

| Setting | What it does |
|---|---|
| `locations` | Places as Zillow names them: a city (`Austin, TX`), ZIP code (`78704`), county (`Travis County, TX`), neighbourhood (`Mueller, Austin, TX`), borough (`Brooklyn, NY`) or state (`Texas`). A place is searched only when exactly one Zillow place matches the text; otherwise a free row lists the candidates (a state that shares its name with a city is written by its code, `NY`, or the city as `New York, NY`). Up to 1,000 per list. |
| `searchUrls` | Zillow search links, with their own listing status, filters, drawn area and sort. A filter you also set replaces only that filter of the link. A link's page number is where reading starts; a search larger than Zillow lists from there is read whole, by price bands. |
| `zipCodes` | Five digit ZIP codes, each searched on its own. |
| `mapAreas` | A circle `latitude,longitude,radius in miles` (homes outside the circle are left out free) or a box `south,west,north,east`. |
| `homes` | Zillow home links, zpids, full street addresses, apartment building links (`/b/...`, `/apartments/...`) or new construction community links. An address is delivered only when exactly one Zillow home matches it and the record carries the same house number and street; a miss is a free row. Search filters do not apply to these homes. |
| `communityHomeTypes` | For new construction community links in `homes`: `plan` (floor plans), `moveInReady` (move in ready homes), `lot` (lots, when Zillow lists them with their own zpid). Empty means all. |
| `datasetId` | An Apify dataset whose rows carry a `zpid` or a Zillow home link (an earlier run of this Actor, for example): every home in it is looked up, a page of 1,000 rows at a time. Datasets of up to 200,000 rows. |
| `listingStatus` | `forSale` (default), `forRent`, `sold` or `all` (each search read three times). |
| `saleTypes`, `includePending`, `includeAcceptingBackupOffers`, `includeForeclosed`, `distressedOnly` | For sale: only `byAgent`, `byOwner`, `newConstruction`, `foreclosure`, `auction` or `comingSoon`; also pending and under contract, homes accepting backup offers, foreclosed (bank owned); or distressed only (foreclosures, auctions and foreclosed, not combined with `saleTypes`). |
| `soldWithin` | Recently sold: sold within 1, 7, 14, 30 or 90 days, or 6, 12, 24 or 36 months. |
| `minPrice`, `maxPrice`, `minBeds`, `maxBeds`, `minBaths`, `maxBaths`, `minSqft`, `maxSqft`, `minLotSize`, `maxLotSize`, `minYearBuilt`, `maxYearBuilt` | Price (the monthly rent for rentals), bedrooms, bathrooms, living area and lot size in square feet, year built. `maxBaths` is checked on each row. |
| `homeTypes` | `house`, `townhouse`, `condo`, `multiFamily`, `apartment`, `manufactured`, `lotLand`. An apartment building card carries no type of its own: it is left out when neither `apartment` nor `condo` is chosen. |
| `maxDaysOnZillow`, `minDaysOnZillow` | Listed on Zillow within a time; or on Zillow for at least N days (stale listings, checked on each row). |
| `keywords` | Words Zillow looks for in the listing (`pool`, `guest house`). |
| `maxHoa`, `includeHomesWithNoHoaData` | The highest monthly HOA fee; keep homes whose HOA fee is not known. |
| `minParkingSpots`, `mustHaveGarage`, `mustHavePool`, `mustHaveAirConditioning`, `waterfrontOnly`, `singleStoryOnly`, `basement`, `views`, `seniorCommunity` | Parking, garage, pool, air conditioning, waterfront, single story, a finished or unfinished basement, city, mountain, park or water views, and 55+ communities (include, leave out or only). |
| `has3DTour`, `openHouseOnly`, `priceReducedOnly`, `showcaseOnly`, `withPhotosOnly` | Only homes with a 3D tour, an open house, a price cut, a Zillow Showcase listing, photos. |
| `minSchoolRating`, `includeUnratedSchools` | Only homes with at least one nearby school rated this or higher (1 to 10), read from the Home details record (needs `includeDetails`); keep homes whose schools carry no rating. |
| `maxPriceToZestimatePercent`, `minGrossRentYieldPercent`, `nonOwnerOccupiedOnly` | Deals and investors, checked on each row: price at most this percent of the Zestimate, gross rent yield at least this percent, absentee owners only (Zillow's not owner occupied flag). A home without the figure is left out free. |
| `sort` | `relevance` (Zillow default), `newest`, `priceLowToHigh`, `priceHighToLow`, `bedrooms`, `bathrooms`, `squareFeet`, `lotSize`. |
| `petsAllowed`, `largeDogsAllowed`, `smallDogsAllowed`, `catsAllowed`, `noPets`, `inUnitLaundry`, `furnished`, `onSiteParking`, `elevator`, `highSpeedInternet`, `outdoorSpace`, `utilitiesIncluded`, `hardwoodFloors`, `disabledAccess`, `incomeRestricted`, `acceptsZillowApplications`, `shortTermLease`, `controlledAccess`, `dishwasher`, `fitnessCenter`, `rentByOwner`, `instantTour`, `apartmentCommunity`, `rentalType`, `moveInDate` | Rentals: pet policies, amenities, for rent by owner, instant tour (a tour booked through Zillow), apartment communities only, entire place, rooms for rent or both, and a move in date. |
| `maxItems`, `maxItemsPerSearch`, `maxPagesPerSearch`, `splitPastCap` | Caps for the run and per search, result pages per search (41 homes a page, 1 to 24), and the split past Zillow's per search cap (on by default). |
| `includeDetails`, `includeInsights`, `includePersonalData` | The Home details and Home insights add-ons (off by default) and the personal data switch (off by default). |
| `expandBuildingUnits`, `outputFormat`, `includeRawData` | One row per apartment unit (a building's raw copy on its first unit row only); `nested` (default) or `flat` rows with columns such as `address.city` for spreadsheets; Zillow's own search row as `raw` (Zillow's record, and a building's or a community's raw data, only with **Include personal data** on, because they name the agents and contacts). |
| `maxConcurrency`, `proxyConfiguration` | Parallel Zillow connections (1 to 4, default 3), each keeping a polite pace; Apify Proxy datacenter by default (included in the price), or your own proxy links. |

#### Every home checked before it is billed

Every filter is sent to Zillow and checked again on each home whose row can show it: price or rent, beds, baths, living area,
home type, the place and the search area, the listing status. A home that fails, a paid placement outside the search included,
is left out free and counted on its search's coverage row. A home met twice in one run is delivered and billed once.

#### Searches past Zillow's 984 home cap

Zillow shows at most 24 pages of 41 homes (984) for one search. With `splitPastCap` on (the default), a bigger search is split
into price bands that each fit, and the walk ends only when the distinct homes met reach the total Zillow states. On 2026-10-27 a
run read 1,000 Austin homes for sale in 111 seconds across 14 price bands (run uIdkjgAfH7K4EYfNn); 200 homes with Home
details took 1073 seconds. When more homes share one price than one search shows, the coverage row says the search could not be read to
its end.

#### Personal data

Brokerage names and phones, building phones and builder data are business data and always delivered. The listing agent, co agent
and buyer's agent (name, phone, e-mail, licence), the listing contact (`listingContactPhone`, and `listedBy`, the person a listing
names as its contact: a landlord or an owner selling by owner) and the agents named on price history events (`buyerAgent`,
`sellerAgent`) are delivered only with **Include personal data** (`includePersonalData`) and Home details on; with it off those
fields are empty. A home its owner sells or lets (Zillow's by owner listings, and the homes of a "for rent by owner" search; an apartment building
card there is a managed building, business data, and stays whole) is a
private person's home: with the switch off its `address.street`, `latitude`, `longitude` and the link naming the street are left
out (`url` becomes the plain zpid link, `personalDataHidden` is true, Zillow's raw copy is left out), and so are the positions,
streets and parcel ids of the homes nested in that row (nearby homes, comparables), its building name, unit number, parcel and listing
ids (and a foreclosure's recorded documents), and every link but Zillow's photos and the plain zpid link (a tour site or a map can
name the street); its summary is rebuilt from the fields that stay, and a status text that names a building (on a building or unit row, or a home in a named building) is rebuilt from the listing status; the town, state and ZIP code stay. A by owner home nested in any other row (a nearby home, a comparable, a building's unit)
loses its street and position the same way. Zillow marks homes for sale by owner on its search cards; a rental let by its owner is
recognised through the "For rent by owner" filter or its Home details record, not on a plain rental search card. Descriptions, photo captions, fact texts, Zillow's card note and every other text are delivered exactly as Zillow serves them, whether the switch is on or off.
You are responsible for using personal data lawfully (GDPR, CCPA and similar laws).

#### AI agents and MCP

AI agents can call this Actor through Apify's MCP server: the inputs are plain text, numbers and switches (places, ZIP codes,
links, prices), and every home row carries a one sentence `summary` an agent can read as it is.

#### When Zillow fails

When Zillow refuses or does not answer after retries, the run still ends normally and its status message says how many calls
Zillow failed, which search pages, homes or Home details records could not be read, that nothing was charged for them, and to
try again later.

### API examples

Run it and get the rows in one call (replace `YOUR_TOKEN`):

```bash
curl -X POST "https://api.apify.com/v2/acts/automation_craft~zillow-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"zipCodes": ["78704"], "listingStatus": "forSale", "maxPrice": 600000, "minBeds": 3, "maxItems": 200}'
```

Node.js:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('automation_craft/zillow-scraper').call({ locations: ['Dayton, OH'], includeDetails: true, maxItems: 100 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((x) => x.type === 'home'));
```

Python:

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_TOKEN")
run = client.actor("automation_craft/zillow-scraper").call(run_input={"locations": ["Phoenix, AZ"], "listingStatus": "sold", "soldWithin": "90", "maxItems": 500})
homes = [x for x in client.dataset(run["defaultDatasetId"]).iterate_items() if x["type"] == "home"]
```

### What this Actor does not do

- **No monitoring between runs.** By design it keeps no memory from one run to the next, so it does not deliver only new or
  changed homes on later runs: each run delivers what the search shows at that moment.
- **No pre foreclosures.** Zillow shows them only to signed in users: logged out, its own pre foreclosure switch changes neither
  the total nor the rows, so `distressedOnly` covers foreclosures, auctions and foreclosed homes only.
- **No year built, largest price cut or "recently changed" sort.** Zillow's search page offers no year built or price cut order,
  and its recently changed order falls back to the default order. Year built is a filter (`minYearBuilt`, `maxYearBuilt`).
- **No search from a school.** Zillow's own place search answers no school for visitors without a login; search the school's town,
  ZIP code or a map area instead, and use `minSchoolRating` (with Home details) to keep homes near well rated schools.
- **A run can stop early to protect its margin.** Work that earns nothing is capped (the unpaid work allowance: USD 0.001 plus 30
  percent of what the run's events earn). A very strict code filter (a high `minSchoolRating`) or very slow answers can end a run
  with `stoppedBy: "work_allowance"` on the coverage row and the summary; nothing is charged for homes not delivered.
- **No "hide rentals with no move in date" filter.** Zillow echoes its own switch but ignores it for visitors without a login
  (the totals stay the same with and without it), and search cards rarely carry the move in date to check it on.
- **No school type filter (public, private, charter).** Zillow ignores its own school filters for visitors without a login, and
  its school entries carry no type. The school rating is checked on the Home details record instead (`minSchoolRating`).
- **No home insights panel and no affordability estimate.** None of the data a Zillow home page loads for a visitor carries them.
- **No agent e-mails from other sources.** It delivers only Zillow's own agent e-mail field (behind the personal data switch),
  which was empty on 8 of 8 homes read in the build's tests, and looks nothing up on other sites.
- **No agent profiles or agent directory.** By design this Actor covers homes; agents named on a listing come with Home details
  and the personal data switch.
- **No cap rate, cash flow, motivated seller score or market report.** It delivers only what Zillow serves plus three figures
  computed from the row's own values (`pricePerSqft`, `priceToZestimatePercent`, `grossRentYieldPercent`); page views and saves
  come with Home details.
- **No map marker mode.** It reads every list page and splits by price past the cap instead.
- **No exact order past 984 homes for a sort other than price.** Zillow lists at most 984 homes of one search, so with `newest`,
  `bedrooms`, `bathrooms`, `squareFeet` or `lotSize` the first 984 homes come in that order and the rest come by price band, each
  band in that order (the coverage row's `orderNote` says so). Price sorts keep their order across bands.
- **No sold price where Zillow shows none.** In states that do not disclose sale prices (Texas among them) Zillow's sold rows carry
  no price, so `soldPrice` stays empty there.
- **No Home details or Home insights on the unit rows of a search.** With `expandBuildingUnits`, unit rows from a search carry
  neither add-on (`detailsStatus` says `not_available_for_unit_rows`); a building link in **Homes** carries the building's details
  on one unit row only (`carriesBuildingDetails`), billed once per building and run, a restarted run included. Home insights
  need a zpid, so building rows carry none.
- **No login and no captcha solving.** It reads only what Zillow shows any visitor.

### FAQ

#### Is it legal to scrape Zillow?

This Actor reads only pages and data Zillow shows to any visitor without a login, and it never solves a captcha. You are
responsible for using the data lawfully, including Zillow's terms and the privacy laws that apply to any personal data.

#### Does Zillow have a public API I can use instead?

This Actor needs no Zillow API key or account: it reads what Zillow shows any visitor and works as a Zillow API. Call it through
the Apify API with places, ZIP codes, map areas, search links, zpids or addresses and read the rows back as JSON.

#### Can I export Zillow listings to Excel or CSV?

Yes. Every run's rows download as CSV, Excel or JSON from the run's dataset; with **Output format** set to `flat`, nested fields
become their own columns (`address.city`, `deal.pricePerSqft`) for spreadsheets.

#### How do I get recently sold homes from Zillow?

Set **Listing status** to `sold` and pick **Recently sold: sold within** (1 day to 36 months); each row carries `soldPrice` and
`soldDate` where Zillow shows them. In states that do not disclose sale prices, such as Texas, Zillow's sold rows carry no price.

#### Can I get Zestimates in bulk?

Yes: every Home row carries `zestimate` and `rentZestimate` where Zillow shows them, Home details adds the record's Zestimate and
its range, and Home insights adds 10 years of monthly Zestimate and rent Zestimate history and the comparable homes behind it.

#### Why does this Actor run with limited permissions?

Least privilege: it reads and writes only its own run's dataset and key-value store, opens no named store, and reads another
dataset only when you give its id in `datasetId`. Limited permissions keep the rest of your Apify data out of its reach.

### Changelog

- 0.1.10 (2026-10-28): fixes shared with the Zillow Property Details Scraper: with the personal data switch off, a by owner
  home keeps its texts as Zillow serves them (only the street, position, ids and links go); an apartment building with nothing
  listed is a free row of its own; more address forms read (ZIP+4, a country at the end, Queens and fraction house numbers);
  zpids with leading zeros; Zillow's "no home" answers told apart from no answer; mortgage rates and photo captions in Home details.
- 0.1 (2026-10-27): first release: Zillow homes for sale, for rent and recently sold by place, ZIP code, map area or search link,
  and homes by link, zpid, address, building link, community link or dataset; every filter checked on each row; searches split by
  price past the 984 home cap with a coverage row; Home details and Home insights add-ons; personal data behind its switch, texts
  as Zillow serves them.

### More data tools by Automation Craft

- [SeLoger Scraper: Listings, Prices and Agencies](https://apify.com/automation_craft/seloger-scraper)
- [Bien'ici Scraper: France Real Estate Ads & DPE](https://apify.com/automation_craft/bienici-scraper)
- [Immowelt Scraper: Rents, Prices and Energy Data](https://apify.com/automation_craft/immowelt-scraper)
- [PAP Scraper: pap.fr Real Estate Ads & Phones](https://apify.com/automation_craft/pap-scraper)
- [FINN Eiendom Scraper: Norway Homes and Rentals](https://apify.com/automation_craft/finn-eiendom-scraper)
- [Airbnb Scraper: Airbnb Data, Prices, Calendar](https://apify.com/automation_craft/airbnb-scraper)
- [US Building Permits Scraper - 38 City Sources](https://apify.com/automation_craft/us-building-permits-scraper)
- [UK EPC Register Scraper - Energy Certificates](https://apify.com/automation_craft/uk-energy-certificate-scraper)
- [Kijiji Scraper: Listings, Cars, Rentals & Prices](https://apify.com/automation_craft/kijiji-scraper)
- [Craigslist Scraper: Listings, Prices & Alerts](https://apify.com/automation_craft/craigslist-scraper)
- [Facebook Marketplace Scraper with Sold Tracker](https://apify.com/automation_craft/facebook-marketplace-scraper)

# Changelog

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

# Actor input Schema

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

Places as Zillow names them, one per line, for example "Austin, TX", "78704", "Travis County, TX", "Mueller, Austin, TX", "Brooklyn, NY" or "Texas". A place is searched only when exactly one Zillow place matches the text; otherwise a free row lists the matching places to pick from.

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

Links copied from a Zillow search page, for example https://www.zillow.com/austin-tx/ or a link with your filters, map area and sort. The link keeps its own listing status, filters and drawn area; a filter you also set below replaces only that filter of the link.

## `zipCodes` (type: `array`):

Five digit US ZIP codes, one per line, each searched on its own (for example 78704).

## `mapAreas` (type: `array`):

Areas on the map, one per line: a circle as "latitude,longitude,radius in miles" (for example "30.27,-97.74,3") or a box as "south,west,north,east". Homes outside the circle are left out free.

## `homes` (type: `array`):

Zillow home links (https://www.zillow.com/homedetails/.../12345678_zpid/), zpids (12345678), full street addresses ("1704 Shelbourne Dr, Austin, TX 78752"), apartment building links (/b/... or /apartments/...) or new construction community links (/community/.../12345678_zpid/: one row per plan and move in ready home). An address is delivered only when exactly one Zillow home matches it and the record carries the same house number and street; a miss is a free row. Search filters do not apply to these homes.

## `datasetId` (type: `string`):

The id of an Apify dataset whose rows carry a "zpid" or a Zillow home link (for example an earlier run of this Actor). Every home in it is looked up like the homes above. At most 200,000 rows.

## `communityHomeTypes` (type: `array`):

For new construction community links in "Homes" only: the kinds of homes delivered. Empty means all.

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

The listing status of every place, ZIP code and map area search. Search links keep their own. Default: for sale.

## `saleTypes` (type: `array`):

Only these for sale listing types (Zillow shows all of them by default). For example only "byOwner" for homes for sale by owner, or only "newConstruction".

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

Also deliver homes that are pending or under contract.

## `includeAcceptingBackupOffers` (type: `boolean`):

Also deliver homes under contract that accept backup offers.

## `includeForeclosed` (type: `boolean`):

Also deliver foreclosed, bank owned homes not on the market.

## `distressedOnly` (type: `boolean`):

Only foreclosures, auctions and foreclosed (bank owned) homes. Cannot be combined with "For sale: listing types". Zillow shows pre foreclosures only to signed in users, so they are not included.

## `soldWithin` (type: `string`):

For recently sold searches: homes sold within this time.

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

The lowest price, in US dollars. For rentals the monthly rent.

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

The highest price, in US dollars. For rentals the monthly rent.

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

At least this many bedrooms (0 for studios and up).

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

At most this many bedrooms.

## `minBaths` (type: `number`):

At least this many bathrooms (1, 1.5, 2, 3 or 4).

## `maxBaths` (type: `number`):

At most this many bathrooms. Checked on each row; homes without a bathroom count are left out free.

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

Only these home types (all by default).

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

At least this living area in square feet.

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

At most this living area in square feet.

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

At least this lot size in square feet (one acre is 43,560).

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

At most this lot size in square feet.

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

Only homes built in this year or later.

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

Only homes built in this year or earlier.

## `maxDaysOnZillow` (type: `string`):

For sale and rental searches: only homes listed on Zillow within this time.

## `minDaysOnZillow` (type: `integer`):

Only homes on Zillow for at least this many days (stale listings). Checked on each row; homes without a days on Zillow figure are left out free.

## `keywords` (type: `string`):

Words Zillow looks for in the listing, for example "pool" or "guest house".

## `maxHoa` (type: `integer`):

At most this monthly HOA fee.

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

With a maximum HOA fee set: keep homes whose HOA fee is not known (Zillow keeps them by default).

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

At least this many parking spots.

## `mustHaveGarage` (type: `boolean`):

Only homes with a garage.

## `mustHavePool` (type: `boolean`):

Only homes with a pool.

## `mustHaveAirConditioning` (type: `boolean`):

Only homes with air conditioning.

## `waterfrontOnly` (type: `boolean`):

Only waterfront homes.

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

Only single story homes.

## `basement` (type: `string`):

Only homes with a finished, or an unfinished, basement.

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

Only homes with these views.

## `seniorCommunity` (type: `string`):

Include, leave out or only show homes in 55+ communities (included by default).

## `has3DTour` (type: `boolean`):

Only homes with a 3D tour.

## `openHouseOnly` (type: `boolean`):

Only homes with an open house.

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

Only homes whose price was reduced.

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

Only Zillow Showcase listings.

## `withPhotosOnly` (type: `boolean`):

Only homes with photos.

## `minSchoolRating` (type: `integer`):

Only homes with at least one nearby school rated this or higher (GreatSchools rating from the home's Zillow record). Needs the Home details add-on; a home whose schools are all lower is left out, and its Home details are not charged.

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

With a minimum school rating: also keep homes whose nearby schools carry no rating at all.

## `maxPriceToZestimatePercent` (type: `number`):

Deals: only homes whose price is at most this percent of their Zestimate (for example 95). Checked on each row; homes without a Zestimate are left out free.

## `minGrossRentYieldPercent` (type: `number`):

Investors: only homes whose rent Zestimate times 12, divided by the price, is at least this percent. Checked on each row; homes without a rent Zestimate are left out free.

## `nonOwnerOccupiedOnly` (type: `boolean`):

Investors: only homes Zillow marks as not owner occupied. Checked on each row; homes without the mark are left out free.

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

The order Zillow lists the homes in. With "maxItemsPerSearch" it decides which homes come first.

## `petsAllowed` (type: `boolean`):

Only rentals that allow pets.

## `largeDogsAllowed` (type: `boolean`):

Only rentals that allow large dogs.

## `smallDogsAllowed` (type: `boolean`):

Only rentals that allow small dogs.

## `catsAllowed` (type: `boolean`):

Only rentals that allow cats.

## `noPets` (type: `boolean`):

Only rentals that allow no pets.

## `inUnitLaundry` (type: `boolean`):

Only rentals with laundry in the unit.

## `furnished` (type: `boolean`):

Only furnished rentals.

## `onSiteParking` (type: `boolean`):

Only rentals with parking.

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

Only rentals with an elevator.

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

Only rentals with high speed internet.

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

Only rentals with outdoor space.

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

Only rentals with utilities included.

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

Only rentals with hardwood floors.

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

Only rentals with disabled access.

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

Only income restricted rentals.

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

Only rentals that accept applications on Zillow.

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

Only rentals with a short term lease.

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

Only rentals with controlled access.

## `dishwasher` (type: `boolean`):

Only rentals with a dishwasher.

## `fitnessCenter` (type: `boolean`):

Only rentals with a fitness center.

## `rentByOwner` (type: `boolean`):

Only rentals listed by their owner.

## `instantTour` (type: `boolean`):

Only rentals with an instant tour (a tour booked through Zillow).

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

Only apartment community buildings.

## `rentalType` (type: `string`):

Entire places (Zillow's default), rooms for rent, or both.

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

Only rentals available by this date (YYYY-MM-DD).

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

The run stops after delivering this many homes. Leave empty for no cap.

## `maxItemsPerSearch` (type: `integer`):

Each search, place, ZIP code or map area stops after this many homes, in the sort order chosen.

## `maxPagesPerSearch` (type: `integer`):

Read at most this many result pages of 41 homes per search (1 to 24). With this set, searches are not split by price.

## `splitPastCap` (type: `boolean`):

Zillow shows at most 984 homes of one search. On (default), a bigger search is split by price into bands that each fit, so every home is read; off, each search stops at 984 homes.

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

Read each home's full Zillow record: price history, tax history, schools, facts and features, HOA, description, MLS id, brokerage, open houses, nearby homes and every photo. Billed as one Home details event per home whose record was read.

## `includeInsights` (type: `boolean`):

Read each home's Walk Score, Transit Score and Bike Score, its Zestimate history and rent Zestimate history (monthly, 10 years) and the comparable homes behind its Zestimate. Billed as one Home insights event per home with at least one of them read.

## `includePersonalData` (type: `boolean`):

Off by default. On, the Home details add-on also delivers the listing agent, co agent and buyer's agent (name, phone, e-mail, licence), the person a listing names as its contact (a landlord or an owner selling by owner) and the agents named on price history events; and for a home its owner sells or lets (by owner), its street, exact map position, parcel id and the links naming its street or position, for that home and for by owner homes nested in other rows (off, the town, state and ZIP code stay; a rental let by its owner is recognised through "For rent by owner" or Home details). You are responsible for using personal data lawfully (GDPR, CCPA and similar laws). Brokerage names and phones are always delivered.

## `expandBuildingUnits` (type: `boolean`):

For apartment buildings on rental searches: one Home row per unit type the building lists (beds and price), instead of one row for the building with a units list. Each unit row is a Home.

## `outputFormat` (type: `string`):

Nested JSON (default) or flat rows whose nested fields become columns such as "address.city".

## `includeRawData` (type: `boolean`):

Add Zillow's own search row to each row as "raw". Zillow's record (and a building's or a community's raw data) is added only with "Include personal data" on, because it names the agents and contacts.

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

How many Zillow connections the run uses at once (1 to 4, default 3). Each connection keeps a polite pace.

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

Default: Apify Proxy datacenter, screened for addresses Zillow refuses. Apify residential is used for search pages only. Or your own proxy links, used for every request.

## Actor input object example

```json
{
  "locations": [
    "Austin, TX"
  ],
  "listingStatus": "forSale",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `items` (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 = {
    "locations": [
        "Austin, TX"
    ],
    "listingStatus": "forSale",
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation_craft/zillow-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"],
    "listingStatus": "forSale",
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("automation_craft/zillow-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"
  ],
  "listingStatus": "forSale",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call automation_craft/zillow-scraper --silent --output-dataset

```

## MCP server setup

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