Zillow Scraper API: For Sale, Sold, Rentals & Zestimate avatar

Zillow Scraper API: For Sale, Sold, Rentals & Zestimate

Pricing

from $1.70 / 1,000 properties

Go to Apify Store
Zillow Scraper API: For Sale, Sold, Rentals & Zestimate

Zillow Scraper API: For Sale, Sold, Rentals & Zestimate

Zillow scraper and Zillow search scraper. Scrape Zillow homes for sale, Zillow rentals and Zillow sold homes by city, ZIP code or search link, FSBO, foreclosure, auction filters, Zestimate and details by zpid or address. Zillow new listings alert, price drop monitor. Zillow listings API; Zillow MCP.

Pricing

from $1.70 / 1,000 properties

Rating

0.0

(0)

Developer

Saulius AutomatesIT

Saulius AutomatesIT

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

3

Monthly active users

12 days ago

Last modified

Features

Limited permissions

Share

Get Zillow data in bulk: homes for sale, for rent and recently sold in any city, ZIP code, neighborhood, county or state, or behind any Zillow search link with your filters, and property details with Zestimate for any Zillow link, zpid or street address. Each home comes with price, Zestimate and its range, rent Zestimate, tax assessed value, last sold price, beds, baths, living area, lot, year built, home type, days on Zillow, page views and saves, description, facts, listing agent and broker, MLS id, coordinates and photos.

No Zillow account, no cookies of yours, no browser. $2 per 1,000 properties with full details, $1.50 per 1,000 listings from searches.

It also works as a Zillow new listings alert and price drop monitor: schedule a search and each run returns only the homes that are new or changed their price since the last run, posts them to Slack, Discord, Teams or any webhook if you want, and charges only for those. See Monitoring.

What you can use it for

  • Real estate investing: every home for sale in a ZIP code with price, Zestimate and rent Zestimate side by side, to spot underpriced homes and rental yields.
  • Valuations in bulk: paste a list of street addresses and get the Zestimate, its low and high range, rent Zestimate, tax value and last sale for each.
  • Market research: inventory, prices, days on market and sold homes by city or neighborhood, scheduled daily or weekly.
  • Lead generation: listings with the listing agent, broker and MLS id; recently sold homes by area.
  • Rentals: apartments and homes for rent with unit prices by bedroom count.
  • New listing alerts and price drop monitoring: schedule a search with monitoringMode or monitor: "priceDrops" and each run returns only new listings, price cuts and status changes, posts them to Slack, Discord or a webhook, and charges only for those.

Why not call Zillow yourself

Zillow has no public API for listings or Zestimates (its old API was shut down). The website loads its data from page JSON and an internal search endpoint that caps every search at 20 pages, answers unknown place names with San Francisco, and pushes back on repeated requests. This Actor resolves places the way Zillow's search box does, pages through results, splits big areas into smaller map boxes to get past the 820-home cap, retries on fresh IPs, and returns plain JSON: one call from Python, JavaScript, cURL or an AI agent.

How to use it

  1. Add Places to search (Austin, TX, 78704) and pick for sale, for rent or sold; or paste Zillow search links with any filters you set on zillow.com; or both.
  2. Add Properties: Zillow links, zpids or street addresses, for one detailed row each.
  3. Turn on Full details for search results if you want the full property row for every home a search finds.
  4. Run it and download the results as JSON, CSV or Excel, or read them through the API.

Input example

{
"locations": ["Austin, TX", "78704"],
"status": "forSale",
"maxResultsPerSearch": 500,
"includeDetails": false,
"searchUrls": ["https://www.zillow.com/seattle-wa/rentals/"],
"properties": [
"2114 Bigelow Ave N, Seattle, WA 98109",
"https://www.zillow.com/homedetails/48841077_zpid/",
"48749425"
]
}

Search filters

