Zillow Sold Data API: Recently Sold Homes, Sale Dates, and Comps in JSON

August 19, 2026 · 7 min read

Sold data is where property analysis actually starts. Comps for a CMA, ARV for a flip, collateral checks for a lender, assessment appeals, portfolio marks — every one of them begins with the same three questions: what did this home last sell for, when, and what happened to its price along the way?

Zillow has the most complete consumer-facing answer to those questions. It also has no public API to ask them with — and here is the part that catches almost everyone who tries to scrape it: on off-market homes, the sale date is missing from the page data most scrapers read. This guide covers what sold data you can get programmatically, how to get it in one API call, and the gotchas that separate a working comps pipeline from a broken one.

What sold data can you actually get?

For any US property — by street address, ZPID, or Zillow URL — APIllow returns the full sales record alongside 50+ other fields:

Field What it is Example
last_sold_price Most recent sale price 289000
last_sold_date Most recent sale date (ISO) "2024-06-14"
price_history Every listing, price change, pending, and sale event date, event, price, source
tax_history Assessed value and tax paid, by year {"year": 2025, ...}
zestimate Zillow's valuation — populated on sold and off-market homes 312400

That last row matters more than it looks: Zillow suppresses the Zestimate on most active listings, but sold and off-market homes return a populated Zestimate — so a sold-data pipeline gets current valuations for free. The full quirk is documented in our Zestimate API guide.

One request, full sales history

# Get sold data for a property curl -X POST https://api.apillow.co/v1/properties \ -H "x-api-key: YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"addresses": ["1874 Bromton Dr, Lyndhurst, OH 44124"]}'

The response carries the whole sales record:

{ "address": "1874 Bromton Dr, Lyndhurst, OH 44124", "home_status": "SOLD", "last_sold_price": 289000, "last_sold_date": "2024-06-14", "zestimate": 312400, "price_history": [ {"date": "2024-06-14", "event": "Sold", "price": 289000, "source": "Public Record"}, {"date": "2024-05-02", "event": "Pending sale", "price": 285000, "source": "MLS"}, {"date": "2024-04-18", "event": "Listed for sale", "price": 285000, "source": "MLS"}, {"date": "2009-08-21", "event": "Sold", "price": 176500, "source": "Public Record"} ], "tax_history": [...] }

Price history routinely reaches back decades because it merges MLS events with public-record sales — you get the 2009 sale next to the 2024 one, with the event type and source on every row.

Why most scrapers miss the sale date

If you have ever scraped a Zillow property page and wondered why last_sold_date came back empty on an off-market home, it is not your parser. Zillow omits the sale date from the standard page payload on off-market properties — the page shows "Sold" but the machine-readable data behind it doesn't say when. The date lives in a separate internal data path that page-level scrapers never touch.

APIllow runs a dedicated enrichment step against that second data path for every off-market property. In production, that recovers a last_sold_date for roughly 7 in 10 off-market homes and a full price_history for roughly 8 in 10 — numbers we measure continuously against live traffic, because they are exactly the fields our comps and valuation customers depend on. Most DIY scrapers and off-the-shelf marketplace actors report near-zero for the same fields, because the listing page alone simply doesn't contain them.

Building comps from sold data

A comps workflow is a batch workflow: take a candidate list of nearby, similar properties, pull the sold record for each, filter to recent arm's-length sales, and compute price per square foot. The API accepts up to 1,000 properties per request:

import requests, time API = "https://api.apillow.co/v1" HEADERS = {"x-api-key": "YOUR_KEY"} # Candidate comp addresses (county records, prior sales, your CRM...) candidates = ["1868 Bromton Dr, Lyndhurst, OH 44124", "..."] job = requests.post(f"{API}/properties", headers=HEADERS, json={"addresses": candidates}).json() # Poll for results while (r := requests.get(f"{API}/results/{job['job_id']}", headers=HEADERS).json())["status"] != "complete": time.sleep(2) props = [item["property"] for item in r["results"]] comps = [p for p in props if (p.get("last_sold_date") or "") >= "2026-02-01"] # sales in the last 6 months for c in comps: print(c["address"], c["last_sold_price"], c["last_sold_price"] / c["living_area"])

The same flow feeds a spreadsheet instead of a script if that's where your analysis lives — the Excel/CSV export guide covers it, and the Python tutorial walks the polling pattern step by step.

Sales data by ZIP code: what works and what doesn't

One honest limitation to design around. The API also accepts ZIP-code queries — but a ZIP search returns active for-sale inventory, the same thing a Zillow search page shows by default. It is not a "recently sold homes in 44124" feed. To pull sold data, request specific properties: a comp candidate list, a street, a farm area's addresses, a portfolio. If your candidate list is thin, a practical pattern is to seed it from the active-listing ZIP search (neighbors of homes for sale are usually good comp candidates) and then pull each candidate's sold record individually.

Where else can you get sold data?

Source Coverage The catch
County records Authoritative, free 3,000+ counties, inconsistent formats, weeks of lag, no listing context
MLS / Bridge Interactive Deep, licensed Application, approval, and typically MLS affiliation — months, not minutes
Marketplace scraper actors Varies per actor Page-level scraping — usually missing the sale date on off-market homes
APIllow Any US property, JSON Free tier of 50 requests/month; ~$0.002–$0.003 per property on paid plans

The full cost math, including how per-property pricing compares to enterprise data contracts, is in the pricing comparison. And if you landed here wondering what happened to Zillow's official API in the first place, that story is in Does Zillow have an API in 2026?

Pull your first sold record now

Free tier, no credit card. Last sold price, sale date, and full price history in one POST request.

Get API Key

Related reading

Final takeaway

There is no public Zillow API for sold homes, but sold data is still one API call away — last_sold_price, last_sold_date, and decades of price_history per property. Build around the two quirks that matter: the sale date requires enrichment beyond the listing page (we handle that), and ZIP search returns active inventory, so comps pipelines should request specific properties.