๐ŸŽ‰ Premium Proxies ยท 3-Day Free TrialClaim Now โ†’
Guides

How to Scrape Zillow Data: Listings, Prices, Zestimate

Learn how to scrape Zillow data: pull listings, prices, the Zestimate, and property details from Zillow's hidden JSON API, and beat its anti-bot defenses.

S SparkProxy 0 26 min read
Share
How to Scrape Zillow Data: Listings, Prices, Zestimate

To scrape Zillow data at any real scale, the hard part isn't parsing HTML. It's two things most guides skip. Zillow ships its listings, prices, the Zestimate, and full property details as JSON buried in the page and behind an undocumented search endpoint, and it runs one of the strictest bot walls on the public web. This guide stays on the keyboard. You'll see exactly where Zillow keeps each field, how to hit its hidden search API for clean JSON instead of scraping cards, how to beat the 500-result cap, how to get past the "Press and Hold" challenge, and working Python against SparkProxy's Scraping API. It's the Zillow-specific companion to our general guide on scraping real estate listings, so here we go deep on what makes Zillow different.

What you'll build

  • A field map for price, Zestimate, beds, baths, sqft, price history, tax history, and location
  • A parser that reads Zillow's embedded __NEXT_DATA__ JSON instead of fighting selectors
  • Direct calls to Zillow's GetSearchPageState endpoint that return listing JSON, no HTML
  • A price-band tiler that beats Zillow's 500-result search cap
  • An anti-bot escalation ladder so a "Press and Hold" wall doesn't end the run

Scrape responsibly: public data, ToS, and the Zestimate caveat

Set the boundary before any code. Scraping listing data that any anonymous visitor can see on a public Zillow page sits on defensible ground, and US courts have repeatedly declined to treat access to public web pages as unauthorized access. That is not blanket permission. A few rules keep you on the right side:

  • Public pages only. Don't scrape anything behind a login, an agent portal, or Zillow's Premier Agent tooling. Bypassing authentication is a different legal category.
  • Read robots.txt and the ToS as signals. Zillow's terms prohibit automated collection, and its data feeds are governed by MLS and RESO licensing. That rarely creates criminal exposure for public data, but it tells you the site will fight you technically, so behave: go slow, keep a small footprint.
  • The Zestimate is an estimate, not a fact. It's Zillow's proprietary valuation model, with a published median error that varies by market. Store it as a signal, label it clearly, and never present it as an appraisal or a sale price.
  • Don't collect agent PII in bulk or rebuild the portal. Using price and inventory data for internal market analysis is a very different risk profile from harvesting agent contact details or republishing MLS-sourced listings as a competing site.

The rest of this article assumes you're collecting public listing data for internal analysis. For the broader legal framework on MLS licensing and Fair Housing when scraped data feeds automated decisions, see the compliance section of our real estate data aggregation guide. For anything you plan to publish or resell, get legal sign-off first.


What a Zillow listing exposes

Decide your schema up front. Retrofitting a field after you've scraped 200,000 pages means re-scraping. Here's the field reference most Zillow property data pipelines converge on, with the type and the gotcha that bites people.

FieldData typeExample valueNotes
`zpid`integer`48749425`Zillow's stable property id. It's in the URL (`/homedetails/.../48749425_zpid/`) and every JSON blob. Your primary key.
`price`integer`459000`Current list price. `0` or missing on off-market homes.
`zestimate`integer`472100`Zillow's estimated market value. Present even on off-market homes. Label it as an estimate.
`rentZestimate`integer`2650`Estimated monthly rent. Useful for cap-rate math.
`bedrooms` / `bathrooms`int / float`3` / `2.5`Keep the decimal on baths. Half baths matter.
`livingArea`integer`1840`Interior sqft. Do not confuse with `lotSize`.
`homeType`string`SINGLE_FAMILY``SINGLE_FAMILY`, `CONDO`, `TOWNHOUSE`, `MANUFACTURED`, `LOT`. Already normalized by Zillow.
`homeStatus`string`FOR_SALE``FOR_SALE`, `PENDING`, `SOLD`, `OTHER` (off-market). Drives whether the row is current.
`yearBuilt`integer`1998`Missing on some land and new construction.
`priceHistory`array`[{date, price, event}]`Sale, listing, and price-cut events. One of the most valuable fields for demand signals.
`taxHistory`array`[{time, taxPaid, value}]`Annual assessed value and tax paid. Great for valuation models.
`resoFacts`object`{lotSize, heating, ...}`The RESO-standard fact bag: lot size, HVAC, parking, HOA, appliances, flooring, and more.
`latitude` / `longitude`float`30.242, -97.769`Exact coordinates, straight from the JSON. No geocoding needed.
`schools`array`[{name, rating, level}]`Assigned schools with GreatSchools-style ratings.

Two of these carry more weight than the rest. Price history plus tax history together tell you seller motivation and a defensible value anchor, which the current list price alone never will. A home with two price cuts over 60 days and an assessed value 15% under asking is a different negotiation than a fresh listing at assessed value, even at the same sticker.


Free trial

Scraping at scale? Skip the blocks.

Fast, unblockable datacentre proxies with unlimited bandwidth.

Where Zillow keeps its data: __NEXT_DATA__ and the GraphQL cache

Here's the thing that trips up first-timers. A Zillow home detail page is a Next.js React app. The visible HTML is a shell, and the real fields (price, Zestimate, resoFacts, coordinates) arrive as a large JSON object embedded in a