# Zillow Detail Scraper - Property Data by URL, ZPID or Address (`benthepythondev/zillow-detail-scraper`) Actor

Get the full Zillow record for any US home by URL, ZPID or street address: price, Zestimate, price and tax history, agent name and phone, schools, facts and photos.

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

## Pricing

from $4.25 / 1,000 properties

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 Detail Scraper - Property Data by URL, ZPID or Address

Get the full Zillow record for any US home. Paste Zillow links, ZPIDs or plain street addresses and receive one row per home with price, Zestimate, price and tax history, listing agent with phone, schools, home facts, climate risk and photo links. Export to JSON/CSV/Excel, run on a schedule, call via API, or connect to Make, Zapier or n8n.

### 🔎 What is the Zillow Detail Scraper?

It is an Apify Actor that looks up each home you name on Zillow and saves everything Zillow publishes about it. It works for homes that are for sale, for rent, recently sold or off the market, because Zillow keeps a record for almost every US address.

You can mix three kinds of input in one list:

- a Zillow home link such as `https://www.zillow.com/homedetails/5718-Highland-Hills-Dr-Austin-TX-78731/29345631_zpid/`
- a ZPID, the number in that link (`29345631`)
- a street address (`3750 N Pittsburgh Ave, Chicago, IL 60634`)

No browser is started and no third-party unblocker is used. Each home takes one request to Zillow: in our tests 100 homes took 18 seconds and 400 homes took one minute.

#### What data does it extract?

- **Identity:** `zpid`, `url`, `homeStatus` (FOR_SALE, PENDING, RECENTLY_SOLD, FOR_RENT, OTHER), `homeType`, `listingTags`
- **Location:** `address`, `street`, `city`, `state`, `zip`, `neighborhood`, `subdivision`, `county`, `countyFips`, `parcelId`, `latitude`, `longitude`
- **Value:** `price`, `zestimate`, `rentZestimate`, `pricePerSqft`, `lastSoldPrice`, `lastSoldDate`, `monthlyHoaFee`, `taxAssessedValue`, `taxAnnualAmount`
- **Size:** `bedrooms`, `bathrooms`, `livingArea`, `lotSize` (both in square feet), `yearBuilt`, `stories`
- **Listing agent:** `agentName`, `agentPhone`, `agentEmail`, `agentLicense`, `coAgentName`, `coAgentPhone`, `brokerName`, `brokerPhone`, `mlsId`, `mlsName`, and for sold homes `buyerAgentName` and `buyerBrokerName`
- **History:** `priceHistory[]` (date, event, price, price per sqft, change, source) and `taxHistory[]` (year, tax paid, assessed value)
- **Schools:** `schools[]` with name, rating, grades, level, type, distance, district and enrollment
- **Facts:** `facts`, Zillow's "Facts & features" block: heating, cooling, appliances, flooring, parking, roof, lot features, rooms, utilities, listing terms and more
- **Risk:** `climateRisk` with flood, fire, wind, heat and air scores from 1 to 10, plus the FEMA flood zone
- **Demand:** `daysOnZillow`, `pageViews`, `favorites`
- **Media and extras:** `photos[]`, `photoCount`, `virtualTourUrl`, `floorPlanUrl`, `description`, `highlights`, `openHouses[]`, `nearbyHomes[]`

`input` repeats the value you entered, so you can join the result back to your own list.

### ⬇️ Input

| Field | Type | What it does |
|---|---|---|
| `homes` | array | Zillow home links, ZPIDs or street addresses. One per line, in any mix |

#### Example input

```json
{
  "homes": [
    "https://www.zillow.com/homedetails/5718-Highland-Hills-Dr-Austin-TX-78731/29345631_zpid/",
    "3595611",
    "8901 Tronewood Dr, Austin, TX"
  ]
}
```

Write addresses the way you would type them into Zillow's search box, with city and state. A ZIP code helps when a street name exists in several towns.

### ⬆️ Output

One row per home. This is a real row with the long lists shortened:

