Zillow Search Scraper With Property Enrichment
Pricing
$19.99/month + usage
Zillow Search Scraper With Property Enrichment
Automate Zillow search scraping with reliable filtering for price, home type, beds, baths, and neighborhood. Retrieve complete listing details, photos, and agent insights. Perfect for building market datasets, powering dashboards, or enriching real estate intelligence tools.
Pricing
$19.99/month + usage
Rating
0.0
(0)
Developer
API Empire
Maintained by CommunityActor stats
1
Bookmarked
4
Total users
0
Monthly active users
2 days ago
Last modified
Categories
Share
π‘ Zillow Search Scraper
Scrape Zillow property listings at scale from search URLs, locations, or ZIP codes. This Apify actor uses Zillow's internal search API with a dynamic map-zoom engine that subdivides dense areas to beat Zillow's ~820-results-per-query cap, lifts clean columns out of Zillow's raw data, computes derived real-estate metrics, and supports price / beds / baths / sqft / home-type / status filters. An optional detail-enrichment mode adds price history, tax history, agent contact, and schools.
Keywords: zillow scraper, zillow search scraper, real estate data, property listings, zillow api, home prices, zestimate, rent zestimate, real estate lead generation, housing market data, zillow zpid, days on market, price cut, price per sqft, property tax data.
Key features
- Beats the ~820 cap β the dynamic-zoom engine reads Zillow's
totalResultCount, recursively subdivides the map bounds into quadrants, paginates each tile, and deduplicates by ZPID across every tile and every URL. - Clean lifted columns β
homeType,homeStatus,rentZestimate,daysOnZillow,lotAreaValue/lotAreaUnit,taxAssessedValue/taxAssessedYear,yearBuilt,priceReduction/priceChange/datePriceChanged,brokerName, and open-house / days-on-Zillow text β all lifted from Zillow's nestedhdpDatablob into flat, usable fields. - Honest data (no fake zeros) β a listing with no price ("Contact for price") emits
unformattedPrice: null(never0), andshouldShowRequestOnPricestays as the honest signal. Missingzestimateisnull, not0. Zestimate is always labeled as Zillow's estimate, never a sale price. - Derived metrics β
pricePerSqft,priceVsZestimateDelta+priceVsZestimatePct,priceCutFlag,daysOnMarketBucket, plusscrapedAt. - Filters β
status(for sale / for rent / sold),minPrice/maxPrice,minBeds/maxBeds,minBaths,minSqft/maxSqft,homeType,maxDaysOnMarket,keywordsβ injected into Zillow'ssearchQueryState.filterState. - Location / ZIP resolver β bare inputs like
dallas-txor90210are resolved into a real Zillow map search (with map bounds), not a naive keyword URL. - Photos β
photoCountand up to N hi-resphotoUrlsbuilt from Zillow's photo keys. - Honest anti-bot handling β soft-block detection flags a
200that actually carries a captcha/HTML challenge (so it is not silently parsed as "empty"), and the proxy chain escalates honestly from direct to Apify Residential. - Optional detail enrichment β opt-in per-property
priceHistory,taxHistory, agent/broker contact, schools, and description, emitted as separate child rows.
Input
| Field | Type | Description |
|---|---|---|
searchUrls (required) | array | Full Zillow search URLs (with searchQueryState) or bare locations / ZIP codes. |
extractionMethod | string | PAGINATION_WITH_DYNAMIC_ZOOM_INCREASE (default, beats the cap), PAGINATION_WITHOUT_ZOOMING_IN (HTML, ~820), MAP_MARKERS (~500). |
maxItems | integer | Global cap across all URLs (deduped by ZPID). 0 = as many as possible. Default 10. |
status | string | all (default), forSale, forRent, sold. |
minPrice / maxPrice | integer | Price range (USD). |
minBeds / maxBeds / minBaths | integer | Bed/bath filters. |
minSqft / maxSqft | integer | Living-area range. |
homeType | string | all, houses, condos, townhomes, multiFamily, apartments, manufactured, lotsLand. |
maxDaysOnMarket | integer | Newest-listing filter (mapped to Zillow's nearest bucket). |
keywords | string | Free-text keyword filter passed to Zillow. |
rawData | boolean | Also include the raw hdpData blob + full carousel. Default off. |
maxPhotos | integer | Hi-res photo URLs per listing. Default 5. |
enableDetailEnrichment | boolean | Opt-in detail pages. Default off. |
detailUrlsOrZpids | array | ZPIDs / property URLs to enrich (used only when enrichment is on). |
proxyConfiguration | object | Residential recommended (Zillow blocks datacenter IPs). |
Input example
{"searchUrls": ["https://www.zillow.com/dallas-tx/?searchQueryState=%7B...%7D"],"extractionMethod": "PAGINATION_WITH_DYNAMIC_ZOOM_INCREASE","maxItems": 100,"status": "forSale","minPrice": 200000,"maxPrice": 750000,"minBeds": 3,"homeType": "houses","proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Output
Each listing row includes (among others):
{"type": "listing","zpid": "26822756","detailUrl": "https://www.zillow.com/homedetails/...","unformattedPrice": 525000,"price": "$525,000","shouldShowRequestOnPrice": false,"addressStreet": "3810 Hawthorne Ave","addressCity": "Dallas","addressState": "TX","addressZipcode": "75219","beds": 3, "baths": 2, "area": 2100,"homeType": "SINGLE_FAMILY","homeStatus": "FOR_SALE","yearBuilt": 1998,"zestimate": 531000,"rentZestimate": 3200,"taxAssessedValue": 480000,"daysOnZillow": 5,"daysOnMarketBucket": "0-7 days (new)","priceCutFlag": false,"pricePerSqft": 250.0,"priceVsZestimateDelta": -6000,"priceVsZestimatePct": -1.13,"brokerName": "Some Realty","photoCount": 34,"photoUrls": ["https://photos.zillowstatic.com/fp/...jpg"],"latLong": { "latitude": 32.82, "longitude": -96.81 },"scrapedAt": "2026-07-03T00:00:00Z"}
Fields that are genuinely unavailable are emitted as null β never a fabricated 0.
Field coverage note (honest): Zillow's search API returns homeType, homeStatus, daysOnZillow, rentZestimate, taxAssessedValue, lotArea*, zestimate and price/bed/bath/area with high coverage. It does not return yearBuilt, priceReduction, or brokerName in the search feed (Zillow only exposes those on the property page), so in a pure search run they are null β they are populated when you use Detail Enrichment. priceReduction/priceCutFlag populate only on listings that actually had a price cut.
Detail-enrichment rows (opt-in)
When enableDetailEnrichment is on, each ZPID/URL produces a child row with type: "detail", isDetail: true, and priceHistory, taxHistory, schools, agentName/agentPhoneNumber/agentEmail, brokerName, and description. Absent fields are null. These rows are mirrored to a per-run zillow-details-<runId> dataset and billed under the separate detail_result event.
How to use
- Open the actor in the Apify Console.
- Paste one or more Zillow search URLs (or locations / ZIP codes).
- Optionally set filters (price, beds, home type, status).
- Set
maxItemsand keepproxyConfigurationon Residential. - Run, then open the OUTPUT tab to view / export (JSON, CSV, Excel).
Notes on extraction methods
- Dynamic zoom (recommended) subdivides the map to collect more than the ~820 listings Zillow returns per single query, deduping by ZPID.
- Pagination without zooming parses Zillow's HTML pages via
__NEXT_DATA__(capped ~820). - Map markers paginates a single query (capped ~500).
Compliance
- Data is collected only from publicly available Zillow pages.
- No private, password-protected, or personal-account data is accessed.
- The user is responsible for legal compliance (privacy, data-protection, and applicable terms).