Zillow Search Scraper: Price History Tracking avatar

Zillow Search Scraper: Price History Tracking

Pricing

$19.99/month + usage

Go to Apify Store
Zillow Search Scraper: Price History Tracking

Zillow Search Scraper: Price History Tracking

Scrape Zillow search results at scale with precise filtering. Extract listings, prices, addresses, home details, photos, and agent data. Ideal for market research, lead generation, pricing analysis, and investment insights. Export clean structured data in JSON, CSV, or Excel.

Pricing

$19.99/month + usage

Rating

0.0

(0)

Developer

Scraper Engine

Scraper Engine

Maintained by Community

Actor stats

1

Bookmarked

3

Total users

1

Monthly active users

4 days ago

Last modified

Share

Zillow Price History Scraper — Listings, Price Drops & Tax History

Zillow Price History Scraper extracts property search listings from any Zillow URL, ZIP code, or city, returning price, address, beds/baths, and — when enabled — each listing's full priceHistory and taxHistory timeline pulled straight from the property detail page. Results ship as structured JSON with a stable schema across runs, no HTML parsing required. A built-in price-drop filter (minPriceReductionEvents) isolates motivated-seller listings automatically. Run it on Apify to pull your first price-history dataset.

What is Zillow Price History Scraper?

Zillow Price History Scraper is an Apify Actor that runs a Zillow search (by URL, ZIP code, or city keyword) and returns each matching property as a structured JSON record, optionally enriched with the property's full price-history and tax-assessment timeline fetched from its detail page. No Zillow account, login, or API key is required anywhere in the code path — it reads only the public search and listing pages Zillow serves to any visitor. It's built for real estate investors, market analysts, and developers who need machine-readable listing and price-trend data without maintaining their own scraper.

What Zillow listing price data is publicly available to scrape?

Zillow publishes listing details, price history, and tax history on its property pages without requiring login.

Data CategoryPublic (no login)Restricted (account)
Price, address, beds/baths, statusYes
Price-history eventsYes, on most listingsNewer/off-market listings may show thin history
Tax-assessment historyYes
Zestimate / rent estimateYes
Detail-page photosYes
Saving/favoriting a listingNoSigned-in account required
Contacting the listing agentNoLogin + contact form required

Zillow Price History Scraper only returns publicly visible data — what any visitor sees. Nothing behind a login wall.

What data can I extract with Zillow Price History Scraper?

Every returned row combines the listing's search-page identity fields, its core quantitative metrics, and — when the history options are turned on — its full price and tax timeline.

Listing identity & location

Field NameDescription
zpidZillow's unique property ID
idSame value as zpid, kept for compatibility
addressFull address string
addressStreetStreet address only
addressCityCity
addressStateState abbreviation
addressZipcodeZIP code
detailUrlCanonical Zillow property detail page URL
statusTypeMachine status code (e.g. FOR_SALE)
statusTextHuman-readable status label
homeTypeProperty type (e.g. SINGLE_FAMILY)
imgSrcPrimary listing photo URL
latLongLatitude/longitude object

Price, size and status metrics

Field NameDescription
priceFormatted listing price string (e.g. "$1,000,000")
unformattedPriceListing price as a plain number
bedsBedroom count
bathsBathroom count
areaLiving area in square feet
daysOnZillowDays the listing has been live on Zillow
zestimateZillow's automated value estimate
taxAssessedValueCurrent tax-assessed value

Price & tax history timeline (detail-fetch fields)

Field NameDescription
priceHistoryFull array of {date, event, price, priceChangePercent, source} events from the detail page; null if not requested
taxHistoryFull array of {year, taxPaid, assessedValue, valueChangePercent} entries; null if not requested
priceReductionEventCountCount of real price-drop events in priceHistory
latestPriceChangeDateDate of the most recent price-history event
latestPriceChangePercent% change of the most recent price-history event
taxHistoryLatestYearMost recent tax-assessment year on record
taxHistoryLatestYoYPercentYear-over-year % change for that latest tax year
detailFetchStatusnot_requested / success / blocked / no_data / not_found
scrapedAtISO timestamp of when the row was collected

