Zillow Scraper: Sale, Rent and Sold Property Listings avatar

Zillow Scraper: Sale, Rent and Sold Property Listings

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Zillow Scraper: Sale, Rent and Sold Property Listings

Zillow Scraper: Sale, Rent and Sold Property Listings

Scrape zillow.com properties for sale, for rent and recently sold across the US: price, beds, baths, area, address, GPS, photos, home value and rent estimates. Optional property page read adds HOA fee, tax rate, MLS id, agent, brokerage and the fact sheet. 25 filters, or paste links.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Categories

Features

Limited permissions

Share

Zillow Scraper turns zillow.com into structured property data. Search any US place by name or ZIP for homes for sale, homes for rent or recently sold homes, or paste links you already have. Every record carries price, beds, baths, area, full address, GPS, photos and the site's own home value and rent estimates; switch on the property page read and it also carries the description, year built, HOA fee, property tax rate, MLS id, listing agent, brokerage and the full fact sheet. Export to JSON, CSV or Excel, or pull results straight into your app through the API.

Why This Scraper?

  • Coverage past the site's own ceiling. One read of a map area returns at most 500 records however many properties exist inside it. This actor splits a busy area into quarters and reads each one, so a city with thousands of homes is genuinely covered instead of truncated at the first few hundred.
  • Honest completeness. Every run reports whether it scanned an area end to end. A refused read, an unresolved place or a run cap all mark the scan partial, and expiry tracking refuses to act on a partial scan.
  • Three channels, one shape. For sale, for rent and recently sold return the same columns, so a rental feed and a sold-comparables feed line up without post-processing.
  • 25 search filters. Channel, price, beds, baths, area, lot size, year built, HOA fee, property type, keyword, time on market, sort order and eight feature toggles.
  • Recurring monitoring built in. Run the same search on a schedule and get only what changed, marked NEW, UPDATED, REAPPEARED or EXPIRED, with the exact list of fields that moved.
  • Pay for results, not for pages. The search-level record costs one result event. Reading each property's own page is optional and billed separately, so you never pay for detail you did not ask for.
  • No fields quietly dropped. Agent name, phone, brokerage and MLS id are returned whenever the property page publishes them, instead of being silently omitted.

Use Cases

  • Property investors and flippers: screen a whole metro for price, days on market and lot size, then compare against the home value estimate.
  • Rental market research: track asking rent by bedroom count and neighborhood across several cities at once.
  • Comparable sales analysis: pull recently sold homes near a subject property to support a valuation or an offer.
  • Lead generation for agents and lenders: monitor a farm area on a schedule and get only the new listings and price changes.
  • Market dashboards and reports: build a standing dataset of active inventory, price trends and property mix for a region.

Data You Get

Sample shape: values are illustrative placeholders, not from a live listing.

FieldExample
id / zpid"00000001"
url"https://www.zillow.com/homedetails/00000001_zpid/"
listingType"FOR_SALE" (also "FOR_RENT", "SOLD")
homeStatus / statusText"FOR_SALE" / "Active"
propertyType"SINGLE_FAMILY"
price / formattedPrice612000 / "$612,000"
zestimate / rentZestimate604800 / 2875
taxAssessedValue498000
priceChange / priceChangeDate-9000 / "2026-02-01T00:00:00.000Z"
streetAddress / city / state / zipCode"142 Sample Ridge Dr" / "Austin" / "TX" / "78701"
latitude / longitude30.30 / -97.70
bedrooms / bathrooms4 / 3
livingArea2100
lotAreaValue / lotAreaUnit8000 / "sqft"
daysOnZillow14
priceReduction / marketingTagline / cardHighlight"$9,000 (Feb 1)" / "Showcase" / short card badge text
cardType / units / dateSold / listingSoldPrice / availabilityDate / sourceSearchUrlcard type, apartment-building units, sold date and price (sold searches), rental availability, originating search link
listingSubType / openHouse / openHouseSchedule{"isFSBA": true, "isOpenHouse": true} (listing-kind flags: for sale by agent or owner, coming soon, pending, auction, foreclosure, bank owned, open house, new home; only the flags the card carries) / "Sat. 11am-2pm" / [{"startDate": "2026-09-05T11:00:00", "endDate": "2026-09-05T14:00:00"}] (open-house windows, property-local wall-clock time with no time-zone suffix)
heroImage / photosproperty photo URL(s)
description / yearBuilt / monthlyHoaFee / propertyTaxRate / mlsId / mlsName"..." / 1995 / 60 / 1.9 / "1234567" / "Sample MLS" (property page only)
listingAgentName / listingAgentPhone / brokerageName"Jordan Example" / "(555) 010-0100" / "Sample Realty Group" (property page only)
resoFactsparking, sub-type and other fact-sheet fields (property page only)
changeType / changedFields"UPDATED" / ["price"] (incremental mode only)
detailFetched / scrapedAttrue / "2026-01-01T00:00:00.000Z"

