Zillow Scraper
Give it a city, ZIP code, county, Zillow search URL, property URL or zpid and it returns Zillow homes for sale, for rent or recently sold, one JSON row per property: price, Zestimate, rent Zestimate, beds, baths, square feet, lot, home type, days on market, price cut, brokerage, photos and coordinates. With details: description, year built, facts, price history, tax history and schools. $2.10 per 1,000 properties, $3.20 per 1,000 with details; paid plans pay less. You pay only for rows you get.
$2.10 per 1,000 properties on the Free plan, down to $1.20 on higher plans
Why this actor
- Whole areas, not just 820 homes: big searches are split into map sections and de-duplicated.
- Any input you have: free-text places, search URLs with your filters, property URLs or zpids.
- No personal data: agents' names, phones, emails and licence numbers are never returned; the brokerage name is kept.
- Inputs that cannot be read give a free error row with a
code.
Drop-in input
Drop-in input. Input written for maxcopell/zillow-scraper (searchUrls, resultsLimit), maxcopell/zillow-zip-search (zipCodes, priceMin, priceMax, daysOnZillow, forRent, sold) or maxcopell/zillow-detail-scraper (startUrls, propertyStatus) works as it is.
As stated in the actor’s README. The full list of accepted input names is on the Store page.
Switching from another actor
- From Zillow Detail Scraper maxcopell/zillow-detail-scraper, 3 input fields work as they are
What you get
| Field | What it holds |
|---|---|
rowType | Kind of row. Filter on this first. 'property': one Zillow property (charged as 'property', or 'property-details' when detailed is true). 'error': an input could not be read; see code and message (free). |
platform | Always 'zillow'. |
propertyId | Zillow property id (zpid), the number before _zpid in the property URL. Unique per run. |
url | Property page URL on zillow.com. |
status | Listing status as Zillow states it: FOR_SALE, FOR_RENT, RECENTLY_SOLD, PENDING, OFF_MARKET, ... |
statusText | Status as shown on the card, e.g. 'Active', 'House for rent', 'Sold'. |
price | List price in USD; monthly rent for rentals; null for sold homes in search rows (see lastSoldPrice on detail rows). |
currency | Currency of all money fields, normally USD. |
address | Full address line, e.g. '3207 Wickham Ln, Austin, TX 78725'. |
street | Street address. |
city | City name of the property address. |
state | Two-letter state code. |
zipcode | ZIP code of the property address. |
latitude | Latitude (WGS84). |
longitude | Longitude (WGS84). |
beds | Number of bedrooms. |
baths | Bathrooms (half baths count 0.5). |
livingArea | Living area in square feet. |
lotArea | Lot size in lotAreaUnit. |
lotAreaUnit | Unit of lotArea: sqft or acres. |
homeType | SINGLE_FAMILY, CONDO, TOWNHOUSE, MULTI_FAMILY, APARTMENT, LOT, MANUFACTURED, ... |
yearBuilt | Year built (detail rows). |
daysOnMarket | Days on Zillow. |
zestimate | Zillow's estimated market value in USD (Zestimate). |
rentZestimate | Zillow's estimated monthly rent in USD. |
taxAssessedValue | Latest tax-assessed value in USD. |
priceChange | Last price change in USD (negative = price cut). |
priceChangeDate | ISO date of the last price change. |
dateSold | ISO date of the last sale, when known. |
lastSoldPrice | Last sold price in USD (detail rows). |
brokerName | Listing brokerage (company). Agent names, phones and emails are never included. |
photos | Property photo URLs (photos.zillowstatic.com). |
photoCount | Number of photos on the listing (detail rows). |
hasVideo | True when the listing has a video. |
has3DModel | True when the listing has a 3D home tour. |
detailed | True when the row carries the detail fields (description, facts, priceHistory, taxHistory, schools). |
description | Listing description; emails, phone numbers and agent names removed. |
monthlyHoaFee | Monthly HOA fee in USD. |
propertyTaxRate | Property tax rate in percent. |
mlsId | MLS listing number. |
listingDataSource | Where the listing comes from, e.g. the MLS name or 'Phoenix'. |
county | County name (detail rows). |
parcelId | County parcel number. |
facts | Selected building and lot facts: heating, cooling, appliances, flooring, parkingFeatures, garageParkingCapacity, stories, basement, poolFeatures, view, lotFeatures, sewer, waterSource, associationFee, taxAnnualAmount, school names, atAGlanceFacts and more (keys present only when Zillow has them). |
priceHistory | Price events, newest first: {date, event ('Listed for sale', 'Price change', 'Sold', 'Listed for rent'...), price, pricePerSquareFoot, priceChangeRate, source}. No agent names. |
taxHistory | Public tax record per year: {date, taxPaid, value, taxIncreaseRate, valueIncreaseRate}. |
schools | Nearby assigned schools: {name, rating (GreatSchools 1-10), distance (miles), grades, level, link}. |
pageViewCount | Page views Zillow reports for the listing. |
favoriteCount | Times the listing was saved. |
searchInput | The location or search URL this row was found by (null for property URLs). |
searchRank | 1-based position in that search's results. |
scrapedAt | ISO time the row was read. |
input | Error rows: the input that failed. |
code | Error rows: invalid_input, not_found, blocked or unavailable. |
message | Error rows: what went wrong, in plain words. |
Sample row (from the README example; long text shortened, lists cut to two items):
{
"rowType": "property",
"platform": "zillow",
"propertyId": "70345655",
"url": "https://www.zillow.com/homedetails/3207-Wickham-Ln-Austin-TX-78725/70345655_zpid/",
"status": "FOR_SALE",
"price": 324900,
"currency": "USD",
"address": "3207 Wickham Ln, Austin, TX 78725",
"city": "Austin",
"state": "TX",
"zipcode": "78725",
"latitude": 30.232096,
"longitude": -97.5937,
"beds": 4,
"baths": 3,
"livingArea": 2575,
"lotArea": 4800.312,
"lotAreaUnit": "sqft",
"homeType": "SINGLE_FAMILY",
"daysOnMarket": 140,
"zestimate": null,
"rentZestimate": null,
"taxAssessedValue": 365588,
"priceChange": -15000,
"priceChangeDate": "2026-10-14",
"brokerName": "T J Lewis Real Estate",
"photos": null,
"detailed": false,
"searchInput": "Austin, TX",
"searchRank": 1,
"scrapedAt": "2026-10-22T10:00:00.000Z"
}
Price
Live Apify price on 2026-11-02, per 1,000 rows, by Apify plan. You pay only for rows delivered; error and summary rows marked free in the README cost nothing. Plus $0.001 per GB of memory when a run starts.
| Per 1,000 | Free | Bronze | Silver | Gold | Platinum | Diamond |
|---|---|---|---|---|---|---|
| Property (main) | $2.10 | $1.80 | $1.50 | $1.20 | $1.20 | $1.20 |
| Property with details | $3.20 | $2.70 | $2.20 | $1.50 | $1.50 | $1.50 |
Run it from code or an AI agent
Actor ID arcadium/zillow-properties. Set APIFY_TOKEN to your Apify API token. The input below is the actor’s prefilled example; see the guide for every field.
curl
curl -X POST "https://api.apify.com/v2/acts/arcadium~zillow-properties/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"locations":["Austin, TX"],"maxResultsPerSearch":50}'JavaScript
// npm install apify-client
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('arcadium/zillow-properties').call({
"locations": [
"Austin, TX"
],
"maxResultsPerSearch": 50
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);Python
# pip install apify-client
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("arcadium/zillow-properties").call(run_input={
"locations": ["Austin, TX"],
"maxResultsPerSearch": 50,
})
items = client.dataset(run.default_dataset_id).list_items().items # apify-client 3.x returns a Run object
print(items)MCP
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=arcadium/zillow-properties",
"headers": {
"Authorization": "Bearer <APIFY_TOKEN>"
}
}
}
}LangChain
# pip install langchain-apify (reads APIFY_API_TOKEN from the environment)
from langchain_apify import ApifyActorsTool
tool = ApifyActorsTool("arcadium/zillow-properties")
rows = tool.invoke({"run_input": {
"locations": ["Austin, TX"],
"maxResultsPerSearch": 50,
}})
# or give `tool` to an agent: create_react_agent(llm, [tool])LlamaIndex
# pip install llama-index-readers-apify
import os
from llama_index.core import Document, VectorStoreIndex
from llama_index.readers.apify import ApifyActor
reader = ApifyActor(os.environ["APIFY_TOKEN"])
documents = reader.load_data(
actor_id="arcadium/zillow-properties",
run_input={
"locations": ["Austin, TX"],
"maxResultsPerSearch": 50,
},
dataset_mapping_function=lambda item: Document(text=str(item.get("description") or ""), metadata={"url": item.get("url")}),
)
index = VectorStoreIndex.from_documents(documents)CrewAI
# pip install crewai crewai-tools langchain-apify (reads APIFY_API_TOKEN from the environment)
from crewai import Agent
from crewai_tools import ApifyActorsTool
tool = ApifyActorsTool(actor_name="arcadium/zillow-properties")
researcher = Agent(
role="Research analyst",
goal="Answer with data collected by the tool",
backstory="Uses public web data.",
tools=[tool],
)n8n
{
"nodes": [
{
"name": "Run arcadium/zillow-properties",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
0,
0
],
"parameters": {
"method": "POST",
"url": "https://api.apify.com/v2/acts/arcadium~zillow-properties/run-sync-get-dataset-items",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\"locations\":[\"Austin, TX\"],\"maxResultsPerSearch\":50}",
"options": {
"timeout": 300000
}
}
}
],
"connections": {}
}Google Sheets
// Extensions > Apps Script. Store your token once: Project Settings > Script properties > APIFY_TOKEN.
function importLastRun() {
const token = PropertiesService.getScriptProperties().getProperty('APIFY_TOKEN');
const url = 'https://api.apify.com/v2/acts/arcadium~zillow-properties/runs/last/dataset/items?status=SUCCEEDED&clean=true&format=json';
const res = UrlFetchApp.fetch(url, { headers: { Authorization: 'Bearer ' + token } });
const rows = JSON.parse(res.getContentText());
if (!rows.length) return;
const keys = Object.keys(rows[0]);
const values = rows.map((r) => keys.map((k) => (typeof r[k] === 'object' ? JSON.stringify(r[k]) : r[k])));
const sheet = SpreadsheetApp.getActiveSheet();
sheet.clearContents();
sheet.getRange(1, 1, 1, keys.length).setValues([keys]);
sheet.getRange(2, 1, values.length, keys.length).setValues(values);
}Limitations
- Zillow lists at most 820 homes per query; larger areas are split into map sections automatically.
- Sold homes often have
price: nullin search rows; useincludeDetailsforlastSoldPrice.
Related actors
AutoScout24 Scraper
AutoScout24 used cars from 8 EU country sites (make, model, year, km, price, price rating, fuel, power, dealer) for URLs or filters; $0.44 per 1,000 cars.
$0.44 per 1,000 Car listings on the Free plan, down to $0.33 on higher plans