The raw dataset row also carries additional Zillow-internal bookkeeping fields (e.g. pgapt, sgapt, hdpData, carouselPhotosComposable) that mirror Zillow's own search-payload structure — they're present in every export but omitted above since they're rarely used directly.

🤖 Add-on: Need additional real estate data?

Once you've tracked a listing's price and tax history, ../zillow-agents-finder-listings-scraper can look up the listing agent behind it — pulling the agent's contact details, active listings, and itemized sold-listing history from the same Zillow ecosystem. It's a separate entity (agents and lenders, not property listings), so there's no overlap with this Actor's output.

Why not build this yourself?

Zillow's public consumer API (the GetSearchResults/GetDeepSearchResults web service) was retired on September 30, 2021, and has not reopened, so there is no supported official channel for pulling price and tax history at scale — anyone who wants this data has to read it off the rendered site. Doing that yourself means reverse-engineering Zillow's __NEXT_DATA__/GraphQL cache structure, keeping up with it as Zillow reshapes its Next.js pages, and building your own anti-bot posture: Zillow's search endpoint and detail pages both fingerprint TLS/JA3 and block cold sessions, so a plain HTTP client gets a bare 403 from most proxy tiers. Zillow Price History Scraper already does this: it warms a Chrome/Safari-impersonating session before every request and auto-escalates from a direct connection to a datacenter proxy to a residential proxy when blocked, and it parses Zillow's own embedded JSON rather than fragile CSS selectors, so the field names stay the same even after a layout change. Building and maintaining that anti-bot and parsing layer yourself is the ongoing cost this Actor removes.

How to use Zillow Price History Scraper

Zillow Price History Scraper runs as an Apify Actor — there's no separate signup or API key beyond your Apify account.

  1. Open the Actor's page in the Apify Console (your account, or the Apify Store listing).
  2. Add at least one entry to priceHistorySearchUrls — a full Zillow search URL, a ZIP code, or a city keyword like dallas-tx. No input field is schema-required, but the run exits immediately with zero results if this list is empty.
  3. Turn on includePriceHistory, includeTaxHistory, or set minPriceReductionEvents above 0 only if you need the value-timeline data — each adds one extra request per kept listing.
  4. Click Start.
  5. Open the Output tab to view results, or export as JSON, CSV, or Excel.

How to scale to bulk Zillow price tracking

priceHistorySearchUrls is an array — add multiple search URLs, ZIP codes, or cities and the Actor processes each one in the same run, applying maxListingsToTrack (1–10,000) as a per-search-target cap rather than a run-wide total. There's no separate "bulk mode" toggle; queuing more search targets in the same list is the bulk pattern. For very large multi-market tracking, running the same input on a schedule (Apify's built-in scheduler) is the practical way to refresh data periodically, since the Actor itself does not diff or store results between separate runs.

What can you do with Zillow price history data?

  • A real estate investor scanning a metro area uses priceHistory and priceReductionEventCount to shortlist listings with two or more real price cuts before making an offer.
  • A market analyst tracking a ZIP code uses latestPriceChangePercent and daysOnZillow together to spot submarkets cooling faster than nearby comps.
  • A property-tax researcher uses taxHistory and taxHistoryLatestYoYPercent to flag properties whose assessed value is rising faster than the local trend.
  • A negotiation-prep buyer compares zestimate against unformattedPrice and filters on minPriceReductionEvents to gauge how much room a motivated seller might have.
  • An AI agent or RAG pipeline ingests the typed priceHistory/taxHistory JSON arrays directly as context for a property-valuation or negotiation-strategy assistant, with no HTML parsing step.

How does Zillow Price History Scraper handle rate limits and blocking?

The search fetch and the optional detail-page history fetch use separate, independently hardened request paths. The search path uses a curl_cffi session impersonating Chrome/Safari TLS fingerprints, warmed with a homepage visit before the first paginated request; on a 403/429 it rotates fingerprints and falls back from no proxy → an Apify proxy tier, retrying with exponential backoff, then locks onto whichever configuration first succeeds. The detail-page fetch (used only when price/tax history is requested) runs its own proxy ladder — direct → datacenter → residential — rotating fingerprints and residential sessions on each block, up to a bounded number of residential retries before giving up on that one listing. If the dynamic-zoom search API itself returns zero results (a known anti-bot outcome independent of proxy tier), the Actor automatically falls back to HTML-page pagination for that URL instead of returning nothing. If a detail-page fetch is ultimately blocked or the property has no recognizable data, the row is still saved with detailFetchStatus set to blocked or no_data and the history fields left null — never a faked value.