Dataset views. The output tab offers three views: Results (the main card fields), Property page details (description, year built, HOA fee, MLS, agent and brokerage, filled when you switch on the property page read) and Changes (changeType and changedFields, filled in incremental mode).

Added card fields. Newer rows also carry cardType, units, priceReduction, marketingTagline, cardHighlight, dateSold, listingSoldPrice, availabilityDate, priceIncludesMonthlyFees, isRentalWithBasePrice, marketingTreatments, sourceSearchUrl, listingSubType and openHouseSchedule. They are additions only; no existing field was renamed or removed. In incremental mode they are ignored by default when deciding UPDATED, so an existing saved baseline does not suddenly bill a wave of changes.

Rental results also include building and community cards, which carry a price range instead of one price and are returned with the fields the site publishes for them.

How to Use

  1. Pick a mode: search (build a search from a location and filters) or url (paste links you already have).
  2. In search mode, add one or more locations and set the channel and any filters. In URL mode, paste search or property links.
  3. Turn on Read the property page for each result if you need the description, year built, HOA fee, MLS id, agent and brokerage.
  4. Set Max results to control run size and cost, then click Start. Download the dataset as JSON, CSV or Excel, or read it through the API.

Search one city for homes for sale:

{
"mode": "search",
"locations": ["Austin, TX"],
"listingType": "FOR_SALE",
"maxItems": 200
}

Search several places for rentals under a price, with filters:

{
"mode": "search",
"locations": ["Brooklyn, NY", "Jersey City, NJ"],
"listingType": "FOR_RENT",
"maxPrice": 3500,
"minBeds": 2,
"homeTypes": ["APARTMENT", "CONDO"],
"daysOnZillow": "30_DAYS",
"maxItems": 500
}

Recently sold comparables with the property page read switched on:

{
"mode": "search",
"locations": ["78759"],
"listingType": "SOLD",
"daysOnZillow": "12_MONTHS",
"fetchDetails": true,
"maxItems": 100
}

Paste links you already have:

{
"mode": "url",
"startUrls": [
"https://www.zillow.com/homes/for_sale/Austin,-TX/",
"https://www.zillow.com/homedetails/00000001_zpid/"
],
"maxItems": 50
}