All optional; with none set, a search returns what Zillow shows by default. They apply to places and to search links (a filter you set here overrides the link's own value).

  • Price, beds, baths, size, year built: minPrice, maxPrice (monthly rent for rentals), minBeds, maxBeds, minBaths, minSqft, maxSqft, minYearBuilt, maxYearBuilt.
  • Home types: homeTypes, for example ["house", "condo"]. Sold within: maxDaysOnZillow on sold searches. Order: sortBy (newest, priceLow, priceHigh and more).
  • Listing types: listingTypes picks by agent, by owner (FSBO), new construction, coming soon, auctions, foreclosures, and the off-market foreclosed (bank owned) and preForeclosure homes Zillow shows only when asked. Rows then carry listingSubTypes. includePending adds pending and under-contract homes.
  • Keywords and features: keywords (Zillow's text filter, for example pool or ADU), maxHoa, minLotSqft, maxLotSqft, minParkingSpots, and mustHave (garage, pool, waterfront, single story, air conditioning, basement, city view, open house).
{
"locations": ["Austin, TX"],
"status": "forSale",
"listingTypes": ["foreclosure", "foreclosed", "auction"],
"maxPrice": 400000,
"minBeds": 3,
"maxResultsPerSearch": 100
}

These work in the JSON input (they are not on the form) and use the same field names as other Zillow scrapers, so an input you already have keeps its filters here.

  • Rentals: pets (largeDogs, smallDogs, cats, notAllowed), space (entirePlace or roomForRent), moveInDate (2026-12-01, available on or before), hideNoMoveInDate, and true switches inUnitLaundry, onSiteParking, elevator, highSpeedInternet, furnished, outdoorSpace, utilitiesIncluded, hardwoodFloors, disabilityAccess, incomeRestricted, apartmentCommunity, acceptsZillowApplications, tourScheduling, shortTermLease, controlledAccess, petsAllowed, dishwasher, fitnessCenter.
  • Any search: views (city, mountain, park, water), basementTypes (finished, unfinished), and true switches 3dTour, showcase, priceDrop. Sold in last: maxSoldDate (1w, 1m, 3m, 6m, 1y and the like).
  • Radius search: latitude, longitude and distanceMiles (default 20, at most 100) give every home within that many miles of the point, with the status and filters above. Rows carry searchInput like 30.2672,-97.7431 within 2 mi.
  • Zestimate history: includeZestimateHistory: true adds zestimateHistory to every home row, search results included: the home's monthly Zestimate for the last ten years ([{ "date": "2016-10-31", "value": 1727349 }, ...]), the series behind the chart on the Zillow page. No extra charge.
  • Walk Score: includeWalkScore: true adds walkScore, transitScore and bikeScore (0 to 100) with Walk Score's words to every home row. No extra charge.
  • Flat rows: flattenOutput: true turns nested fields into dot paths (facts.Heating, priceHistory.0.price, photos.0) for CSV and spreadsheet exports.
{
"latitude": 30.2672,
"longitude": -97.7431,
"distanceMiles": 3,
"status": "forRent",
"pets": ["largeDogs"],
"inUnitLaundry": true,
"maxResultsPerSearch": 200
}

Zillow new listings alert and price drop monitor

Schedule the same search daily or hourly and get a feed of what changed instead of the whole market again: new listings, price cuts and rises, and status changes Zillow shows in the search. Unchanged homes are skipped before any detail request, so they are not saved and not charged. A run with nothing new costs only the $0.00005 start.

Switches (JSON input; the names of other Zillow monitors work too, see below):

FieldWhat it does
monitoringMode: trueNew listings plus price and status changes since the last run
onlyNewSinceLastRun: trueNew listings only
monitor: "priceDrops"Price cuts only. The first run saves the homes as the baseline and returns nothing; later runs return each cut
changeTypesPick the changes you want: newListing, priceCut, priceIncrease, backOnMarket, pending, sold (also NEW, PRICE_CHANGE, STATUS_CHANGE)
alertWebhookUrlPost each run's changes to a Slack, Discord or Microsoft Teams incoming webhook, or as JSON to any HTTPS endpoint (Zapier, Make, n8n, your server). Turns monitoring on
alertChangeTypesWhich changes are posted (default: all of them)
storeNameName of the key-value store in your account that remembers earlier runs. Leave it out and each search and filter set gets its own

Each changed row carries changeType (NEW, PRICE_CHANGE, STATUS_CHANGE), changeKind (newListing, priceCut, priceIncrease, priceChange when one side has no price, backOnMarket, pending, sold, statusChange), previousPrice, priceChange, previousStatus, firstSeenAt and previousSeenAt. The first run returns every listing as NEW (except in price-drop-only mode). maxResultsPerSearch is how many listings each run checks, so pair it with "sortBy": "newest" on big areas.

Set up a scheduled alert in 3 steps

  1. In Apify Console open this Actor, switch the input to JSON, paste one of the examples below and click Save as a new task.
  2. On the task, open Schedules, click Create new schedule and pick daily (or every hour).
  3. Get the changes: in alertWebhookUrl (Slack, Discord, Teams), from the task's last dataset through the API, or with the task's Integrations tab (email, Google Sheets, Zapier, Make).

Example inputs for scheduled runs

New listings in a ZIP code, posted to Slack every morning:

{
"locations": ["78704"],
"status": "forSale",
"sortBy": "newest",
"maxResultsPerSearch": 200,
"onlyNewSinceLastRun": true,
"alertWebhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ"
}

Price drop monitor for 3+ bed houses under $600,000 in a city:

{
"locations": ["Austin, TX"],
"status": "forSale",
"homeTypes": ["house"],
"minBeds": 3,
"maxPrice": 600000,
"maxResultsPerSearch": 2000,
"monitor": "priceDrops"
}

Investor feed: new FSBO, foreclosure and auction homes plus price cuts and back on market:

{
"locations": ["Phoenix, AZ"],
"status": "forSale",
"listingTypes": ["owner", "foreclosure", "auction"],
"sortBy": "newest",
"maxResultsPerSearch": 500,
"monitoringMode": true,
"changeTypes": ["newListing", "priceCut", "backOnMarket"]
}

New rentals that take large dogs, posted to Discord:

{
"locations": ["Denver, CO"],
"status": "forRent",
"maxPrice": 2500,
"pets": ["largeDogs"],
"sortBy": "newest",
"maxResultsPerSearch": 300,
"onlyNewSinceLastRun": true,
"alertWebhookUrl": "https://discord.com/api/webhooks/123/abc"
}

Your own Zillow search link (map area and filters as set on zillow.com), new homes only:

{
"searchUrls": ["https://www.zillow.com/homes/for_sale/?searchQueryState=..."],
"maxResultsPerSearch": 500,
"onlyNewSinceLastRun": true
}

New sales in an area (comps feed): a home that sells leaves a for-sale search instead of changing status there, so watch sales with their own monitor:

{
"locations": ["Raleigh, NC"],
"status": "sold",
"maxDaysOnZillow": "7",
"maxResultsPerSearch": 500,
"onlyNewSinceLastRun": true
}

Run it from code on your own schedule (cron, Airflow, n8n) and read only the changes:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("sauliusautomatesit/zillow-scraper-api").call(run_input={
"locations": ["Austin, TX"], "sortBy": "newest", "maxResultsPerSearch": 500, "monitoringMode": True,
})
if run is None:
raise RuntimeError("Actor run was not found")
for home in client.dataset(run.default_dataset_id).iterate_items():
print(home["changeKind"], home["price"], home.get("priceChange"), home["address"], home["url"])

For a runnable Python workflow, use the Zillow new listings and price drop monitoring tutorial. It includes a tested script, named monitor state, a spend cap and instructions for repeated runs.

What a monitor costs you: a daily run with 20 changes is about 600 listings a month, $0.90. An hourly run that finds nothing new costs only the start, $0.036 a month. You pay for changes, not for re-reading the market.

Inputs of other Zillow monitors and price trackers work here as is: onlyChanges, historyName, onlyPriceCuts, deduplicateResults, webhookUrl, maxHoursOld, maxListingsPerZip, listingType (sale, rent, sold, for_sale), minSquareFeet, maxSquareFeet, and monitoringMode with storeName.

Price history, tax history and schools

Turn on Price history, tax history and schools (includeHistory: true) and each property row also gets priceHistory (every listing, price change and sale with date and price), taxHistory (yearly tax paid and assessed value), schools (rating, grades, distance), nearby homes and climateRisk (flood, fire, wind, heat and air quality scores with the FEMA flood zone and insurance advice). It works for for-sale, pending, sold and off-market homes, and is charged as a normal property.

Apartment buildings: every unit with rent, fees and availability

Rental searches mostly return apartment buildings, not single homes. Add "extractBuildingUnits": true to the JSON input ("all" works too) and each building becomes one row per available unit: unit number, rent, fees, beds, baths, square feet, availability date, lease terms and pet policy, plus the building's amenities, offers and scores. Building links (/apartments/..., /b/...) pasted in Properties always give unit rows. maxUnitsPerBuilding caps spend on very large buildings. Each unit is charged as a property.

{
"locations": ["Austin, TX"],
"status": "forRent",
"extractBuildingUnits": true,
"maxUnitsPerBuilding": 50
}

Output

{
"type": "listing",
"zpid": "58312123",
"url": "https://www.zillow.com/homedetails/1011-Brodie-St-APT-28-Austin-TX-78704/58312123_zpid/",
"status": "FOR_SALE",
"price": 600000,
"address": "1011 Brodie St APT 28, Austin, TX 78704",
"city": "Austin", "state": "TX", "zipcode": "78704",
"latitude": 30.24636, "longitude": -97.76386,
"bedrooms": 3, "bathrooms": 3, "livingArea": 1521,
"lotArea": 4173.048, "lotAreaUnit": "sqft",
"homeType": "SINGLE_FAMILY",
"zestimate": null, "rentZestimate": null, "taxAssessedValue": 516022,
"daysOnZillow": 2, "dateSold": null,
"brokerName": "Compass RE Texas, LLC",
"photos": ["https://photos.zillowstatic.com/fp/7a619a56e12d0d6372afe4917d72ff10-p_e.jpg"],
"source": "search", "searchInput": "78704", "searchStatus": "forSale", "matchedPlace": "78704", "position": 2
}

Rentals in apartment buildings have isBuilding: true, the building name and units with price per bedroom count, and no zpid.

{
"type": "property",
"zpid": "48749425",
"url": "https://www.zillow.com/homedetails/2114-Bigelow-Ave-N-Seattle-WA-98109/48749425_zpid/",
"status": "OTHER",
"price": 2155400,
"zestimate": 2155400, "zestimateLow": 1939860, "zestimateHigh": 2370940,
"rentZestimate": 6769,
"streetAddress": "2114 Bigelow Ave N", "city": "Seattle", "state": "WA", "zipcode": "98109",
"county": "King County",
"bedrooms": 4, "bathrooms": 3, "livingArea": 3470, "lotSize": 4680, "yearBuilt": 1924,
"homeType": "SINGLE_FAMILY",
"taxAssessedValue": 2044000, "propertyTaxRate": 0.82, "lastSoldPrice": 995000,
"daysOnZillow": 6522, "pageViews": null, "favorites": null,
"description": null,
"agentName": null, "brokerName": null, "mlsId": null,
"neighborhood": "Queen Anne", "pricePerSquareFoot": 621,
"facts": { "homeType": "SingleFamily", "lotSize": "4,680 sqft", "yearBuilt": 1924, "parkingFeatures": ["Off-street", "Garage"] },
"photos": ["https://photos.zillowstatic.com/fp/..."],
"source": "address", "input": "2114 Bigelow Ave N, Seattle, WA 98109",
"matchedAddress": "2114 Bigelow Ave N Seattle, WA 98109"
}

For-sale homes add the listing description, agent name and phone, broker, MLS name and id, page views and saves, HOA fee and price per square foot. priceHistory and taxHistory are filled when Zillow puts them in the page (some showcase listings); otherwise they are null.

Good to know

  • Search size: Zillow shows at most about 820 homes per search (20 pages of 41). Ask for more and the Actor splits the area into map quarters, again and again where needed, and removes duplicates. The run summary (OUTPUT in the key-value store) shows how many homes Zillow has per search and how many you got.
  • Places are matched with Zillow's own search box: the first place it suggests is used, and the row says which (matchedPlace). A name Zillow does not know comes back as a free NOT_FOUND row instead of another city's homes.
  • Addresses are matched the same way; the row carries the address Zillow matched (matchedAddress).
  • Zestimates are Zillow's estimates; some homes and some states have none, and the field is then null.
  • Apartment buildings appear in rental searches as one building row each, unless extractBuildingUnits is set in the JSON input; building links in Properties always give one row per unit.

Pricing

Pay per result, no subscription:

ItemPrice
Property (full details)$0.002 ($2 per 1,000)
Listing (search result)$0.0015 ($1.50 per 1,000)
Run start$0.00005

Bronze, Silver and Gold Apify plans pay 5%, 10% and 15% less. With Full details for search results on, each home is charged once, as a property. Inputs that give nothing (unknown place, deleted home, a search with no homes) come back as free error rows that say why.

Use it from code or an AI agent

These examples use apify-client 3.x: install it with pip install "apify-client>=3,<4". On 2.x, use run["defaultDatasetId"] instead of run.default_dataset_id.

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("sauliusautomatesit/zillow-scraper-api").call(run_input={
"locations": ["78704"],
"status": "forSale",
"maxResultsPerSearch": 200,
})
if run is None:
raise RuntimeError("Actor run was not found")
for item in client.dataset(run.default_dataset_id).iterate_items():
print(item["price"], item["zestimate"], item["address"])

As an MCP tool for Claude, Cursor or any MCP client: https://mcp.apify.com/?tools=sauliusautomatesit/zillow-scraper-api.

Notes

The Actor reads only public data that Zillow shows to any logged-out visitor, and it does not collect agents' e-mail addresses. Use the data in line with Zillow's terms and the privacy and fair housing laws that apply to you.

⌂ 换网址