⬇️ Input

All 7 parameters are optional (no field is required by the schema), but at least one entry in priceHistorySearchUrls is needed for the run to produce results.

ParameterRequiredTypeDescriptionExample Value
priceHistorySearchUrlsNoarrayZillow search URLs, ZIP codes, or city/location keywords to track. Full URLs with searchQueryState give the most accurate results. Also accepts the base actor's searchUrls key.["dallas-tx"]
listingScanModeNostringHow the search results page is paginated: PAGINATION_WITH_DYNAMIC_ZOOM_INCREASE (default, splits map areas for large datasets), PAGINATION_WITHOUT_ZOOMING_IN (HTML pages, useful when the API is blocked), or MAP_MARKERS (capped ~500 results)."PAGINATION_WITH_DYNAMIC_ZOOM_INCREASE"
maxListingsToTrackNointegerMaximum listings to scrape per search target (1–10,000). Also caps extra detail-page requests when history is enabled.50
includePriceHistoryNobooleanWhen true, fetches each listing's detail page and adds the priceHistory[] timeline. Adds one request per listing. Default false.true
includeTaxHistoryNobooleanWhen true, fetches each listing's detail page and adds the taxHistory[] timeline (shares the same request as price history). Default false.true
minPriceReductionEventsNointegerKeep only listings with at least this many real price-drop events. 0 = no filtering (default); any value above 0 auto-triggers the detail-page fetch.2
proxyConfigurationNoobjectApify proxy settings shared by the search fetch and the detail-page history fetch. Default: no proxy, with automatic fallback to datacenter then residential on blocks.{ "useApifyProxy": true }

Example input