URL mode defaults: if you switch to URL mode and leave the links field untouched (or omit startUrls from an API call), the run scrapes one example of each supported link shape: a for-sale search, a city page, a page-numbered city page (/austin-tx/2_p/ starts at page 2, it does not restart at page 1), a for-rent search and one property page (returned as a single record). Replace the list, or pass an empty list, to scrape only your own links. Max results still caps the whole run.

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/zillow-scraper").call(
run_input={"mode": "search", "locations": ["Austin, TX"], "maxItems": 50}
)
for record in client.dataset(run["defaultDatasetId"]).iterate_items():
print(record["address"], record["price"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/zillow-scraper').call({
mode: 'search', locations: ['Austin, TX'], maxItems: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

How coverage and Max results interact

One read of a map area returns at most 500 records, however many exist inside it. This actor covers a busy area by splitting it into quarters and reading each one, up to a run-level cap on total reads (Max reads per location). When an area still holds more than one read can return and can no longer be split, the run reports that area as not fully covered rather than reporting a silent partial count.

Resume and recurring updates

  • Resume (resumeFromRunId) continues one interrupted run: paste its run or dataset id and the actor skips every row already collected there, so you don't pay twice.
  • Incremental mode (incrementalMode) is for scheduled runs over the same search. Each property is classified NEW, UPDATED (with changedFields), UNCHANGED (suppressed and not billed unless emitUnchanged is on), REAPPEARED or EXPIRED (only after a run scanned the whole search end to end, and only with emitExpired). stateKey names or shares the stored state. With incremental mode off, output is exactly as before.
  • Ignoring noisy fields (incremental mode). These fields are always ignored when deciding UPDATED: the scrape time, days on Zillow, favourite count and page view count (they move on their own), and the added card fields sourceSearchUrl, cardType, units, isValid, hasImage, marketingTagline, cardHighlight, priceReduction, priceIncludesMonthlyFees, isRentalWithBasePrice, marketingTreatments, availabilityDate, dateSold, listingSoldPrice, listingSubType and openHouseSchedule. A change to only one of them does not, on its own, make a row UPDATED (a changed price or openHouse label still does), and changedFields leaves them out; they are still returned in every row. Add more with ignoreFieldsForChanges; Zillow's own zestimate and rentZestimate are recomputed regularly, so list them there if you only care about listing changes. The saved baseline is compared again with your current list on every run, so editing the list never turns the whole baseline into UPDATED.
  • Resume plus incremental mode. You can combine the two only on a campaign with no saved state yet; with saved state the run stops and asks you to remove the resume id or pick a different stateKey. On that first combined run the resumed properties are skipped, and they carry no saved values into the campaign. So the next incremental run returns each resumed property that is still listed once as UPDATED (with every field in changedFields) and bills it. From the run after that, classification is normal. To avoid that one extra batch, start a campaign with a plain incremental run instead of a resume.
  • Tip: keep Max results high (or 0) on incremental runs. Max results limits how many properties each read checks, not only how many are returned. This is deliberate: a property the run never checked is never counted as seen, so the run is correctly reported as partial and nothing is wrongly marked EXPIRED. The side effect is that unchanged properties use up the cap even though they are not returned. With a small cap, a new or changed property that sits later in the scan order can go unchecked for that run, and the run can end with fewer rows, or none, and a status saying nothing changed, even though changes exist. Those properties are not lost: any later run whose cap reaches them reports them. Set Max results to 0, or comfortably above the area's normal listing count, whenever incrementalMode is on; keep a tight cap for one-off searches.
  • Tip: emitExpired rows count toward Max results. Once a run has scanned its tracked search end to end, properties that are no longer found are pushed and billed as EXPIRED in that same run, but only while the run is still under Max results (the cap covers the whole run, every location or link together, minus the rows already returned). Properties left over when the cap is reached stay tracked and are reported by a later run; Max results 0 means no cap, so every one is reported at once. A run that stopped because it reached Max results did not scan the search end to end, so it reports no EXPIRED rows at all. Turn emitExpired off if you only want the NEW/UPDATED delta.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify, Settings, Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch builds the search from the location and filters below. url takes zillow.com links you already have.
locationsarray["Austin, TX"]Search mode only. One or more US places, written the way you would type them into the site. The run cap is shared evenly between them.
listingTypestringFOR_SALESearch mode only. FOR_SALE, FOR_RENT or SOLD.
homeTypesarray[]Search mode only. Empty means every property type.
minPriceintegernoneSearch mode only. Lowest price in USD (lowest monthly rent on a for-rent search).
maxPriceintegernoneSearch mode only. Highest price in USD (highest monthly rent on a for-rent search).
minBedsintegernoneSearch mode only. Fewest bedrooms.
maxBedsintegernoneSearch mode only. Most bedrooms.
minBathsintegernoneSearch mode only. Fewest bathrooms.
minSqftintegernoneSearch mode only. Smallest interior area in square feet.
maxSqftintegernoneSearch mode only. Largest interior area in square feet.
minLotSizeintegernoneSearch mode only. Smallest lot in square feet.
maxLotSizeintegernoneSearch mode only. Largest lot in square feet.
minYearBuiltintegernoneSearch mode only. Earliest year built.
maxYearBuiltintegernoneSearch mode only. Latest year built.
maxHoaFeeintegernoneSearch mode only. Highest monthly HOA fee in USD. 0 returns only properties with no HOA fee.
keywordsstringnoneSearch mode only. Narrows to properties whose listing text mentions this word.
daysOnZillowstringANYSearch mode only. How recently the property was listed, or sold on a recently-sold search.
sortBystringRECOMMENDEDSearch mode only. Result ordering; changes the order results arrive in, not which properties match.
hasPoolbooleanfalseSearch mode only. Must have a pool.
hasGaragebooleanfalseSearch mode only. Must have a garage.
hasAirConditioningbooleanfalseSearch mode only. Must have air conditioning.
isWaterfrontbooleanfalseSearch mode only. Waterfront only.
singleStoryOnlybooleanfalseSearch mode only. Single story only.
has3dTourbooleanfalseSearch mode only. Must have a 3D tour.
openHouseOnlybooleanfalseSearch mode only. Open house only.
priceReducedOnlybooleanfalseSearch mode only. Price reduced only.
startUrlsarrayone example of each link shapeURL mode only. zillow.com search links (walked automatically) or property links ending in _zpid. Search-mode filters are ignored in this mode.
fetchDetailsbooleanfalseRead the property page for each result. Adds description, year built, HOA fee, property tax rate, MLS id and name, listing agent and brokerage, full photo gallery, parking and the fact sheet. Billed per enriched result.
maxItemsinteger20Maximum number of results across every location or link. 0 means unlimited.
maxPagesinteger0Optional safety cap on search reads per location or link. 0 means no read limit; the run still stops at Max results.
resumeFromRunIdstringnoneContinue one interrupted run without returning or billing for rows already collected there. For recurring monitoring, use Incremental mode instead.
incrementalModebooleanfalseReturn only new and changed results on scheduled runs against the same search.
stateKeystringnoneName a monitoring campaign to keep its state stable, or share state across differently configured runs.
emitUnchangedbooleanfalseAlso return (and bill) results unchanged since the last run.
emitExpiredbooleanfalseAlso return (and bill) results that were present before and are no longer found, once a run has scanned the search end to end.
ignoreFieldsForChangesarraynoneIncremental mode only. Field names that never, on their own, make a property UPDATED, for example zestimate. Use a dotted name such as resoFacts.hoaFee for a nested field. Ignored fields are still returned in every row.
proxyobjectApify Proxy, USHow this run reaches the site. The prefilled option is billed by traffic on top of the run itself. You can also supply your own connection URLs instead.
mcpConnectorsarraynoneOptional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstringnoneNotion connector only: page under which item pages are created.
maxNotifyListingsinteger50Cap on items written to each connector per run. Does not affect the dataset.

Output Example

Sample shape: values are illustrative placeholders, not from a live listing.

{
"id": "00000001",
"zpid": "00000001",
"url": "https://www.zillow.com/homedetails/00000001_zpid/",
"listingType": "FOR_SALE",
"homeStatus": "FOR_SALE",
"statusText": "Active",
"propertyType": "SINGLE_FAMILY",
"price": 612000,
"formattedPrice": "$612,000",
"currency": "USD",
"zestimate": 604800,
"rentZestimate": 2875,
"taxAssessedValue": 498000,
"priceChange": -9000,
"priceChangeDate": "2026-02-01T00:00:00.000Z",
"streetAddress": "142 Sample Ridge Dr",
"city": "Austin",
"state": "TX",
"zipCode": "78701",
"country": "USA",
"address": "142 Sample Ridge Dr, Austin, TX 78701",
"latitude": 30.30,
"longitude": -97.70,
"bedrooms": 4,
"bathrooms": 3,
"livingArea": 2100,
"lotAreaValue": 8000,
"lotAreaUnit": "sqft",
"daysOnZillow": 14,
"heroImage": "https://photos.zillowstatic.com/fp/00000000-p_e.jpg",
"photos": ["https://photos.zillowstatic.com/fp/00000000-p_e.jpg"],
"description": "Single story home with an open kitchen and a covered patio.",
"yearBuilt": 1995,
"monthlyHoaFee": 60,
"propertyTaxRate": 1.9,
"pricePerSquareFoot": 291,
"mlsId": "1234567",
"mlsName": "Sample MLS",
"listingAgentName": "Jordan Example",
"listingAgentPhone": "(555) 010-0100",
"brokerageName": "Sample Realty Group",
"resoFacts": {
"parkingCapacity": 2,
"propertySubType": ["Single Family Residence"]
},
"detailFetched": true,
"scrapedAt": "2026-01-01T00:00:00.000Z"
}

Plan Requirement

Zillow guards its pages with a bot-protection layer that refuses datacenter connections outright. Only residential connections work, so this actor needs a residential connection. The prefilled Proxy & connection setting (Apify Proxy, US) is residential and works out of the box; it is billed by traffic on top of the run itself. A plan without access to residential connections cannot use it: the run logs that the selected connection is unavailable (Apify free plans do not include residential proxies) and then ends as failed with a clear message, so upgrade your plan or supply your own residential connection URLs under Proxy & connection. A datacenter-only setup returns nothing. The actor rotates connections automatically when one is refused. When the residential connection is open on your account but the site keeps refusing its exits, the last attempt of each read goes over a backup connection, and the log says once when the backup served the data. Your own connection URLs never get a backup.

FAQ

How much does it cost?

You pay per result returned, plus a start charge per run. The property page read is a separate charge, applied once per enriched result and only when you switch it on and the record is actually returned. The Pricing tab shows the current rates. Use Max results to cap the cost of any run.

This actor collects only publicly available listing data. You are responsible for how you use it: follow Zillow's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Listing facts (price, beds, baths, address) are generally usable, but photos, descriptions and estimates such as the home value figure may carry additional rights.

Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new and updated properties, and unchanged ones are not billed. Keep Max results high (or 0) on these runs; a small cap can cause the run to stop scanning before it reaches a genuinely new or changed listing, and can return fewer rows, or none, even though changes exist. See the tips under How to Use for the exact mechanics.

Why did a scheduled run suddenly return a lot of EXPIRED rows?

Once a run scans its tracked search completely, previously tracked properties that are no longer found are returned as EXPIRED in that same run. These rows count toward Max results (the whole run, minus the rows already returned), so with a cap the leftover properties stay tracked and a later run reports them; with Max results 0 the whole batch comes at once, and a large swing in local inventory can make it bigger than you expect. Turn emitExpired off if you only want the new and updated delta.

What does it not return?

Coverage is US only. Price history, tax history and school assignments are not returned, because those tables are not published on the pages this actor reads.

Why did my run fail instead of returning an empty dataset?

If the site refuses every request, the run stops with the message "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later." (or, when the account is refused proxy access, "The proxy connection was refused for this account, so no page could be read ..."), so "no listings matched" is never confused with "nothing could be read". Run it again in a few minutes, and check that Proxy & connection is a residential one. A search that genuinely matches nothing ends with "No results matched. Widen the filters, or in URL mode check the link points at a zillow.com search or property page." Property page reads that keep failing stop early instead of being retried for the whole run. If only some locations or links could be read, you still get what was found, and the run says the scan was partial.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

πŸ”— More scrapers you might like

Pair this actor with these related scrapers from the same team:

🏠 Redfin Scraper
Scrape redfin.com home listings: price, beds, baths, sqft, lot, year built, coordinates...
🧩 Homes.com Scraper
Scrape US property records from Homes.com. Pick a city, state or ZIP and a channel (for...
🏠 Realtor.com
Extract property listings from realtor.com. Get comprehensive data, including prices...
🏠 View.com.au Scraper
Scrape View.com.au properties for sale, rent and recently sold across Australia. Search...
🏠 Homes.co.nz Scraper
Scrape Homes.co.nz listings by location or URL with pagination. Extract property details...
🏠 Crexi Scraper
Scrape crexi.com commercial listings: asking price, cap rate, square footage, units, year...

πŸ‘‰ Browse all abotapi scrapers

πŸ’¬ Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • πŸ› οΈ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.
⌂ 捒网址