# Zillow Detail Scraper (`crawl_craft/zillow-detail-scraper`) Actor

Checking Zillow homes one tab at a time slows every deal. Get full property details from links, addresses or zpids: price, Zestimate, rent estimate, price and tax history, schools, comps, agents, plus cap rate and cash-on-cash return. No login.

- **URL**: https://apify.com/crawl_craft/zillow-detail-scraper.md
- **Developed by:** [Crawl Craft](https://apify.com/crawl_craft) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Detail Scraper?

Zillow Detail Scraper is an Apify Actor that turns Zillow links, plain addresses and zpids into one structured row per property. Each row holds the price, Zestimate, rent estimate, history, schools, comparable homes, agent details and rental investment figures. No Zillow account and no API key are needed.

- 📋 **Bulk input.** Paste home links, building links, addresses and zpids in one list, and repeated identical inputs are merged. Anyone who needs a Zillow bulk property scraper can start with a long list.
- ⚡ **Live results.** Each property is saved the moment it is ready, so results appear while the run is still going, and inputs that fail are saved as rows in the Failed inputs table.
- 🗂️ **Section tables.** Price history, tax history, schools, comparable homes, nearby homes, Zestimate history, building units and floor plans each get a table of their own. Each section table repeats the property ID, so the Zillow data extractor output can be joined in spreadsheets and databases.
- 💰 **Investor figures.** PITI, NOI, cap rate, cash flow, cash-on-cash return, DSCR and a 1% rule check come with assumptions you can change.
- 🔔 **Change monitoring.** Schedule runs and get events such as price cut, went pending, sold or back on market.

Click **Try for free**, paste a link, an address or a zpid, and press **Start**.

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

Every row can carry the Zillow real estate data listed below, and you can download the dataset as JSON, CSV or Excel from the Storage tab. Fields that Zillow does not show for a property stay empty, and a dash in the Example column means no example is shown for that field. Agent names, phone numbers, license numbers, profile links, photos and IDs, plus the broker phone, are left out of the examples on purpose.

Because the names match the dataset schema, a Zillow property data scraper workflow can map them to columns without renaming.

| Field | Description | Example |
|---|---|---|
| `recordType` | Record kind: `home` or `building`. | `home` |
| `zpid` | Zillow property ID. | `11026031` |
| `url` | Zillow page link. | `https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/11026031_z...` |
| `status` | Listing status. | `forSale` |
| `statusRaw` | Status in Zillow's own wording. | `FOR_SALE` |
| `isFsbo` | Whether the home is for sale by owner. | `false` |
| `isForeclosure` | Whether the listing is a foreclosure. | `false` |
| `isBankOwned` | Whether the home is bank owned. | `false` |
| `isPreforeclosure` | Whether the home is in preforeclosure. | `false` |
| `isAuction` | Whether the home is going to auction. | `false` |
| `isNewConstruction` | Whether the home is new construction. | `false` |
| `isComingSoon` | Whether the listing is marked coming soon. | `false` |
| `hasOpenHouse` | Whether an open house is listed. | `false` |
| `contingentType` | Contingency type when the listing is contingent. | - |
| `isZillowOwned` | Whether Zillow owns the home. | `false` |
| `streetAddress` | Street address. | `17 Zelma Dr` |
| `city` | City. | `Greenville` |
| `state` | State. | `SC` |
| `zipcode` | Zipcode. | `29617` |
| `county` | County. | `Greenville County` |
| `countyFips` | County FIPS code. | `45045` |
| `neighborhood` | Neighborhood. | - |
| `subdivision` | Subdivision. | `Oakland Heights` |
| `latitude` | Latitude. | `34.91575` |
| `longitude` | Longitude. | `-82.44426` |
| `parcelId` | Parcel ID. | `0429000101400` |
| `timeZone` | Time zone of the property. | `America/New_York` |
| `price` | Price. | `487500` |
| `currency` | Currency of the price. | `USD` |
| `pricePerSqft` | Price per square foot. | `189` |
| `zestimate` | Zestimate. | `479000` |
| `zestimateLow` | Lower end of the Zestimate range. | `455050` |
| `zestimateHigh` | Upper end of the Zestimate range. | `502950` |
| `rentZestimate` | Rent estimate per month. | `2699` |
| `priceVsZestimatePct` | Price compared with the Zestimate, in percent. | `1.77` |
| `taxAssessedValue` | Tax assessed value. | `491870` |
| `annualTax` | Yearly property tax. | `2974` |
| `propertyTaxRatePct` | Property tax rate in percent. | `0.51` |
| `monthlyHoa` | Monthly HOA fee. | - |
| `annualInsurance` | Yearly insurance estimate. | - |
| `zillowMonthlyCostEstimate` | Estimated total monthly cost of owning the home. | `3498` |
| `mortgageRate30yr` | 30-year mortgage rate in percent. | `7.442` |
| `mortgageRateSource` | Where the mortgage rate came from. | `zillow-live` |
| `lastSoldPrice` | Last sold price. | `415000` |
| `lastSoldDate` | Last sold date. | `2023-07-10` |
| `homeType` | Home type. | `SINGLE_FAMILY` |
| `propertySubType` | Property sub types. | `["Single Family Residence","Residential"]` |
| `bedrooms` | Bedrooms. | `4` |
| `bathrooms` | Bathrooms. | `3` |
| `bathroomsFull` | Full bathrooms. | `3` |
| `bathroomsHalf` | Half bathrooms. | `0` |
| `livingArea` | Living area. | `2582` |
| `livingAreaUnits` | Unit of the living area. | `sqft` |
| `lotSizeSqft` | Lot size in square feet. | `21780` |
| `lotSizeAcres` | Lot size in acres. | `0.5` |
| `yearBuilt` | Year built. | - |
| `description` | Description. | `Location doesn't get better than this! Just steps from Furman University and ...` |
| `aiHighlights` | Short highlights of the listing. | `["Brick home","Large back deck","Thoughtfully renovated interiors","Remodeled kitchen","Multiple patios and decks","Stainless appliances","Tile backsplash"]` |
| `datePosted` | Date the listing was posted. | `2026-08-09` |
| `onMarketDate` | Date the home went on the market. | `2026-08-09` |
| `daysOnZillow` | Days the listing has been on Zillow. | `62` |
| `pageViewCount` | Page views of the listing. | `814` |
| `favoriteCount` | Number of times the listing was saved as a favorite. | `89` |
| `priceChange` | Latest price change. | `-7500` |
| `priceChangeDate` | Date of the latest price change. | `2026-09-21` |
| `sellingSoonPercentile` | Selling-soon percentile shown by Zillow. | `0.588` |
| `listingType` | Listing type. | `For Sale by Agent` |
| `buildingId` | Building Id. | - |
| `sourceListingUrl` | Source listing url. | - |
| `rentalApplicationFee` | Rental application fee. | - |
| `tourTypes` | Tour types offered. | `["INSTANT_BOOK"]` |
| `listingAgentName` | Listing agent name. | - |
| `listingAgentPhone` | Listing agent phone. | - |
| `listingAgentEmail` | Listing agent email. | - |
| `listingAgentLicense` | Listing agent license. | - |
| `coListingAgentName` | Co listing agent name. | - |
| `coListingAgentPhone` | Co listing agent phone. | - |
| `brokerName` | Listing broker name. | `Bluefield Realty Group` |
| `brokerPhone` | Listing broker phone. | - |
| `buyerAgentName` | Buyer agent name. | - |
| `buyerBrokerName` | Buyer broker name. | - |
| `mlsId` | MLS ID. | `1600300` |
| `mlsName` | MLS name. | `Greater Greenville AOR` |
| `mlsLastChecked` | When the MLS record was last checked. | `2026-10-10 12:53:54` |
| `mlsLastUpdated` | When the MLS record was last updated. | `2026-09-21 14:51:33` |
| `isMlsListing` | Whether the listing comes from an MLS. | `true` |
| `coListingOfficeName` | Co-listing office name. | `Bluefield Realty Group` |
| `coListingAgentLicense` | Co listing agent license. | - |
| `buyerAgentLicense` | Buyer agent license. | - |
| `listingAgentProfileUrl` | Listing agent profile url. | - |
| `listingAgentRating` | Listing agent rating. | `5` |
| `listingAgentReviewCount` | Listing agent review count. | `5` |
| `listingAgentRecentSales` | Listing agent recent sales. | `0` |
| `listingAgentPhoto` | Listing agent photo. | - |
| `listingAgentZuid` | Listing agent zuid. | - |
| `listingWebsite` | Listing website. | - |
| `listingSource` | Listing source line. | `Source: Greater Greenville AOR` |
| `isListedByOwner` | Whether the home is listed by its owner. | `false` |
| `facts` | Home facts. | - |
| `atAGlanceFacts` | At-a-glance facts. | - |
| `originalListPrice` | Original list price. | `495000` |
| `listedDate` | Date the home was listed. | `2026-08-09` |
| `lastListPrice` | Latest list price. | `487500` |
| `relistsInCampaign` | Number of relists. | `0` |
| `priceCutCount` | Number of price cuts. | `1` |
| `priceIncreaseCount` | Number of price increases. | `0` |
| `totalPriceCutPct` | Total price cut in percent. | `1.52` |
| `soldVsLastListPct` | Sold price compared with the last list price, in percent. | - |
| `daysListedToSold` | Days from listing to sale. | - |
| `lastPriceCutDate` | Date of the last price cut. | `2026-09-21` |
| `daysSinceLastPriceCut` | Days since the last price cut. | `19` |
| `wentPendingThenBackOnMarket` | Whether the home went pending and then came back on the market. | `false` |
| `timesListedLast5y` | Times listed in the last 5 years. | `2` |
| `timesSold` | Times sold. | `3` |
| `yearsSinceLastSale` | Years since the last sale. | `3.3` |
| `isStale` | Whether the listing is marked stale. | `false` |
| `comps` | Comparable homes. | - |
| `compsCount` | Number of comparable homes. | `5` |
| `compsMedianPrice` | Median price of the comparable homes. | `475000` |
| `compsMedianPricePerSqft` | Median price per square foot of the comparable homes. | `174.0` |
| `arvEstimate` | After-repair-value estimate. | `450000` |
| `discountToArvPct` | Price compared with the after-repair-value estimate, in percent. | `-8.33` |
| `zestimateHistory` | Monthly Zestimate values. | - |
| `zestimateChange1yPct` | Zestimate change over 1 year, in percent. | `2.92` |
| `zestimateChange5yPct` | Zestimate change over 5 years, in percent. | `33.8` |
| `zestimateChange10yPct` | Zestimate change over 10 years, in percent. | `155.43` |
| `marketTemperature` | Local market temperature. | `buyer` |
| `marketTemperatureIndex` | Local market temperature index. | `43.1` |
| `marketTemperatureDescription` | Text description of the local market. | `Sellers outnumber buyers. Listing price cuts and concessions are common, but ...` |
| `marketMedianDaysToPending` | Local median days to pending. | `28.0` |
| `offerStrength` | Offer strength for homes for sale. | - |
| `walkScore` | Walk score. | `14` |
| `transitScore` | Transit score. | `9` |
| `bikeScore` | Bike score. | `40` |
| `climateRisk` | Flood, fire, heat, wind and air risk. | - |
| `schools` | Assigned and nearby schools. | - |
| `elementarySchoolName` | Elementary school name. | `Duncan Chapel Elementary School` |
| `elementarySchoolRating` | Elementary school rating. | `3` |
| `middleSchoolName` | Middle school name. | `Berea Middle School` |
| `middleSchoolRating` | Middle school rating. | `2` |
| `highSchoolName` | High school name. | `Travelers Rest High School` |
| `highSchoolRating` | High school rating. | `5` |
| `priceHistory` | Price history events. | - |
| `taxHistory` | Tax history by year. | - |
| `nearbyHomes` | Nearby homes. | - |
| `photoCount` | Number of photos. | `47` |
| `mainImage` | Main photo link. | `https://photos.zillowstatic.com/fp/6b25775b92e69c40a67ac44e05b52dbe-p_f.jpg` |
| `photos` | Photos (see the Photos input). | - |
| `virtualTourUrl` | Virtual tour link. | - |
| `hasVideo` | Whether the listing has a video. | `false` |
| `openHouses` | Open house events. | `[]` |
| `staticMapUrl` | Static map link. | `https://maps.googleapis.com/maps/api/staticmap?center=34.91575,-82.44426&zoom...` |
| `investment` | Rental investment figures. | - |
| `input` | The link, address or zpid you entered. | `https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/11026031_z...` |
| `inputType` | Kind of input: url, zpid or address. | `url` |
| `isValid` | True when data was found. | `true` |
| `invalidReason` | Reason when no data was found. | - |
| `scrapedAt` | Scraped at (ISO 8601 UTC). | `2026-10-10T20:09:10Z` |
| `buildingName` | Building name (building records). | - |
| `lotId` | Lot ID (building records). | - |
| `unitCount` | Unit count (building records). | - |
| `availableUnitCount` | Available units (building records). | - |
| `unitsByStatus` | Units by status (building records). | - |
| `minRent` | Lowest rent (building records). | - |
| `maxRent` | Highest rent (building records). | - |
| `medianRentByBedrooms` | Median rent by bedrooms (building records). | - |
| `units` | Units (building records). | - |
| `floorPlans` | Floor plans (building records). | - |
| `amenities` | Amenities (building records). | - |
| `petsAllowed` | Pets allowed (building records). | - |
| `petPolicy` | Pet policy (building records). | - |
| `specialOffers` | Special offers (building records). | - |
| `isNew` | New since the last run (monitor mode). | - |
| `events` | Monitor events (monitor mode). | - |
| `changes` | Monitor changes (monitor mode). | - |
| `phone` | Contact phone (building records). | - |
| `contactName` | Contact name (building records). | - |
| `competingBuildings` | Competing buildings (building records). | - |
| `fees` | Fees (building records). | - |
| `screeningCriteria` | Screening criteria (building records). | - |
| `nearbyBuildings` | Nearby buildings (building records). | - |
| `buildingDetails` | Building details (building records). | - |
| `homeTypes` | Home types (building records). | - |
| `buildingFeatures` | Building features (building records). | - |
| `unitAmenities` | Unit amenities (building records). | - |
| `laundry` | Laundry (building records). | - |
| `neighborhoodHighlights` | Neighborhood highlights (building records). | - |
| `isTrustedListing` | Trusted listing (building records). | - |
| `isLowIncome` | Low income housing (building records). | - |
| `isSeniorHousing` | Senior housing (building records). | - |
| `isStudentHousing` | Student housing (building records). | - |

#### Section tables

A Zillow data scraper that returns history as separate rows suits analysis, and the free section tables do exactly that. Each of the eight section tables repeats `propertyZpid`, `propertyAddress` and `propertyUrl` so rows can be joined back to the property. The dataset schema defines no example values for these tables, so only the field names are listed.

- **Price history:** `date`, `event`, `price`, `pricePerSqft`, `priceChangeRate`, `source`, `mlsId`, `sellerAgent`, `buyerAgent`, `isRental`
- **Tax history:** `year`, `taxPaid`, `assessedValue`, `taxIncreaseRate`, `valueIncreaseRate`
- **Schools:** `name`, `rating`, `level`, `grades`, `type`, `distanceMiles`, `isAssigned`, `district`, `enrollment`, `studentTeacherRatio`, `testScoresRating`, `link`
- **Comps:** `zpid`, `url`, `status`, `price`, `lastSoldPrice`, `dateSold`, `zestimate`, `bedrooms`, `bathrooms`, `livingArea`, `homeType`, `streetAddress`, `city`, `state`, `zipcode`, `image`
- **Nearby homes:** the same fields as Comps
- **Zestimate history:** `date`, `value`
- **Building units** (building pages): `lotId`, `zpid`, `unitNumber`, `floorPlan`, `status`, `price`, `requiredMonthlyFees`, `allInMonthlyRent`, `bedrooms`, `bathrooms`, `livingArea`, `availableNow`, `availableFrom`, `lastSoldDate`, `url`
- **Floor plans** (building pages): `lotId`, `name`, `bedrooms`, `bathrooms`, `livingArea`, `minPrice`, `maxPrice`, `leaseTerm`, `requiredMonthlyFees`, `availableNow`, `availableFrom`, `unitCount`, `image`
- **Failed inputs** (a separate table, not one of the eight, with no property fields): `input`, `inputType`, `invalidReason`, `zpid`, `url`, `candidates`, `scrapedAt`

A `SUMMARY` record in the key-value store holds totals for the whole run.

### 💡 Use cases for Zillow data

- **Rental underwriting:** Screen a Zillow rental investment shortlist by sorting rows on the modelled cap rate and cash-on-cash return.
- **Flip research:** Open the comparable homes table when you need a Zillow comps tool for quick after-repair-value checks.
- **Motivated-seller leads:** Rank homes by `priceCutCount`, `totalPriceCutPct` and `daysSinceLastPriceCut` to catch Zillow price drops early.
- **Valuation checks:** Compare the Zillow rent Zestimate with your own rent comparables before you make an offer.
- **Property history review:** Export the Zillow price history of a home as its own table.
- **Market tracking:** Agents and analysts who need a Zillow home data scraper for status, price and days on market can read them from every row, and monitor mode flags new or changed properties between runs.
- **Zestimate trend studies:** Teams that want a Zillow Zestimate scraper get 10 years of monthly values plus the 1, 5 and 10 year change.
- **Apartment research:** Building records carry units, floor plans, the rent range and the pet policy, which a Zillow rental data scraper can read for apartment research.

### 🛠️ How to scrape Zillow property details

You can mix links, addresses and zpids in one list. That input style suits a Zillow property scraper run for one home or many.

1. Create a free Apify account.
2. Open Zillow Detail Scraper in the Apify Store.
3. Add home links, building links, addresses or zpids to **Zillow links, addresses or zpids (bulk)**.
4. Switch on the extras you need, such as price and tax history, comparable homes or the rental investment model.
5. Set **Max properties** and click **Start**.
6. Download the dataset as JSON, CSV or Excel, or open the section tables.

Investors looking for a Zillow cap rate will find `capRatePct` in the investment object, and it follows your own assumptions.

#### How to web scrape Zillow with a link or an address

Paste a home link such as the pre-filled example, or a plain address like `18 Zelma Dr, Greenville, SC 29617`, into the bulk list and press **Start**. Every entry becomes one row, or one entry in the Failed inputs table if no property could be found.

#### How to scrape Zillow data for many properties

Add one entry per line. Repeated identical inputs are merged, and each property is saved as soon as it is ready. Use **Max properties** to cap the run, where 0 means no cap.

#### How to run a Zillow address lookup

Enter addresses as `123 Main St, City, State` and add the unit for apartments, for example `67 Morton St APT 6E, New York, NY`. Each address is matched to one Zillow property. **Minimum address match** runs from 0 to 1 with a default of 0.75, and a weaker match is not guessed: it goes to the Failed inputs table with its best candidates.

#### How to use a Zillow zpid lookup

The zpid is the number before `_zpid` in a home link, for example 11026031. Paste zpids into **Extra zpids** or the bulk list. A Zillow zpid scraper run accepts a zpid directly, so you do not need the full link.

#### How to scrape building and apartment pages

Building links (`/b/`, `/apartments/` or `/community/`) return one summary per building. Set **Units from building pages** to `none`, `all`, `forRent`, `forSale`, `sold` or `offMarket` to also open each unit, and use **Max units per building** to limit them, where 0 means every matching unit.

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

Zillow Detail Scraper uses pay-per-event pricing: $1.5 per 1,000 results on the Free plan and less on paid plans, billed as the `main_result` event, which the Console shows as Results. A tiny Actor Start event of $0.00005 per run start is added on top.

| Apify plan | Price per 1,000 results |
|---|---|
| Free | $1.5 |
| Bronze | $1.35 |
| Silver | $1.2 |
| Gold / Platinum / Diamond | $1 |

One result is one saved property, building or unit page. The section tables and the Failed inputs table are not billed. With monitor mode on, **Only new or changed** skips unchanged properties and they are not billed. For example, on the Free plan 1,000 results cost about $1.5 plus the start fee.

You can try this Zillow scraper free: free-plan runs save up to 10 properties each with no monthly cap, and paid plans have no per-run limit. If you set a spend limit, the run stops cleanly when it is reached. See the Pricing tab for current rates.

### ⬇️ Input

Only the bulk **Zillow links, addresses or zpids (bulk)** list (`urls`) is required, and every other option has a default or can stay empty.

![Zillow property details scraper input form with Zillow links, addresses and zpids](IMAGE_URL_PLACEHOLDER "zillow-detail-scraper-input-form.png")

See the Input tab for every option. The main ones are:

| Input | Default | What it does |
|---|---|---|
| `urls` | one pre-filled home link | Home links, building links, addresses or zpids, one per line. |
| `addresses` | empty | Extra addresses, one per line. |
| `zpids` | empty | Extra Zillow property IDs, one per line. |
| `minMatchConfidence` | 0.75 | Lowest address match accepted, from 0 to 1. |
| `extractBuildingUnits` | `none` | Which units to open on building pages: `none`, `all`, `forRent`, `forSale`, `sold` or `offMarket`. |
| `maxUnitsPerBuilding` | see the Input tab | Most units opened per building, where 0 means every matching unit. |
| `includeHistory` | true | Price history, tax history, schools, nearby homes, agents and foreclosure details. |
| `includeComps` | true | Comparable homes, their median price per square foot and an after-repair-value estimate. |
| `includeZestimateHistory` | true | 10 years of monthly Zestimate values plus the 1, 5 and 10 year change. |
| `includeMarketData` | true | Market temperature, median days to pending and offer strength for homes for sale. |
| `includeWalkScore` | true | Walk, transit and bike scores. |
| `includeClimateRisk` | true | Flood (including FEMA zone), fire, heat, wind and air risk. |
| `photos` | `urls` | `none`, `urls` (largest picture and caption) or `allSizes`. |
| `maxPhotos` | 0 | Most photos per property, where 0 means all. |
| `maxNearbyHomes` | 10 | Most nearby homes per property, where 0 means none. |
| `includeRawFacts` | false | Adds every MLS fact Zillow shows and makes rows larger. |
| `includeRaw` | false | Adds every field Zillow returned and makes rows much larger. |
| `investorAnalysis` | true | Adds the rental investment figures for properties with a price (or Zestimate) and a rent estimate. |
| `investorAssumptions` | down payment 20, loan term 30 years, closing costs 3, rehab budget 0, vacancy 5, maintenance 8, management 8, capex 5, insurance 0.5 | Your own assumptions. `interestRatePct` and `rentOverride` have no default and can stay empty. |
| `monitor` | false | Marks each property as new or changed since your last run and lists events. |
| `monitorOnlyChanges` | false | With the monitor on, saves only new or changed properties. |
| `maxItems` | 10 | Stops after this many saved properties, where 0 means no cap. |
| `writeCsv` | false | Also stores `properties.csv` in the run's storage. |
| `concurrency` | 4 | Properties processed at the same time. |
| `maxConcurrentRequests` | 3 | Parallel lookups across the whole run. |
| `maxRetries` | see the Input tab | Retries for a lookup that failed, where 0 means none. |
| `proxyConfiguration` | no proxy selected | Optional proxy settings; leave the default if you are unsure. |

Example input, built from the pre-filled and default values in the input schema:

```json
{
  "urls": [
    "https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/11026031_zpid/"
  ],
  "minMatchConfidence": 0.75,
  "extractBuildingUnits": "none",
  "includeHistory": true,
  "includeComps": true,
  "includeZestimateHistory": true,
  "includeMarketData": true,
  "includeWalkScore": true,
  "includeClimateRisk": true,
  "photos": "urls",
  "maxPhotos": 0,
  "maxNearbyHomes": 10,
  "investorAnalysis": true,
  "monitor": false,
  "maxItems": 10,
  "writeCsv": false,
  "concurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

💡 Keep **Max properties** low for a first test run.

⚠️ Each extra switched on makes a run slower, so turn off what you do not need.

### ⬆️ Output

The scraped results are shown as a dataset in the **Storage** tab. The table view is for convenience and doesn't show **all the fields**.

![Zillow property detail scraper output table with price, Zestimate and history](IMAGE_URL_PLACEHOLDER "zillow-detail-scraper-output-table.png")

- **JSON:** the full record, including the nested lists.
- **CSV:** from the dataset export, or as `properties.csv` when **Also save a CSV file** is on.
- **Excel:** use the dataset export to download Zillow data to Excel.

The row below is an example built only from the example values in the dataset schema. It continues from the example input above and is not a captured run.

```json
{
  "recordType": "home",
  "zpid": 11026031,
  "status": "forSale",
  "streetAddress": "17 Zelma Dr",
  "city": "Greenville",
  "state": "SC",
  "zipcode": "29617",
  "county": "Greenville County",
  "price": 487500,
  "zestimate": 479000,
  "zestimateLow": 455050,
  "zestimateHigh": 502950,
  "rentZestimate": 2699,
  "priceVsZestimatePct": 1.77,
  "annualTax": 2974,
  "mortgageRate30yr": 7.442,
  "homeType": "SINGLE_FAMILY",
  "bedrooms": 4,
  "bathrooms": 3,
  "livingArea": 2582,
  "lotSizeSqft": 21780,
  "daysOnZillow": 62,
  "priceCutCount": 1,
  "totalPriceCutPct": 1.52,
  "compsCount": 5,
  "compsMedianPrice": 475000,
  "arvEstimate": 450000,
  "marketTemperature": "buyer",
  "walkScore": 14,
  "transitScore": 9,
  "bikeScore": 40,
  "elementarySchoolName": "Duncan Chapel Elementary School",
  "elementarySchoolRating": 3,
  "brokerName": "Bluefield Realty Group",
  "mlsId": "1600300",
  "inputType": "url",
  "isValid": true,
  "scrapedAt": "2026-10-10T20:09:10Z"
}
```

Each home gets one row like this, which suits anyone looking for a Zillow home details scraper. The Zestimate history table suits anyone who wants a Zillow value history scraper, because it holds monthly values for the last 10 years.

The Zillow tax history table lists the yearly property tax paid and the assessed value.

### ⚠️ Limitations and error handling

- Zillow Detail Scraper looks up the properties and buildings you name. This is not a Zillow listings scraper for whole areas, because search results are not an input.
- Free-plan runs save up to 10 properties each, and **Max properties** counts buildings and unit pages too.
- Fields stay empty when Zillow shows no value, and an extra section can be unavailable for some homes while the main property data is still saved.
- Only public listing data is collected. There is no access to private or logged-in data.
- A weak address match is reported in the Failed inputs table instead of being guessed.
- Results reflect what Zillow shows at the time of the run.

Inputs that return no property are written to the Failed inputs table, and the reason is in `invalidReason`. These are readable reasons, not numeric codes:

| Reason in `invalidReason` | Meaning | What to do |
|---|---|---|
| `no Zillow address matched` | No property was close to the address. | Check the spelling and add city and state, or use a link or zpid. |
| `best match ... scored ... < minMatchConfidence ...` | The best candidate scored below your minimum. | Lower **Minimum address match** or use a link or zpid. |
| `address lookup failed – please try again later` | The address could not be looked up. | Run again later. |
| `page request failed` | The page could not be retrieved. | Run again later. |
| `page could not be loaded – please try again later` | The page could not be loaded after retries. | Run again later. |
| `page not found — listing removed or URL invalid` | The page does not exist. | Check the link. |
| `the building / listing is no longer published` | The building or listing was taken down. | Check the link on Zillow. |
| `unrecognised page` | The link is not a home or building page. | Use a home, building or apartment link. |
| `not processed – the connection to Zillow failed` | The run stopped early and this input was not processed. | Run again later. |
| `unexpected error while reading this property` | The page could not be read. | Run again, or report the input in the Issues tab. |

### 🔌 Integrating Zillow Detail Scraper with other apps

Zillow Detail Scraper runs on Apify, so you can start it through the API, schedule it, and pass its dataset to other tools with Apify integrations and webhooks. The API tab shows ready-made JavaScript, Python and CLI snippets.

- Start runs from your own code through the Apify API and treat the Actor as a Zillow scraper API.
- Python users can start runs and read results through the Apify client.
- The finished dataset can feed dashboards and spreadsheets as a Zillow property data API.
- Schedule the Actor on Apify, and with monitor mode on it reports price cuts, pending and sold events between runs.

### 🔗 More Apify Actors by crawl_craft

These Actors cover other platforms and have no topical relation to Zillow Detail Scraper. They are listed only because they come from the same account.

| Actor | What it extracts |
|---|---|
| [Google Job Scraper](https://apify.com/crawl_craft/google-job-scraper) | Job listings from Google Jobs with company, location, salary and apply links. |
| [Telegram Scraper](https://apify.com/crawl_craft/telegram-scraper) | Messages, views, reactions and subscriber counts from public Telegram channels. |
| [Etsy Scraper](https://apify.com/crawl_craft/etsy-scraper) | Etsy listings, shops, reviews, prices and keyword research. |

### ⚖️ Is it legal to scrape Zillow?

Zillow Detail Scraper only collects information shown publicly on Zillow pages and does not collect data behind a login. Results can still contain personal data such as agent names, so collect it only with a legitimate reason and consider GDPR (Regulation (EU) 2016/679). Zillow web scraping can be restricted by Zillow's terms of use and by local law, so consult a lawyer if you are unsure. Apify's posts on [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) and [ethical web scraping](https://blog.apify.com/what-is-ethical-web-scraping-and-how-do-you-do-it/) are a good starting point.

### ❓ FAQ

#### How much does Zillow Detail Scraper cost?

It costs $1.5 per 1,000 results on the Free plan and less on paid plans (see the table in the pricing section), plus a tiny Actor Start event of $0.00005 per run start. Free-plan runs save up to 10 properties each.

#### Can you scrape Zillow without an account?

Yes. No Zillow account or login is needed to read the public pages this Actor uses.

#### Do I need a Zillow API key?

No. The Actor takes links, addresses or zpids and needs no key from Zillow, and no Zillow scraper Python script is needed to run it.

#### How do I export Zillow data to Excel?

Open the dataset in the Storage tab, choose the export option and pick Excel. You can also switch on **Also save a CSV file** for a flat `properties.csv`.

#### Can I get a Zillow Zestimate by address?

Yes. Add the address to the bulk list or to **Extra addresses**, and it is matched to one Zillow property. The Zestimate fields are filled when Zillow shows them for that home.

#### Is this a general Zillow real estate scraper?

No. Zillow Detail Scraper returns details for the links, addresses and zpids you provide and does not crawl search results.

#### Do I need to install this Zillow scraper tool?

No. It runs on Apify as an Apify Zillow scraper, so you start it from the Console or the API and download the results.

#### How many properties can I scrape?

**Max properties** sets the cap, and 0 means no cap. Free-plan runs stop at 10 properties, and paid plans have no per-run limit.

#### Do I need proxies?

Proxy settings are optional. Leave the default if you are unsure.

#### Can I scrape private data?

No. Only public listing data is collected.

### 💬 Your feedback

Found a bug or want a new field? Open an issue in the Issues tab. For custom solutions, write to hello.crawlcraft@gmail.com.

# Actor input Schema

## `urls` (type: `array`):

One entry per line. Accepted: a home link (https://www.zillow.com/homedetails/Address/12345678_zpid/), a building or apartment link (/b/..., /apartments/..., /community/...), a plain address such as 18 Zelma Dr, Greenville, SC 29617, or a numeric zpid. Any mix works.

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

Optional addresses, one per line, in the form 123 Main St, City, State. Add the unit for apartments (for example 67 Morton St APT 6E, New York, NY). Each address is matched to one Zillow property.

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

Optional Zillow property IDs, one per line (for example 11026031). The fastest way to look up a home when you already have its ID.

## `minMatchConfidence` (type: `number`):

From 0 to 1. An address that matches a Zillow property with less confidence than this is not guessed: it is listed in the Failed inputs table with its best candidates instead.

## `extractBuildingUnits` (type: `string`):

For building links, also scrape each individual unit. Choose which units to open: none (building summary only), all, or only units for rent, for sale, sold or off market.

## `maxUnitsPerBuilding` (type: `integer`):

Most units opened for each building page. 0 means every matching unit.

## `includeHistory` (type: `boolean`):

Add price history, tax history, assigned schools, nearby homes, agents and foreclosure details when the page does not already carry them.

## `includeComps` (type: `boolean`):

Add Zillow's comparable homes, their median price per square foot and an after-repair-value estimate.

## `includeZestimateHistory` (type: `boolean`):

Add 10 years of monthly Zestimate values plus the 1, 5 and 10 year change.

## `includeMarketData` (type: `boolean`):

Add the local market temperature and median days to pending, plus offer strength (offer as a percent of list price needed to win) for homes for sale.

## `includeWalkScore` (type: `boolean`):

Add the walk, transit and bike scores of the address.

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

Add flood (including FEMA zone), fire, heat, wind and air risk.

## `photos` (type: `string`):

none skips photos, urls returns the largest picture and caption of each photo, allSizes returns every available size.

## `maxPhotos` (type: `integer`):

Most photos returned per property. 0 means all of them.

## `maxNearbyHomes` (type: `integer`):

Most nearby homes returned per property. 0 means none.

## `includeRawFacts` (type: `boolean`):

Add every MLS fact Zillow shows to each property. Makes rows larger.

## `includeRaw` (type: `boolean`):

Add every raw field Zillow returned for the property. Makes rows much larger.

## `investorAnalysis` (type: `boolean`):

For every property with a price (or Zestimate) and a rent estimate, add the rental investment figures.

## `investorAssumptions` (type: `object`):

Your own assumptions for the rental investment figures. Leave a value empty to use its default.

## `monitor` (type: `boolean`):

Mark each property as new or changed since your last run and list events such as price cut, went pending, sold or back on market. Combine with a schedule to watch listings.

## `monitorOnlyChanges` (type: `boolean`):

With the monitor on, save only properties that are new or have an event. Unchanged properties are skipped and not billed.

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

Stop after this many properties are saved (buildings and unit pages count too). 0 means no cap. Free plan users get up to 10 properties per run; paid plans have no run limit.

## `writeCsv` (type: `boolean`):

Also store a flat CSV (one row per property) in the run's storage as properties.csv.

## `concurrency` (type: `integer`):

How many properties are processed at the same time. Lower it if many inputs fail.

## `maxConcurrentRequests` (type: `integer`):

Most lookups running at the same moment across the whole run. Lower it if many inputs fail.

## `maxRetries` (type: `integer`):

Number of extra attempts for a lookup that failed. 0 means none.

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

Optional proxy settings for this run. Leave the default if you are unsure.

## Actor input object example

```json
{
  "urls": [
    "https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/11026031_zpid/"
  ],
  "addresses": [],
  "zpids": [],
  "minMatchConfidence": 0.75,
  "extractBuildingUnits": "none",
  "maxUnitsPerBuilding": 10,
  "includeHistory": true,
  "includeComps": true,
  "includeZestimateHistory": true,
  "includeMarketData": true,
  "includeWalkScore": true,
  "includeClimateRisk": true,
  "photos": "urls",
  "maxPhotos": 0,
  "maxNearbyHomes": 10,
  "includeRawFacts": false,
  "includeRaw": false,
  "investorAnalysis": true,
  "investorAssumptions": {
    "downPaymentPct": 20,
    "loanTermYears": 30,
    "closingCostPct": 3,
    "rehabBudget": 0,
    "vacancyPct": 5,
    "maintenancePct": 8,
    "managementPct": 8,
    "capexPct": 5,
    "insuranceRatePct": 0.5
  },
  "monitor": false,
  "monitorOnlyChanges": false,
  "maxItems": 10,
  "writeCsv": false,
  "concurrency": 4,
  "maxConcurrentRequests": 3,
  "maxRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `properties` (type: `string`):

One row per property or building with prices, Zestimate, history, contacts and the investor model.

## `priceHistory` (type: `string`):

Every listing, price change and sale event of each property.

## `taxHistory` (type: `string`):

Yearly property tax paid and assessed value.

## `schools` (type: `string`):

Nearby and assigned schools with ratings.

## `comps` (type: `string`):

Zillow's comparable homes for each property.

## `nearbyHomes` (type: `string`):

Homes near each property.

## `zestimateHistory` (type: `string`):

Monthly Zestimate values for the last 10 years.

## `buildingUnits` (type: `string`):

Every unit listed on a building page.

## `floorPlans` (type: `string`):

Floor plans of each building with price range and availability.

## `failedInputs` (type: `string`):

Inputs that returned no property, with the reason and best address candidates.

## `summary` (type: `string`):

Totals for the whole run.

## `csv` (type: `string`):

Properties as CSV, when 'Also save a CSV file' is on.

# 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 = {
    "urls": [
        "https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/11026031_zpid/"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawl_craft/zillow-detail-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 = {
    "urls": ["https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/11026031_zpid/"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("crawl_craft/zillow-detail-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 '{
  "urls": [
    "https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/11026031_zpid/"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call crawl_craft/zillow-detail-scraper --silent --output-dataset

```

## MCP server setup

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