{
"priceHistorySearchUrls": [
"https://www.zillow.com/dallas-tx/?category=SEMANTIC&searchQueryState=%7B%22isMapVisible%22%3Atrue%2C%22mapBounds%22%3A%7B%22north%22%3A33.10%2C%22south%22%3A32.53%2C%22east%22%3A-96.35%2C%22west%22%3A-97.20%7D%2C%22filterState%22%3A%7B%22sort%22%3A%7B%22value%22%3A%22globalrelevanceex%22%7D%7D%2C%22isListVisible%22%3Atrue%2C%22usersSearchTerm%22%3A%22Dallas%2C%20TX%22%2C%22category%22%3A%22cat1%22%7D",
"austin-tx"
],
"listingScanMode": "PAGINATION_WITH_DYNAMIC_ZOOM_INCREASE",
"maxListingsToTrack": 50,
"includePriceHistory": true,
"includeTaxHistory": true,
"minPriceReductionEvents": 2,
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

⬆️ Output

Every listing is pushed to the dataset as a typed, normalized JSON record with a consistent schema across runs, exportable as JSON, CSV, or Excel from the Apify Console. Each pushed row is billed under a single row_result charged event — the Actor does not push any separate uncharged accounting rows.

Example output

{
"zpid": "55826232",
"id": "55826232",
"price": "$1,000,000",
"unformattedPrice": 1000000,
"address": "3810 Hawthorne Ave, Dallas, TX 75219",
"addressStreet": "3810 Hawthorne Ave",
"addressCity": "Dallas",
"addressState": "TX",
"addressZipcode": "75219",
"beds": 3,
"baths": 3.0,
"area": 2622,
"homeType": "SINGLE_FAMILY",
"daysOnZillow": 14,
"detailUrl": "https://www.zillow.com/homedetails/3810-Hawthorne-Ave-Dallas-TX-75219/55826232_zpid/",
"statusType": "FOR_SALE",
"statusText": "For sale",
"imgSrc": "https://photos.zillowstatic.com/fp/abc123-p_e.jpg",
"latLong": { "latitude": 32.822, "longitude": -96.812 },
"zestimate": 994000,
"taxAssessedValue": 812000,
"detailFetchStatus": "success",
"priceReductionEventCount": 2,
"latestPriceChangeDate": "2025-03-11",
"latestPriceChangePercent": -3.5,
"priceHistory": [
{ "date": "2025-03-11", "event": "Price change", "price": 1000000, "priceChangePercent": -3.5, "source": "Zillow" },
{ "date": "2024-11-02", "event": "Listed for sale", "price": 1036000, "priceChangePercent": null, "source": "MLS" }
],
"taxHistoryLatestYear": 2024,
"taxHistoryLatestYoYPercent": 2.9,
"taxHistory": [
{ "year": 2024, "taxPaid": 14200, "assessedValue": 812000, "valueChangePercent": 2.9 },
{ "year": 2023, "taxPaid": 13800, "assessedValue": 789000, "valueChangePercent": null }
],
"scrapedAt": "2026-07-25T00:00:00.000Z"
}

How does it work?

Zillow Price History Scraper sends search-page requests through a curl_cffi session impersonating a real Chrome or Safari TLS fingerprint, warmed with a homepage visit first so it carries cookies a browser would already have — Zillow's search endpoint rejects cold requests outright. Search results are parsed from Zillow's own embedded JSON payload, not scraped from rendered HTML text. When history options are enabled, a second, independently proxied fetcher requests each listing's detail page and reads the same priceHistory/taxHistory arrays Zillow's site displays, walking its __NEXT_DATA__/GraphQL cache to find the property object even if Zillow rearranges its page structure. Both paths escalate through no-proxy, datacenter, and residential proxy tiers when blocked. Only data visible on Zillow's public pages is returned, and output field names stay stable regardless of layout changes.

Integrations

Zillow Price History Scraper runs on the Apify platform, so it works with anything that can call the Apify API or run an Apify Actor.

Calling Zillow Price History Scraper programmatically

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<your-username>/zillow-search-scraper-price-history-tracking").call(
run_input={
"priceHistorySearchUrls": ["dallas-tx"],
"includePriceHistory": True,
"includeTaxHistory": True,
"minPriceReductionEvents": 1,
}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.

MCP integration for AI agents

Zillow Price History Scraper is reachable through Apify's official Actors MCP Server, which exposes any Apify Actor as a callable MCP tool. Register it with an MCP-compatible client (Claude Desktop, Claude Code, or any other MCP client) using:

{
"mcpServers": {
"apify": {
"command": "npx",
"args": ["-y", "@apify/actors-mcp-server", "--actors", "<your-username>/zillow-search-scraper-price-history-tracking"],
"env": { "APIFY_TOKEN": "<YOUR_APIFY_TOKEN>" }
}
}
}

No-code tools (n8n, Make, LangChain)

In n8n, use the official Apify node (or the HTTP Request node against the Actor's run endpoint) to start a run and read back the dataset. In Make, the Apify app's "Run Actor" module does the same, feeding results into any downstream scenario. In LangChain or a custom agent framework, call the Actor via the apify-client SDK or a plain HTTP request and pass the returned JSON straight into a tool or retriever.

Scraping publicly available real estate listing data, including price and tax history, is generally permissible since Zillow makes this information visible to any visitor without a login. Zillow Price History Scraper only returns data displayed on Zillow's public search and detail pages — nothing gated behind an account. Property listings, prices, and tax records are business/product data rather than personal data, so this falls under Zillow's Terms of Service and database-rights considerations rather than a personal-data regime like GDPR or CCPA. Consult legal counsel if your use case involves bulk storage of personal data (e.g., agent contact details) or redistribution of Zillow's data at scale.

Frequently asked questions

What Zillow listing fields does Zillow Price History Scraper return?

It returns price, address, beds/baths, and — when history is enabled — priceHistory and taxHistory as its top fields, alongside zestimate, taxAssessedValue, and status fields. See What data can I extract for the full list.

Does Zillow Price History Scraper require a Zillow account or login?

No. The Actor makes no login or authenticated request anywhere in its code — it only reads Zillow's public search results and property detail pages.

How many listings can I extract in one run?

maxListingsToTrack allows 1–10,000 listings per search target (URL, ZIP, or city), and you can queue multiple search targets in priceHistorySearchUrls in a single run.

What happens if a search returns zero listings, or a listing's detail page is blocked or removed?

A search with no matching properties simply produces zero rows for that target after a few consecutive empty pages. For an individual listing's detail-page fetch, the row is still saved with detailFetchStatus set to blocked, not_found, or no_data and the history fields left null — it is never dropped silently or given a faked value.

Can I scrape multiple Zillow searches at once?

Yes. priceHistorySearchUrls accepts an array of URLs, ZIP codes, or city keywords, and each one is processed within the same run, up to maxListingsToTrack per target.

Does Zillow Price History Scraper work with Claude, ChatGPT, and other AI agent tools?

Yes. It's reachable through Apify's Actors MCP Server (see Integrations) for MCP-compatible clients, and it's callable as a plain HTTP/API endpoint by any agent framework.

How does Zillow Price History Scraper compare to other Zillow price history scrapers?

It differs mainly in discovery and filtering: it finds listings directly from a live search (URL, ZIP, or city) and applies a built-in motivated-seller filter (minPriceReductionEvents), rather than requiring a pre-built list of property URLs. As observed on their own Apify Store listings on 2026-07-25, vulnv's Zillow Price History Scraper returns per-event price records from bulk property URLs but has no tax-history extraction or price-drop threshold filter, and kawsar's Zillow Price Tax History Scraper outputs one flat row per price/tax event across ID/URL/address lookup modes but likewise has no motivated-seller filter. Pricing and success-rate figures shown on those listings are the vendors' own claims and were not independently verified here.

Does Zillow Price History Scraper return data in a format LLMs can use directly?

Yes. Output is typed, normalized JSON with consistent field names across runs — no HTML parsing or CSS selectors. Pass it directly to an LLM, index it into a vector store, or feed it to an agent tool.

How does the price-history tracking actually work?

priceHistory and taxHistory are extracted live, on every run, from the priceHistory[]/taxHistory[] arrays already embedded in Zillow's own property detail page — the same timeline Zillow's own site displays. This is not a database the Actor maintains across runs: it does not store previous runs' results or diff a property's price against an earlier scrape. Each run reads whatever history Zillow has published as of that run.

What happens when Zillow changes its layout or anti-bot system?

The output schema is designed to stay stable: listings are parsed from Zillow's structured JSON payload (with several known JSON-path fallbacks) rather than brittle CSS selectors, and the detail-page parser walks the response recursively to find the property object even if Zillow rearranges its page structure. No specific update turnaround time is promised.

Can I use Zillow Price History Scraper without managing proxies or browser infrastructure?

Yes. The Actor handles TLS-fingerprint impersonation, session warming, and automatic proxy escalation (no proxy → datacenter → residential) on both the search and detail-page fetch paths; you only need to supply optional proxy settings if you want to override the defaults.

Which fields work best for AI training data and RAG indexing?

For RAG, index address, statusText, and the event-level text inside priceHistory (event, source) as retrievable context. For training data, zpid, unformattedPrice, beds, baths, and taxAssessedValue are the most consistently structured typed fields across every returned row.

Scraper NameWhat it extracts
../zillow-agents-finder-listings-scraperZillow real estate agents and lenders, plus each agent's active and sold listings
../airbnb-full-year-price-tracker-scraper-cheapest-most-expensive-datesDaily Airbnb nightly rates across a full calendar year, per listing
../airbnb-occupancy-scraper-with-booking-rate-percentageAirbnb booking-rate percentage and open-date gaps per listing
../amazon-search-products-scraper-top-rated-best-reviewedAmazon search results ranked and filtered by rating, review count, and price
../eBay-ScrapereBay listing prices, seller info, availability, and category data

Your feedback

Found a bug or missing a field? Let us know through this Actor's Issues tab on its Apify Store page, or message the developer directly from the listing. Bug reports and field requests are what keep this Actor's field coverage accurate as Zillow's site changes.