```json
{
  "input": "https://www.zillow.com/homedetails/5718-Highland-Hills-Dr-Austin-TX-78731/29345631_zpid/",
  "zpid": "29345631",
  "url": "https://www.zillow.com/homedetails/5718-Highland-Hills-Dr-Austin-TX-78731/29345631_zpid/",
  "homeStatus": "FOR_SALE",
  "homeType": "SINGLE_FAMILY",
  "listingTags": ["agent listing", "open house"],
  "address": "5718 Highland Hills Dr, Austin, TX 78731",
  "neighborhood": "Northwest Hills",
  "county": "Travis County",
  "countyFips": "48453",
  "parcelId": "128020",
  "latitude": 30.339848,
  "longitude": -97.758835,
  "price": 1185000,
  "pricePerSqft": 499,
  "lastSoldDate": "2013-04-13",
  "taxAssessedValue": 939974,
  "taxAnnualAmount": 22189,
  "bedrooms": 4,
  "bathrooms": 3,
  "livingArea": 2376,
  "lotSize": 9931,
  "yearBuilt": 1958,
  "daysOnZillow": 1,
  "pageViews": 703,
  "favorites": 51,
  "agentName": "Atoosa Ponsford",
  "agentPhone": "(512) 480-0848",
  "brokerName": "Moreland Properties",
  "mlsId": "2986990",
  "mlsName": "Unlock MLS",
  "highlights": ["Large lot", "Private greenbelt setting", "New european hardwood flooring"],
  "priceHistory": [
    {"date": "2026-09-30", "event": "Listed for sale", "price": 1185000, "pricePerSqft": 499, "changeRate": 0.1296, "source": "Unlock MLS"},
    {"date": "2024-11-23", "event": "Listing removed", "price": 1049000, "pricePerSqft": 441, "changeRate": 0, "source": "Unlock MLS"}
  ],
  "taxHistory": [{"year": 2025, "taxPaid": 19236.43, "assessedValue": 939974}],
  "schools": [
    {"name": "Highland Park Elementary School", "rating": 10, "grades": "PK-5", "level": "Primary", "type": "Public", "distance": 0.6, "district": "Austin Independent School District", "enrollment": 648}
  ],
  "facts": {
    "heating": ["Central", "Natural Gas"],
    "cooling": ["Central Air", "Electric"],
    "flooring": ["Tile", "Wood"],
    "parkingFeatures": ["Driveway"],
    "roofType": "Composition, Shingle",
    "listingTerms": "Cash,Conventional,FHA,VA Loan",
    "onMarketDate": "2026-09-30"
  },
  "climateRisk": {"flood": {"score": 1, "label": "MINIMAL"}, "femaZone": "X_UNSHADED", "wind": {"score": 8, "label": "SEVERE"}, "heat": {"score": 8, "label": "SEVERE"}},
  "openHouses": [{"start": "2026-10-03 11:00:00", "end": "2026-10-03 13:00:00"}],
  "nearbyHomes": [{"zpid": "29345689", "address": "5716 Highland Hills Dr", "price": 915800, "bedrooms": 3, "bathrooms": 2, "livingArea": 2033, "homeStatus": "OTHER"}],
  "photos": ["https://photos.zillowstatic.com/fp/12c1fde4a1a03e5f9dd1cf0d2179da3d-uncropped_scaled_within_1536_1152.jpg"],
  "photoCount": 40,
  "virtualTourUrl": "https://www.zillow.com/view-3d-home/bcd68007-0e50-475d-9320-045a2de5f712",
  "detailsLevel": "full",
  "scrapedAt": "2026-10-02T16:00:00+00:00"
}
```

This home had 28 price events, 22 tax years and 40 photos in the full row. A sold home adds values such as `"lastSoldPrice": 305000`, `"zestimate": 308700` and `"rentZestimate": 2495`.

### 💰 How much does it cost?

You pay per home found, plus a tiny start fee per run. Inputs that Zillow does not know are not charged.

| Apify plan | Price per 1,000 homes |
|---|---|
| Free | $5.00 |
| Starter | $4.75 |
| Scale | $4.50 |
| Business and above | $4.25 |

A list of 200 homes costs $1.00 on the Free plan. Set **Maximum cost per run** in the run options and the Actor stops at that amount. History, agent contact, schools and photos are all included in the price.

### 💡 Use cases

- 📊 **Valuation and comps:** pull price history, tax history and Zestimate for a list of addresses before an appraisal or an offer.
- 📞 **Agent and broker leads:** collect the listing agent, phone, brokerage and MLS number for every active listing in your farm area.
- 🏦 **Portfolio monitoring:** run the same ZPID list every week and track `price`, `zestimate` and `homeStatus` over time.
- 🧾 **Data enrichment:** turn a CRM export of street addresses into parcel IDs, lot sizes, year built and school ratings.

