Zillow Details Scraper — Zillow Property Details, Agent Data
Pricing
from $50.00 / 1,000 properties
Zillow Details Scraper — Zillow Property Details, Agent Data
Zillow search scraper for real estate listings, agent leads, contacts: listing agent email, phone, price history, Zestimate. Homes for sale, FSBO by owner: owner name, phone, foreclosures, multi family, rentals, recently sold comps by city or ZIP code; addresses, ZPIDs, property links, Zillow URL.
Pricing
from $50.00 / 1,000 properties
Rating
4.9
(4)
Developer
Andrey Afanasenko
Maintained by CommunityActor stats
17
Bookmarked
811
Total users
51
Monthly active users
4 days ago
Last modified
Categories
Share
Extract Zillow property listings with agent contacts (emails, phones) — or the owner's name and phone on FSBO listings — price history, and 70+ data fields. Three search modes: a city, county or ZIP codes, a list of ZPIDs, property links or street addresses, or any Zillow search URL. 40+ filters including tri-state controls for auctions, foreclosures, and new construction. Built for real-estate lead generation.
Find homes for sale, rent, and sold across the US — get listing details, photos, and agent contacts in one structured row per property.
Zillow's public API only covers properties you own or sell on the Zillow brand network. This actor reads anything Zillow shows in the browser — full filter set, agent emails and phone numbers, price-history arrays, school ratings, photo galleries, and 70+ output columns per row.
🎯 What it does
Three input shapes — pick the one that matches what you have:
| Mode | Input | What it returns |
|---|---|---|
1: City or ZIP Code Search (mode: "zip") | Cities with their state (Phoenix, AZ), counties, neighborhoods or ZIP codes + 40+ filters | Listings inside each place or ZIP you enter, enriched — one search per entry. Most-used mode (74% of runs). Cost cap: maxPropertiesPerZip, applied per ZIP or place. |
2: ZPIDs, property links or addresses (mode: "zpid") | A list of ZPIDs, property links (zillow.com/homedetails/…_zpid/) or street addresses (6503 Linda Ln, Austin, TX 78723), one per row | Enrichment-only — full property + agent + history per property, the whole list in one run. Filters and Walk/Photos enrichments ignored. |
3: Zillow URL (mode: "url") | One zillowUrl (search / sold / single-listing) | Whatever the URL shows on Zillow, enriched. Filters embedded in the URL. |
URL mode reads the page behind the link. It understands search-results URLs (containing searchQueryState=), city, ZIP and state browse URLs (zillow.com/austin-tx/, zillow.com/ocala-fl-34481/, zillow.com/nc/land/), keyword browse URLs (zillow.com/fl/fixer-upper_att/), and single-property pages — including address-only ones without a _zpid number. Two kinds of link cannot work: agent and company profile pages, which list no homes, and neighbourhoods inside a city, which Zillow will not search on their own. Both end the run at zero rows, charge nothing, and write a USER_MESSAGE record naming what to paste instead.
Each row carries the listing essentials (price, status, address, beds/baths, sqft, year built), the financial layer (Zestimate, rent Zestimate, HOA fee, property tax, last-sold, full price history), the agent contact layer (agent name, email, phone, license, brokerage), the property-detail layer (heating, cooling, appliances, view, fireplace, pool, garage, photos, schools), and the risk-and-neighbourhood layer: flood, wildfire, wind, heat and air-quality risk scores with the FEMA flood zone, the homes around the property, and how its price per square foot compares with theirs. The record layer adds the county tax record by year (taxHistory) and the rooms the listing names (rooms). The last two layers come from the same property page — no extra charge.
Zestimate history (from 13 November 2026) — switch on Add Zestimate history and every property also gets zestimateHistory: its monthly Zestimate for up to about ten years. A paid add-on, $0.02 per property that has a history, only when you turn it on.
ZIP-code mode adds 40+ filters that narrow the search before the actor pays for an enrichment. Tri-state filters (isAuction, isNewConstruction, isForSaleForeclosure) accept any / only / exclude, so you can flip a single field to filter foreclosures out without losing the rest of your filter set. Optional enrichments — Walk Score / Transit Score / Bike Score and full photo galleries — attach extra columns when you enable them.
📦 Output sample
One dataset row, ZIP mode, listing in Beverly Hills with full enrichment enabled:
{"zpid": "20533889","hdpUrl": "https://www.zillow.com/homedetails/123-Palm-Dr-Beverly-Hills-CA-90210/20533889_zpid/","price": 5500000,"status": "ForSale","homeType": "SINGLE_FAMILY","streetAddress": "123 Palm Dr","city": "Beverly Hills","state": "CA","zipcode": "90210","county": "Los Angeles County","neighborhood": "Beverly Hills Flats","latitude": 34.0901,"longitude": -118.4065,"bedrooms": 5,"bathrooms": 4,"bathroomsFull": 3,"bathroomsHalf": 2,"livingArea": 3500,"lotSize": "10,890 sqft","yearBuilt": 2010,"stories": 2,"architecturalStyle": "Contemporary","agentName": "Jane Doe","agentEmail": "jane@example-realty.com","agentEmailSource": "property_details","cellPhone": "310-555-0199","brokerName": "Luxury Real Estate Inc.","zestimate": 5600000,"rentZestimate": 18500,"pricePerSqft": 1571,"hoaFee": 500,"propertyTax": 68500,"priceChange": -100000,"datePriceChanged": "2026-04-12","hasPool": true,"hasGarage": true,"garageSpaces": 3,"hasBasement": false,"view": "City, Mountain(s)","heating": "Forced Air, Natural Gas","cooling": "Central Air","daysOnZillow": 14,"lastSoldDate": "2018-06-22","lastSoldPrice": 4250000,"lastTaxAssessedValue": 4400000,"priceHistory": [{"date": "2026-04-12", "price": 5500000, "event": "Price changed", "pricePerSquareFoot": 1571, "source": "Listing", "postingIsRental": false},{"date": "2018-06-22", "price": 4250000, "event": "Sold", "pricePerSquareFoot": 1214, "source": "Public Record", "postingIsRental": false}],"schools": [{"name": "Beverly Vista Elementary", "level": "Elementary", "rating": 9, "distance": 0.6}],"mainPhoto": "https://photos.zillowstatic.com/fp/abc123-uncropped_scaled_within_1536_1152.jpg","photos": ["https://photos.zillowstatic.com/fp/abc123-uncropped_scaled_within_1536_1152.jpg"],"walkScore": 95,"transitScore": 80,"bikeScore": 88,"listingType": "FSBA, openHouse","floodRiskScore": 2,"floodRiskLabel": "MINOR","femaFloodZone": "X_UNSHADED","fireRiskScore": 7,"fireRiskLabel": "SEVERE","windRiskScore": 3,"windRiskLabel": "MINOR","heatRiskScore": 8,"heatRiskLabel": "SEVERE","airRiskScore": 6,"airRiskLabel": "MAJOR","nearbyHomes": [{"zpid": "20533051", "address": "123 Example Dr, Beverly Hills, CA 90210", "homeType": "SINGLE_FAMILY", "homeStatus": "RECENTLY_SOLD", "price": 4900000, "priceKind": "sold", "bedrooms": 4, "bathrooms": 4, "livingArea": 3400, "pricePerSqft": 1441, "hdpUrl": "https://www.zillow.com/homedetails/123-Example-Dr-Beverly-Hills-CA-90210/20533051_zpid/"}],"compsMedianPricePerSqft": 1460,"compsCount": 6,"compsHomeTypeMatched": true,"pricePerSqftVsCompsPct": 7.6,"pricePerSqftVsCompsBasis": "price","taxHistory": [{"date": "2025-10-29", "taxPaid": 68120.4, "taxIncreaseRate": 0.021, "assessedValue": 4400000, "assessedValueIncreaseRate": 0.02}],"rooms": [{"roomType": "PrimaryBedroom", "level": "Second", "dimensions": "18'2\" x 16'0\"", "areaSqft": 291, "features": null, "description": null}],"enrichmentStatus": "enriched","whyNotEnriched": "N/A","input": null,"isValid": true,"invalidReason": null}
120 columns are documented in the .actor/dataset_schema.json — you can see every column's type, description, and example in the Apify Console's dataset view.
On the free plan, the results also show you what the search matched and did not return. The free plan enriches 15 properties per run. When a search matched more, the run adds up to 25 extra rows after your results — "enrichmentStatus": "not_enriched", the address, price, beds, baths and listing URL that the search already returned, and every column that costs money to look up left empty. whyNotEnriched names how many properties the search matched in total. Those rows are never charged, and a paid run never produces them.
⚡ Quick start
- Pick a mode: ZIP codes (discover), ZPIDs or property links (enrich a list you already have), or Zillow URL (browser-configured filters).
- Fill in the inputs for that mode. The other modes' inputs are ignored.
- (Optional) Toggle enrichments — Walk Score and Photos — for ZIP mode.
- Run the actor.
- Download in JSON / CSV / Excel / XML, or read the dataset programmatically (see § Programmatic / API use).
Minimal ZIP-mode input:
{"mode": "zip","zipCodes": ["94103"],"maxPropertiesPerZip": 5}
That's a single ZIP, capped at 5 properties — under $0.50 to test on the free plan.
🧭 When to use it
- Real-estate lead generation — build an agent contact list straight from live inventory: agent name, email, cell phone, license number and brokerage on every for-sale row in a ZIP.
- Valuation and comps — Zestimate, rent Zestimate, last-sold price and the full price-history array on each property, plus the homes around it and how its price per square foot compares with their median; switch
status_typeto sold listings to pull comparables for a neighbourhood. - Climate and insurance risk — flood, wildfire, wind, heat and air-quality risk on a 1–10 scale and the FEMA flood zone on every property, from the same lookup.
- Watching a market — schedule a ZIP or search-URL run with
skipDeliveredon and each run returns only listings that are new or changed (price, status) since the earlier runs; the unchanged ones are not charged again. - Rental and flip analysis — switch on
includeInvestorMetricsfor monthly cash flow, cap rate, cash-on-cash return, the 1% rule, after-repair value (ARV) and the 70% rule offer (MAO) on every property, calculated from the listing's own figures and your down payment, rate, expenses and repair budget. - Details for a list of addresses — paste street addresses from a spreadsheet into ZPID mode; each comes back as its property, or as a free row that says why it matched none.
- FSBO, foreclosure and auction sourcing — for-sale-by-owner, foreclosure, pre-foreclosure and auction listings come back as ordinary rows with contact and history (on an FSBO row the contact is the owner:
contactRole: "owner",ownerName,ownerPhone), and each is a tri-state filter you can include, isolate, or exclude without rebuilding the rest of the search. - Multi family, condo and lot/land search — narrow to the property type you actually want, with HOA cap, lot size, parking and year built applied by the search itself rather than after the download.
- Rental market research — rent range, pets, in-unit laundry, furnished, short-term lease and utilities-included filters, with rent Zestimate attached to every listing. Rental searches often return whole apartment buildings; switch on
expandBuildingUnitsto get one row per unit — unit number, rent, beds, baths, size, available-from date — not charged on top of the building. - School-quality filtering — school names and ratings ride along with each property, and a minimum rating narrows the search before the actor pays to enrich anything.
🎯 Example tasks
Ready-to-run examples — each opens a pre-configured task you can run in one click (no setup):
- Get full details for specific Zillow homes — Paste the Zillow IDs of the homes you care about and get price, beds, baths, square footage, agent contact, and Zestimate for each one.
- Turn any Zillow search link into a spreadsheet — Paste the link of a Zillow search you already set up and get every matching home as rows with price, beds, baths, agent contact, and Zestimate.
- Find foreclosed homes by ZIP code on Zillow — Pull foreclosure listings in any ZIP code with price, beds, baths, square footage, and agent contact as clean rows you can sort and filter.
- Find new construction homes by ZIP code — Pull newly built homes for sale in any ZIP code with price, beds, baths, square footage, agent contact, and Zestimate as structured rows.
- Scrape homes for sale by ZIP code on Zillow — Pull every for-sale home in any ZIP code with price, beds, baths, square footage, agent contact, and Zestimate as clean structured data.
- Find recently sold homes by ZIP for comps — Get recently sold properties in any ZIP code with sale price, sold date, beds, baths, and size — ideal for pricing comps and market research.
- Scrape homes for rent by ZIP code on Zillow — Export every rental listing in a ZIP code with monthly rent, beds, baths, square footage, and contact details — refreshed whenever you run it.
- Scrape real estate agent leads by ZIP code — Build a real estate agent contact list from active Zillow listings — agent name, email, phone, and brokerage for every for-sale home in a ZIP.
🛠 Input
The input schema is grouped into the following sections (open the Input tab in the Apify Console for the full UI):
- Operation Mode —
mode("zip"/"zpid"/"url"). - ZIP Mode Inputs —
zipCodes,maxPropertiesPerZip. - Search Filters (ZIP only) —
status_type,price_min/max,rentMinPrice/MaxPrice,beds_min/max,baths_min/max,doz,sort,keywords. - Home Type —
isSingleFamily,isTownhouse,isCondo,isMultiFamily,isApartment,isManufactured,isLotLand. - Listing Type & Status —
isForSaleByOwner,isForSaleByAgent,isNewConstruction,isAuction,isForSaleForeclosure,includeForeclosed,includePreForeclosure,isPendingUnderContract,isAcceptingBackupOffers. - Property Features —
sqft_min/max,lotSize_min/max,built_min/max,parkingSpots_min,hasGarage,hasPool,hasAirConditioning,isWaterfront,isBasementFinished,isBasementUnfinished,hoa_max. - View Filters —
isCityView,isMountainView,isParkView,isWaterView. - Tour Filters —
isOpenHousesOnly,is3dHome. - Rental-Only Filters — pet policies (
largeDogsAllowed,smallDogsAllowed,catsAllowed,noPets) + amenities (inUnitLaundry,furnished,hardwoodFloor,utilitiesIncluded,disabledAccess,shortTermLease,outdoorSpace,controlledAccess,highSpeedInternet,elevator,acceptsApplications,incomeRestricted,parkingAvailable). - School Filters —
schools,schoolsRating,includeUnratedSchools. - ZPID Mode Inputs —
zpids: ZPIDs, property links or street addresses, one per row. - URL Mode Inputs —
zillowUrl. - Only new or changed listings (ZIP and URL modes) —
skipDelivered("off", a number of days,"forever"). See § Only new or changed listings. - Enrichment Options (ZIP only) —
enrichWalkScore,enrichPhotos;expandBuildingUnits(ZIP and URL modes) adds one free row per unit of each apartment building found. - Zestimate history (all modes) —
includeZestimateHistory(off by default): monthly Zestimate of each property for up to about ten years, inzestimateHistory. Paid add-on from 13 November 2026 — see § Pricing. - Investor metrics (all modes) —
includeInvestorMetricsplus the optional assumptionsinvestorDownPaymentPct,investorInterestRatePct,investorLoanTermYears,investorPropertyTaxRatePct,investorInsuranceAnnual,investorOperatingExpensePct,investorRepairCost,investorMaoPct.
Highlights:
- Tri-state filters (
isAuction,isNewConstruction,isForSaleForeclosure) acceptany(no filter),only(require), orexclude(block). Flip one toexcludeto drop foreclosures without losing your other filter logic. - Filter and enrichment options are silently ignored in ZPID and URL modes — they're not errors, they just don't apply.
- Free plan caps: 15 properties / 20 ZIPs per run, 15 runs per month, agent emails masked. See § Free vs paid plan.
JSON snippets per mode:
{ "mode": "zip", "zipCodes": ["94103"], "status_type": "ForSale", "maxPropertiesPerZip": 50, "isAuction": "exclude", "hasPool": true }
{ "mode": "zpid", "zpids": ["20521978", "95547747"] }
{ "mode": "url", "zillowUrl": "https://www.zillow.com/homes/for_rent/?searchQueryState=..." }
💰 Pricing
Pay-per-event. You pay only when the actor finishes enriching a property — not for failed lookups, ZIPs that produced zero matches, or URL fetches that didn't yield a property.
| Event | Trigger | Free | Bronze | Silver | Gold | Platinum | Diamond |
|---|---|---|---|---|---|---|---|
apify-actor-start | Actor starts (1 event per GB of memory, minimum 1) | $0.00005 | $0.00005 | $0.00005 | $0.00005 | $0.00005 | $0.00005 |
PROPERTY_ENRICHED | Detailed property info fetched (price, agent contacts, price history, specs) | $0.08 | $0.07 | $0.06 | $0.05 | $0.05 | $0.05 |
ZESTIMATE_HISTORY | From 13 November 2026, only with Add Zestimate history on: monthly Zestimate history of one property (up to about ten years). Not charged when the property has no history | $0.02 | $0.02 | $0.02 | $0.02 | $0.02 | $0.02 |
Zestimate history is an add-on you switch on yourself (includeZestimateHistory, off by default). With it off, nothing changes. With it on, each property that has a history costs $0.02 on top of its property price — 100 properties on Diamond with history ≈ $5.00 + $2.00 = $7.00. Before 13 November 2026 the option is ignored: no history is looked up, the log says when it starts, and nothing extra is charged.
Cost math:
- 100 properties on Free ≈ 100 × $0.08 + actor-start ≈ $8.00
- 100 properties on Diamond ≈ 100 × $0.05 + actor-start ≈ $5.00
- 1,000 properties on Diamond ≈ 1,000 × $0.05 + actor-start ≈ $50.00
The actor self-bounds via budgetManager — it stops paying for new enrichments once the budget cap is reached, and records freeLimitBudget to the FREE_LIMITS_APPLIED storage record. To cap what a run can spend, use Apify's built-in Max total charge run option; API callers can also pass a maxBudgetUsd value in the input JSON.
🆓 Free vs paid plan
| Plan | Max properties / run | Max ZIPs / run | Runs / month | Agent emails | Per-event price |
|---|---|---|---|---|---|
| Free | 15 | 20 | 15 | Masked (j***@e***.com) | $0.08 / PROPERTY_ENRICHED |
| Paid (Bronze → Diamond) | Unlimited (budget-bounded) | Unlimited | Unlimited | Full (jane@example.com) | $0.07 → $0.05 / PROPERTY_ENRICHED |
The free monthly run allowance resets on the 1st of each calendar month; demo/test runs don't count against it. When a free-plan run hits a ceiling, the run's USER_MESSAGE record spells out exactly what was held back (how many matched properties weren't enriched, how many ZIP codes weren't searched, how many agent emails were masked).
Free-plan ceilings hit during a run are recorded to the FREE_LIMITS_APPLIED storage record so API consumers can switch on them without log-parsing.
Free runs that start at the same time are counted exactly. A free run you stop (abort) or that times out counts as one of the 15, like a finished run (resurrecting it does not count again); a run that fails, or whose maximum cost cannot pay for a single property, does not. If the run count cannot be checked, the free run stops before any work, charges nothing and says so — run it again in a minute.
While an unusually large number of new free accounts run this Actor at once, free runs from new accounts may be reduced to one property for a short while — the first ZIP code, link or ZPID, from the property's own page, without the agent-email lookups, Walk Score, photos, building units or Zestimate history. The run says so in its message and still counts as one of the 15. Paid plans are never affected.
🧪 Filter recipes
Single-family for-sale homes in 90210, exclude auctions, must have pool:
{"mode": "zip","zipCodes": ["90210"],"status_type": "ForSale","maxPropertiesPerZip": 50,"isSingleFamily": true,"isCondo": false,"isAuction": "exclude","hasPool": true}
New-construction-only in three Texas ZIPs:
{"mode": "zip","zipCodes": ["78701", "78704", "78745"],"status_type": "ForSale","isNewConstruction": "only","maxPropertiesPerZip": 100}
Furnished pet-friendly rentals in NYC with in-unit laundry:
{"mode": "zip","zipCodes": ["10001", "10011"],"status_type": "ForRent","rentMinPrice": 2500,"rentMaxPrice": 6000,"beds_min": 1,"largeDogsAllowed": true,"inUnitLaundry": true,"furnished": true}
Re-enrich a saved list of ZPIDs (ZPID mode):
{"mode": "zpid","zpids": ["20521978", "95547747", "12345678"]}
Details for a list of property links (ZPID mode):
{"mode": "zpid","zpids": ["https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/11026031_zpid/","https://www.zillow.com/homedetails/17-Cottonwood-Trl-Sparta-NJ-07871/39949685_zpid/"]}
Details for a list of street addresses (ZPID mode):
{"mode": "zpid","zpids": ["6503 Linda Ln, Austin, TX 78723","407 Glynn Dr, Birmingham, AL"]}
ZPIDs, links and addresses can be mixed. Write each address on its own row with the house number, the street and the state or ZIP code — the same street address exists in many towns. Addresses pasted from a spreadsheet are cleaned first: quotes, tabs, a ZIP+4 suffix, a leading "City of", doubled commas and spaces. Each address is checked against the property it finds: the house number, the street, and the state, ZIP and town you typed. An address that matches no single property is not charged — it comes back as a free row with isValid: false, an invalidReason (invalid_format, not_found or ambiguous) and, in whyNotEnriched, the reason and the closest match with its ZPID. Every row in ZPID mode has input — what you typed for it. A row that is none of the three is not looked up and not charged; it is listed in SKIPPED_ITEMS.
🔁 Only new or changed listings
For scheduled runs that watch a ZIP code or a Zillow search, set skipDelivered (ZIP and URL modes only) to a period — "7", "30", "90", "180", "365" days or "forever"; from the API any number of days works, e.g. "45". Off by default.
- A listing this actor already delivered to your Apify account for the same ZIP code with the same filters, or the same search URL, and whose status and price have not changed, is skipped: not looked up and not charged. The run takes the next listings instead, so
maxPropertiesPerZipstill counts new ones. - A listing delivered before whose status or price changed (a price cut, pending, sold) comes back and is charged as usual, with
"deliveryChange": "changed"; a listing never delivered has"new". - Listings that left the search are not listed — the run sees only what the search returns today.
- When everything the search found was delivered before, the run ends with 0 rows, nothing charged, and a
USER_MESSAGEthat says so. - The history is a key-value store named
zl-delivered-…in your own Storage, written by every ZIP and URL run from version 2.3.118 on (whether the option is on or not), so it is there the day you switch it on. Delete it to start over. A list of ZPIDs is never skipped — it is your own choice of homes. - Runs that overlap in time may still deliver the same listing twice. If the history cannot be read, the run searches nothing and charges nothing, and says so.
🔁 Resume / checkpoint
Long ZIP-mode runs are checkpointed automatically. If the run is aborted, paused, or hits the platform timeout, resurrecting the run picks up from the last checkpoint instead of restarting — you don't pay for already-enriched properties twice.
Resurrect from the Apify Console: open the aborted run → Resurrect button. The next run instance reads the actor's per-run KVS state and skips the already-processed ZIP codes. Live progress is mirrored to the status.html storage record while the run is active.
📡 Live status & storage records
The actor writes structured records to its key-value store on every run. Read them with Actor.getValue(<KEY>) from another actor, or fetch them via the REST API.
| Key | What it is | When |
|---|---|---|
RUN_SUMMARY | JSON object with search params, property counts, email-discovery rates, billing totals, and any free-tier limits hit during the run. ZIP-mode runs also carry zipScope — which ZIPs were searched directly, which had to be searched through their city (and how many rows were dropped unbilled), and which returned nothing. | End of every run. |
status.html | Auto-updating HTML status page with live scrape progress, budget, and ETA. Open from the Storage tab while the run is active. | Streaming throughout the run. |
FREE_LIMITS_APPLIED | Array<{id, message}> — every free-tier ceiling hit during the run (property cap, ZIP cap, budget exhaustion, email masking). Empty / omitted on paid runs. | End of every free-plan run. |
USER_MESSAGE | {id, title, body} — plain-language note about the run: zero-result diagnosis with the exact cause and fix, missing-input guidance on failed validation, free-plan ceilings that held back results (with real numbers), monthly-allowance notice, a note when a ZIP had to be searched through its city, demo-run explainer, or paid onboarding on the 1st/3rd paid run. | Whenever the run needs an explanation. |
SKIPPED_ITEMS | Per-item list of zpids / ZIPs / URLs skipped during the run, with reason and category (not_found / error / temporarily_unavailable / free_limit / duplicate / not_resolvable / test_run_cap / not_searched). Useful to re-run the error cohort. | End of every run. |
🤖 Programmatic / API use
Start a run from your own code via the Apify REST API:
TOKEN="<your-apify-token>"ID=YwkoMBHoFxCLI4gpM# Start a synchronous run + read datasetcurl -s -X POST "https://api.apify.com/v2/acts/$ID/run-sync-get-dataset-items?token=$TOKEN&format=json" \-H 'Content-Type: application/json' \-d '{"mode":"zip","zipCodes":["94103"],"maxPropertiesPerZip":5}'
Read the run-end summary from another script:
RUN_ID="<run-id-from-the-launch-call>"curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID/key-value-store/records/RUN_SUMMARY?token=$TOKEN"
The actor is also available via the Apify MCP server (https://mcp.apify.com) — any MCP-aware client (Claude Desktop, Cursor, etc.) can call it as a tool. Input + output schemas in this repo are the source of truth the MCP client reads to build the call signature.
❓ FAQ
Is it legal to scrape Zillow?
The actor extracts only publicly available property listing data; private user data is never touched. Listings include personal information for licensed agents (a public role), which can fall under GDPR and similar regimes — make sure you have a legitimate basis to process it. If unsure, consult legal counsel.
What's the difference between ZIP, ZPID, and URL modes?
- ZIP — discovery from scratch, full filter control.
- ZPID — enrichment of properties you already know: paste their ZPIDs, property links or street addresses, a whole list in one run.
- URL — Zillow's own UI does the filtering; you paste the resulting URL.
ZIP mode is the only mode where input-schema filters and enrichment toggles take effect.
Can I get agent emails and phone numbers?
Yes. agentEmail, cellPhone, agentLicenseNumber, brokerPhoneNumber ship in the output when Zillow exposes them. The agentEmailSource column tells you which lookup path produced the email (property_details → from the Zillow listing page; agent_profile_direct → from the agent's Zillow profile; agent_search_fallback → name-search match).
On the free plan emails are masked (j***@e***.com); upgrade to a paid plan for the unmasked value.
How do I get a Zillow URL for URL mode?
Configure your filters at zillow.com in the browser, then copy the full address-bar URL (it includes a long searchQueryState=... query string) and paste it into zillowUrl.
Why are some fields null?
Zillow doesn't always publish every field for every listing. Common reasons:
- The data isn't in Zillow's feed for this property.
- An enrichment toggle was off (
walkScore/transitScore/bikeScoreneedenrichWalkScore: true; fullphotosneedsenrichPhotos: true). - The listing is incomplete (e.g. an FSBO owner who published no phone, or agent details on an FSBO listing — there the contact is the owner, in
ownerName/ownerPhone).
Missing values are returned as null, not the string "N/A".
Where do the climate risks and the nearby-home comparison come from?
From the property's own Zillow page, read in the same lookup — they cost nothing extra. The flood, wildfire, wind, heat and air-quality columns are the risk scores (1–10) and labels Zillow shows in the page's climate-risk section, with the FEMA flood zone; about 95% of properties carry them, and the rest have null. nearbyHomes lists the homes around the property that the page shows (usually eight), each with what its price is (priceKind: Zestimate, sale price, asking price or rent). These are neighbours, not a hand-picked set of comparable sales.
compsMedianPricePerSqft and pricePerSqftVsCompsPct are calculated by this actor, not Zillow figures: the median price per square foot of the nearby homes whose price is a value (rents are left out), using homes of the same type when at least three are, and how far this property sits above or below it, in percent. The property is compared by its price only when it is for sale, pending or sold; a foreclosed or off-market home's page price is often its tax-assessed value, so it is compared by its Zestimate, or not at all (pricePerSqftVsCompsBasis: no_sale_price). No median is given when fewer than three nearby homes have a value.
Can I get the units of an apartment building?
Yes, in ZIP and URL modes. A rental search often returns an apartment building as one row (homeType: "APARTMENT_BUILDING"). With expandBuildingUnits on, the actor reads the building's page once and adds one row per unit after the building's row — listingType: "BUILDING_UNIT", enrichmentStatus: "building_unit", with unitNumber, floorPlanName, rent (price), beds, baths, square feet (livingArea), availableFrom and buildingZpid pointing to the building. A building that lists floor plans without units gets one row per floor plan. Unit rows are not charged: the building is charged once, as one property, exactly as without the option. Up to 300 unit rows per building.
How are the investor metrics calculated?
Only when you switch on includeInvestorMetrics, and by this actor, not by Zillow — an estimate from the listing's own figures, not financial advice. No extra charge.
- Purchase price: the asking or sale price of a home for sale, pending or sold; otherwise the Zestimate. A foreclosed or off-market home's page price is often its tax-assessed value, so it is not used — such a home without a Zestimate gets no cash flow.
- Rent: the rent Zestimate, or the asking rent of a rental listing.
- Mortgage: the purchase price minus your down payment (default 20%), at your rate — or the 30-year fixed rate the property's Zillow page shows, 7% when it shows none — over your term (default 30 years).
- Expenses: property tax (the page's tax rate, else the listing's annual tax, else 1.1%), insurance (the page's estimate, else 0.35% of the price), HOA, and operating expenses for vacancy, repairs, management and reserves (default 30% of the rent).
- Cash flow = rent − mortgage − expenses. Cap rate = a year of rent minus expenses (before the mortgage) ÷ price. Cash-on-cash = a year of cash flow ÷ (down payment + repair budget). Rent to price = rent ÷ price (the 1% rule).
- ARV (after-repair value) = the nearby homes' median $/sq ft × this home's living area, or the Zestimate when there is no median. MAO = ARV × 70% (or your
investorMaoPct) − your repair budget.
Every figure used, and where it came from, is in investorAssumptions on the row — set any of them on the input and run again.
Can I schedule runs?
Yes — use Apify's built-in Schedules tab on the actor's detail page to trigger the run hourly / daily / on a cron. Each scheduled run is its own paid run.
What happens when a run is aborted mid-way?
The actor checkpoints progress per ZIP. Resurrecting the aborted run resumes from the last checkpoint (see § Resume / checkpoint). The status.html storage record reflects live progress while the run is active.
Why did my run return 0 properties?
The usual causes, in order of frequency:
- The search matched nothing — a PO-box or business-district ZIP (no residential listings by design), or a Status Type mismatch (e.g. expecting rentals while
status_typeisForSale). - The URL shape wasn't recognised (URL mode) — re-copy the address-bar URL from zillow.com with your filters applied, or switch to ZIP mode.
- The listings found couldn't be enriched — delisted or stale ZPIDs; take fresh ones from current zillow.com listing pages. For an address, its row with
isValid: falsesays why it matched no property. - Zillow data could not be reached in time — when many searches run at the same moment, a run waits its turn; whatever it still could not finish before its timeout is listed in
SKIPPED_ITEMSundertemporarily_unavailable, is not charged, and usually goes through when you run it again a few minutes later.
Every zero-result run writes a USER_MESSAGE storage record with the exact cause for that run and the top fix. A quick sanity check that always returns data: ZIP mode, ZIP code 90210, no filters.
Do I pay for runs that return nothing?
No. Properties are billed only when enrichment succeeds — failed lookups, empty ZIPs, unrecognised URLs, zero-result searches, and searches or lookups that could not be reached in time cost nothing beyond the fractional actor-start event.
Do I need a Zillow login, cookies, or a proxy?
No. The actor needs no Zillow account, no cookies, and no proxy setup — paste your ZIPs / ZPIDs / URL and run. There is nothing to configure or rotate.
Can I search a whole city instead of ZIP codes?
Yes — type the place with its state into zipCodes: Phoenix, AZ, Austin TX, Maricopa County, AZ or a neighborhood like Downtown, Phoenix, AZ. It is searched the way Zillow's own search box does, and you can mix places and ZIP codes in one list. A name without its state (Phoenix) is not searched and not charged — there are dozens of towns with the same name. A place Zillow does not recognise ends the same way, named in SKIPPED_ITEMS.
How do I get the owner's contact on for-sale-by-owner listings?
Turn on Owner Posted (FSBO) and turn off Agent Listed. You then get only homes the owner posted: Zillow's by-owner search also returns bank-owned and new-construction listings (in Phoenix, 34 of 41), and those are dropped before enrichment, so they are never charged. Each FSBO row carries contactRole: "owner" with the owner's name and phone in ownerName and ownerPhone, as the listing shows them; agent-listed rows carry contactRole: "listing_agent". An owner who published no phone has ownerPhone: null.
Can I scrape many ZIP codes in bulk?
Yes — zipCodes accepts a list, and paid plans have no per-run ZIP cap (free plan: 20 per run). For very large sweeps, split ZIPs across scheduled runs so each run stays comfortably inside its time box, or drive batches via the API (see § Programmatic / API use).
How do I get more than 15 properties per run?
The 15-property cap is the free plan's per-run ceiling. When it bites, the run's USER_MESSAGE record reports exactly how many matching properties were held back. Any paid Apify plan removes the cap — re-run the same input afterwards and the full result set is delivered.
🔗 Related actors
| You want to scrape Zillow by… | Use this actor |
|---|---|
| Multi-mode (ZIP + ZPID + URL) — full flexibility | This actor |
| ZIP code only — simpler input, single-mode | zillow-zip-search |
| Search URL — paste any Zillow search page | zillow-url-search |
| MCP server — connect Claude Desktop / Cursor / ChatGPT to Zillow tools | zillow-mcp-server |
More lead-generation actors from the same author:
| You want leads from… | Use this actor |
|---|---|
| LinkedIn job postings — salary data + hiring contacts | linkedin-jobs-scraper |
| Instagram profiles — emails, engagement, 38 fields per profile | instagram-profile-scraper |
🛟 Support & feedback
- Bug or feature request — file an issue from the actor's Issues tab on the Apify Console.
- Custom solutions / enterprise needs — reach out via the actor's Apify Store page.
⚖️ Disclaimer
This actor is a tool for automated retrieval of publicly available data. You're responsible for using it in compliance with Zillow's terms of service, your jurisdiction's data-protection laws (GDPR, CCPA, etc.), and any third-party licenses. The author makes no representation about the accuracy or fitness of Zillow's underlying data for any purpose.