A property's price history is its negotiation file. Three price cuts in ninety days says more about the seller than any listing description. A purchase two years ago at 30% below today's ask tells you exactly where the anchor is. A de-list-and-relist pattern tells you the days-on-market counter has been reset — and by how much.
Zillow displays this timeline on every property page, but there is no official API for it. This guide shows how to pull the full price and tax history for any US property as JSON — what the events look like, what they mean, and how to build price-cut detection on top of them.
What a price history payload looks like
Request any property by address, ZPID, or Zillow URL:
The price_history array comes back newest-first, one entry per event:
Two things to notice. The timeline reaches back decades — MLS events merged with public-record sales. And every event carries its source, so you can weight an MLS-sourced sale differently from a county-record one.
Reading the events
| Event | What it means | What it signals |
|---|---|---|
Listed for sale |
Property hit the market at this ask | Start of the days-on-market clock |
Price change |
Ask moved while listed | Cuts = seller motivation; the gap and cadence matter |
Pending sale |
Offer accepted | Ask-at-pending vs final sold price = negotiation room |
Listing removed |
De-listed without a sale | Followed by a new listing = DOM reset; real history persists here |
Sold |
Sale closed | The comp: pair with last_sold_date for recency filters |
Example: detect motivated sellers with a price-cut scan
The classic use case: scan a batch of properties and rank by how aggressively the ask has dropped.
Run it over a ZIP's active inventory (a ZIP-code query returns exactly that — the for-sale listings) and sort descending: the top of the list is your call sheet. The Python tutorial covers the batch-and-poll pattern this plugs into.
Tax history rides along
The tax_history array — assessed value and tax paid, by year — is in the same response, no extra call. The two workhorse uses: assessment appeals (assessed value climbing faster than the price events justify) and expense modeling for rental underwriting, where last year's actual tax paid beats any estimate. Divide last_sold_price by the assessment in the sale year and you get the county's assessment ratio — useful for sanity-checking any valuation in the area.
The off-market catch (and why scrapers come back empty)
If you have tried to scrape price history yourself, you have probably seen it work on active listings and return nothing on off-market homes. That is Zillow's doing, not yours: on off-market properties, most of the sales record is omitted from the standard page payload. It lives in a separate internal data path. APIllow enriches every off-market property against that path and recovers a full price_history for roughly 8 in 10 off-market homes — the mechanics are covered in the sold data API guide, this article's sibling.
Pull a price history now
Free tier, no credit card. Decades of events for any US property, one POST request.
Get API KeyRelated reading
- Zillow sold data API: sale dates, price history, and comps
- Zestimate API: how to get Zestimates programmatically
- Zillow API Python tutorial
- Export Zillow data to Excel or CSV
Final takeaway
Price history is the highest-signal-per-byte field in property data, and it is one API call away: every listing, cut, pending, and sale — plus tax history — in a single JSON response. Just know the one asymmetry: active listings carry their history in plain sight, while off-market homes need the enrichment step we run for you.