### ❓ FAQ

**What can I use as input?** Zillow home links, ZPIDs and street addresses, mixed freely. Links to apartment buildings (`/apartments/` or `/b/`) are not single homes; use the Zillow Rentals Scraper for those.

**Does it work for homes that are not for sale?** Yes. Off-market and sold homes return their record too, usually with a Zestimate and a rent Zestimate. Agent fields are filled only while a listing exists or shortly after a sale.

**What does `price` mean for each status?** For an active listing it is the asking price, for a sold home the sale price, and for an off-market home Zillow reports its own estimate in that field. Check `homeStatus` before comparing prices.

**Why is `lastSoldPrice` empty when `lastSoldDate` is filled?** Some states, Texas among them, do not disclose sale prices. Zillow then shows the sale date without an amount.

**How do I get the homes to look up?** Use the [Zillow Search Scraper](https://apify.com/benthepythondev/zillow-scraper) for a city or ZIP code and pass its `zpid` or `url` column to this Actor, or paste your own address list.

**What happens when an address is not found?** The Actor logs a warning, skips the entry and continues. You are not charged for it.

**What is `detailsLevel`?** `full` means the complete record. If Zillow changes its site and the complete record is temporarily unavailable, the Actor falls back to the smaller record on the home page and marks the row `basic` (no history or schools) instead of failing.

**How fresh is the data?** Every run reads Zillow live. Nothing is cached between runs.

**Is it legal to scrape Zillow property data?** The Actor collects information Zillow shows publicly to any visitor and does not log in or bypass a paywall. You are responsible for how you use the data. Agent names and phone numbers are business contact details, but privacy and marketing rules such as GDPR, CCPA, CAN-SPAM and the TCPA still apply to outreach, and Zillow's terms of use apply to you as well. If in doubt, ask a lawyer.

**Something is missing or broken?** Open an issue on the Actor's Issues tab with the run ID. Issues are answered within one business day.

### 🧩 Need this as a managed feed?

If you would rather receive a weekly file for your markets than run the Actor yourself, request a quote at <https://benthepythondev00.github.io/custom.html>.

### 🔗 You might also like

- [Zillow Search Scraper](https://apify.com/benthepythondev/zillow-scraper)
- [Zillow Rentals Scraper](https://apify.com/benthepythondev/zillow-rentals-scraper)
- [Apartments.com Rent & Availability Monitor](https://apify.com/benthepythondev/apartments-com-rent-monitor)
- [Zumper Rental Scraper & Price Change Monitor](https://apify.com/benthepythondev/zumper-rental-scraper)
- [Real Estate Agent & Agency Lead Scraper](https://apify.com/benthepythondev/real-estate-agent-lead-scraper)
- [Craigslist Real Estate Scraper](https://apify.com/benthepythondev/craigslist-real-estate-scraper)

**Keywords:** zillow detail scraper, zillow property details, zillow api alternative, zillow zpid lookup, zillow address lookup, zestimate api, zillow price history, zillow tax history, property data api, real estate data enrichment, listing agent phone numbers, real estate agent leads, home value data, parcel data, school ratings data, flood risk data, zillow csv export, zillow property scraper

# Actor input Schema

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

Zillow home URLs, ZPIDs (the number before "\_zpid" in a Zillow URL) or full street addresses with city and state. One per line. You can mix all three. Each home found is one charged result.

## Actor input object example

```json
{
  "homes": [
    "https://www.zillow.com/homedetails/5718-Highland-Hills-Dr-Austin-TX-78731/29345631_zpid/",
    "3750 N Pittsburgh Ave, Chicago, IL 60634"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "homes": [
        "https://www.zillow.com/homedetails/5718-Highland-Hills-Dr-Austin-TX-78731/29345631_zpid/",
        "3750 N Pittsburgh Ave, Chicago, IL 60634"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/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 = { "homes": [
        "https://www.zillow.com/homedetails/5718-Highland-Hills-Dr-Austin-TX-78731/29345631_zpid/",
        "3750 N Pittsburgh Ave, Chicago, IL 60634",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("benthepythondev/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 '{
  "homes": [
    "https://www.zillow.com/homedetails/5718-Highland-Hills-Dr-Austin-TX-78731/29345631_zpid/",
    "3750 N Pittsburgh Ave, Chicago, IL 60634"
  ]
}' |
apify call benthepythondev/zillow-detail-scraper --silent --output-dataset

```

## MCP server setup

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