Zillow Scraper
Pricing
$1.00 / 1,000 results
Zillow Scraper
Extract public Zillow property details from listing URLs, addresses, and city search pages. Export prices, status, location, home facts, photos, listing attribution, and available history.
Pricing
$1.00 / 1,000 results
Rating
0.0
(0)
Developer
MLG Data
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
17 hours ago
Last modified
Categories
Share
Scrape Zillow property details from public listing URLs, street addresses, or city search pages. Export Zillow data to CSV, JSON, or Excel for pricing research, listing monitoring, and property comparisons. This actor is a practical Zillow API alternative for public listing information: a direct detail page can provide listing facts and attribution, while a search page can deliver a larger set of concise property records.
Each output row represents one property. The detailAvailable field tells you whether the actor reached its detail page. This distinction matters: property pages can show description, listing attribution, parking, and more photos, while search cards supply price, address, status, home type, beds, baths, area, and other summary facts. If a detail page is blocked, the actor retains the search card record instead of silently dropping the property.
What data can you extract from Zillow?
The dataset uses stable top level fields. Values depend on the property type, listing status, and what the public page exposes. An empty value does not imply the property lacks that characteristic. It means the relevant public page did not supply the field at collection time.
| Field | Description | Example |
|---|---|---|
zpid | Zillow property identifier. | 11026031 |
detailAvailable | True when the property detail page was read; false when only search card data was available.. | true |
propertyUrl | Canonical property detail URL. | https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/... |
inputUrl | URL requested for this property. | https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/... |
sourceSearchUrl | Search page that yielded the property, when applicable. | null |
listingStatus | Current property status as reported on the page. | FOR_SALE |
homeType | Property type code. | SINGLE_FAMILY |
listingType | Human readable listing category. | For Sale by Agent |
isShowcaseListing | Whether the property uses a showcase listing. | false |
isForSaleByOwner | Whether the property is listed by its owner. | false |
price | Displayed property price in the listed currency. | 487500 |
currency | ISO currency code. | USD |
priceChange | Most recent absolute price change. | -7500 |
priceChangedAt | Date of the most recent price change. | 2026-09-21 |
lastSoldPrice | Price of the last sale when available. | 415000 |
zestimate | Estimated property value when shown. | 478900 |
rentZestimate | Estimated monthly rent when shown. | 2755 |
bedrooms | Bedroom count. | 4 |
bathrooms | Bathroom count. | 3 |
bathroomsFull | Full bathroom count. | 3 |
bathroomsHalf | Half bathroom count. | 0 |
livingArea | Interior area in the displayed unit. | 2582 |
livingAreaUnit | Interior area unit, usually square feet. | null |
yearBuilt | Year of original construction. | null |
lotAreaValue | Numeric lot area. | 0.5 |
lotAreaUnit | Lot area unit. | Acres |
lotSizeSqft | Lot size in square feet when provided. | 21780 |
pricePerSquareFoot | Price divided by interior square feet when supplied. | 189 |
streetAddress | Street address. | 17 Zelma Dr |
city | City. | Greenville |
state | State abbreviation. | SC |
zipCode | Postal ZIP code. | 29617 |
country | Country. | USA |
fullAddress | Combined public property address. | 17 Zelma Dr, Greenville, SC 29617 |
latitude | Latitude of the property. | 34.91575 |
longitude | Longitude of the property. | -82.44426 |
neighborhood | Neighborhood or parent region. | 29617 |
timeZone | Local time zone. | America/New_York |
description | Public listing description. | Public listing text |
datePosted | Date the listing was posted. | 2026-08-09 |
dateSold | Date of the last sale. | 2023-07-10 |
daysOnZillow | Days the listing has been displayed. | 48 |
pageViewCount | Reported page views. | 984 |
favoriteCount | Reported saves or favorites. | 125 |
monthlyHoaFee | Monthly homeowners association fee. | null |
taxAssessedValue | Assessed property tax value. | null |
propertyTaxRate | Property tax rate when shown. | 0.51 |
parkingSpaces | Total parking capacity. | 0 |
hasGarage | Whether a garage is present. | false |
parkingFeatures | Parking features listed in public facts. | ["Driveway", "Parking Pad"] |
agentName | Public listing agent name. | Available when published |
agentPhoneNumber | Public listing agent business phone. | Available when published |
agentEmail | Public listing agent business email when shown. | Available when published |
brokerName | Listing brokerage name. | Available when published |
mlsId | Listing identifier at the listing source. | 1600300 |
mlsName | Name of the listing source. | Available when published |
photoCount | Reported number of photos. | 47 |
mainImageUrl | Main listing photo URL. | Available when published |
photoUrls | Public photo URLs when requested. | ["https://photos.zillowstatic.com/..."] |
virtualTourUrl | Public virtual tour URL. | Available when published |
priceHistory | Price history events exposed in the page payload. | [] |
scrapedAt | UTC timestamp when the record was collected. | UTC timestamp |
The actor preserves numeric values as numbers rather than adding currency signs or units to them. price and currency can be used together for calculations. livingArea, lotAreaValue, and lotAreaUnit should be read together because acreage and square footage are different units. The priceHistory array is present only when exposed in the embedded detail data; an empty array does not mean there has never been a price change.
How to scrape Zillow
- Add one or more property detail URLs, a city search URL, or full street addresses. A typical property URL contains
/homedetails/and ends with a numeric_zpididentifier. A city search URL such ashttps://www.zillow.com/greenville-sc/yields many candidate properties. - Set
maxItemsto cap dataset records. For a city search, choosemaxSearchPagesand the desiredpropertyStatus. Start with one page and a modest item limit before expanding a collection. - Leave
enrichSearchResultsenabled if you want the actor to open each property discovered on a search page. Turn it off if search card facts are sufficient or if the detail pages are heavily blocked. Direct property URLs are always opened as detail pages. - Run the actor and open the dataset. Export the table as JSON, CSV, or Excel. Check
detailAvailablebefore relying on description, agent, parking, or history fields.
The actor removes duplicate property identifiers within a run. If a direct URL and a search page point to the same property, only one row is saved. For a direct URL, the record contains inputUrl equal to the requested URL and sourceSearchUrl is empty. For properties discovered through a city page, sourceSearchUrl records that page.
Input
| Parameter | Type | Default | Description |
|---|---|---|---|
startUrls | URL list | Empty | Public Zillow property detail or city search URLs. |
addresses | String list | Empty | Full street addresses to resolve through public search results. |
propertyStatus | Select | ANY | Filter property cards expanded from a search page: any, for sale, for rent, or recently sold. |
maxSearchPages | Integer | 1 | Maximum search result pages followed, up to 20. |
maxItems | Integer | 100 | Maximum property rows saved. Set zero to remove the item cap. |
enrichSearchResults | Boolean | true | Open property detail pages found in search results. |
includePhotos | Boolean | true | Include available photo URLs in photoUrls. |
proxyConfiguration | Object | Enabled | Connection settings for remote requests. |
A single direct property URL is the best input when you need all publicly exposed details for one listing. A city search URL is better when you need a table of comparable properties. Addresses are resolved by the site's public search path, which may redirect to a matching property. If an address is ambiguous, use a direct property URL to prevent a different match.
Example input for 30 for-sale records from a city search page:
{"startUrls": [{ "url": "https://www.zillow.com/greenville-sc/" }],"propertyStatus": "FOR_SALE","maxSearchPages": 1,"maxItems": 30,"enrichSearchResults": false,"includePhotos": true}
For detailed records, change enrichSearchResults to true or provide the detail URLs themselves. A search run can contain a mix of detailed and summary records because some detail pages may be blocked while the search page remains available. The field detailAvailable makes this visible per row.
Output example
The following selected fields came from a real detail record in the 30 item verification run on September 27, 2026. The listing description and photo list are shortened here for readability. The dataset includes every field listed above, including empty values.
{"zpid": 11026031,"detailAvailable": true,"propertyUrl": "https://www.zillow.com/homedetails/17-Zelma-Dr-Greenville-SC-29617/11026031_zpid/","listingStatus": "FOR_SALE","homeType": "SINGLE_FAMILY","listingType": "For Sale by Agent","price": 487500,"currency": "USD","priceChange": -7500,"priceChangedAt": "2026-09-21","lastSoldPrice": 415000,"zestimate": 478900,"rentZestimate": 2755,"bedrooms": 4,"bathrooms": 3,"livingArea": 2582,"lotAreaValue": 0.5,"lotAreaUnit": "Acres","fullAddress": "17 Zelma Dr, Greenville, SC 29617","latitude": 34.91575,"longitude": -82.44426,"datePosted": "2026-08-09","dateSold": "2023-07-10","daysOnZillow": 48,"photoCount": 47,"description": "Location doesn't get better than this!..."}
That property had a detailed page available. A record from the same city search can show detailAvailable: false while still carrying zpid, status, price, address, home type, bedrooms, bathrooms, area, and estimates from the search card. Treat the two kinds of records differently when building a report that requires complete listing descriptions or attribution.
Use cases
- Comparable listing research: collect active listings in a city, then group homes by location, property type, interior area, beds, and price. Use
pricePerSquareFootwhere the detail page supplies it, or calculate it from numeric price and area. - Price movement monitoring: schedule repeated runs for a stable set of detail URLs and compare
price,priceChange,priceChangedAt, andlistingStatusacross dated datasets. A single run is a snapshot, not a historical archive. - Property intake: enter addresses or property URLs from a research list and standardize the output into fields suitable for a spreadsheet. Keep
zpidas the matching key when refreshing records. - Rental and sale comparisons: use
rentZestimateandzestimatewhere the site publishes them, alongside listed price and property facts. Estimates are site-provided values, not independent valuations. - Listing quality review: identify records with missing photos, description, construction year, or public attribution. Filter on
detailAvailablebefore treating missing detail fields as a listing quality problem. - Geographic review: plot latitude and longitude for properties where the public listing discloses coordinates. Check
fullAddressbefore sharing a location externally.
How much does it cost to scrape Zillow?
The configured dataset event price is $1 per 1,000 delivered property records, or $0.001 per saved row. The count refers to output records, not to every page request. A 30 row run has an event charge of about $0.03; 1,000 rows cost $1.00; and 5,000 rows cost $5.00 at that rate. Your account's live pricing page is the authority for any separate platform or proxy charges.
A search page can contain dozens of property cards, so enrichSearchResults: false can produce a larger dataset with fewer requests. When enrichment is on, each property detail request adds processing time. It does not add an extra result charge for the same property: a property identifier is written once. Residential proxy escalation can also make a blocked detail run more expensive to operate. Start with a smaller maxItems value to measure the actual run time and availability for your target area.
Tips for best results
Use precise property URLs when you need detail fields. The city search path is useful for discovery, but the public card has less information than a property detail page. A full street address with city, state, and ZIP is more reliable than a partial street name; the public resolver can redirect an ambiguous query to another property.
For a large city, set a small maxItems and maxSearchPages: 1 first. Search pages may expose a limited number of results and a finite number of anonymous pages. Increase maxSearchPages only if the initial output shows that your page and status combination yields useful results. The actor follows the search page's next link rather than inventing page numbers.
Check detailAvailable before deciding which fields to require. If it is false, the row came from embedded search card data. Price, status, address, home type, bed and bath count, interior area, coordinates, and estimates can still be present. Description, full photo sets, parking details, and source attribution usually require a detail page. For strict detail-only pipelines, keep only rows where detailAvailable is true and rerun blocked URLs separately later.
Use the date and unit fields carefully. datePosted, dateSold, and priceChangedAt are dates from the public page and can be empty. scrapedAt is the collection timestamp. lotAreaValue may be in acres while livingArea is in square feet. Do not add those measurements together or compare them without converting units.
Limits
The site may return a block page or a rate limit response, especially when many detail pages are opened in one run. The actor starts with a lower cost connection route, rotates the connection after repeated blocks, and may use a residential route when necessary. Search cards are saved as fallback when their detail pages cannot be read. Direct detail URLs have no search card fallback unless the same property also appears in a search input.
The search expander currently follows public city search pages and emits property detail records identified by a _zpid URL. Some rental search pages mostly return apartment or building pages with a different data structure; those entries are skipped. Community and building unit extraction are outside this version's verified scope. A result page can also return fewer rows than requested because of search page limits, duplicate property identifiers, unsupported result types, or blocked pages.
Not every listing publishes every field. A sold or off-market property may not have a current listing price, current agent, or current description. Some property layouts expose price history while others do not. A value may also change between runs as the listing changes. Use zpid, scrapedAt, and detailAvailable to compare snapshots responsibly.
Automated workflows
A scheduled workflow can collect a small city sample each morning and compare the new dataset to the previous day's dataset by zpid. For example: “Collect the first 30 for-sale properties in Greenville and report newly listed properties and price changes.” The comparison step should use the saved datasets because this actor returns the current page snapshot.
A second workflow can enrich a curated list of property URLs: “Open these 20 property detail links and return prices, bedroom counts, interior area, photos, and publicly displayed listing attribution.” Set maxItems to match the list length, then flag any row missing from the dataset for retry. Do not assume a blocked direct URL produced a summary record unless a search page also supplied it.
FAQ
Do I need a login?
No. The actor uses public pages. It does not read private account pages or require account credentials for the target site. Public availability still varies with status, location, and traffic controls.
Why is detailAvailable false?
The row was built from a public search card. This occurs when enrichSearchResults is disabled or when the detail page could not be read after connection retries. Core card fields remain useful, but detail-only fields may be empty.
Can I collect all results from a large city?
The actor follows up to 20 search result pages per run when they are available. The site can cap anonymous search results, and a city may contain more listings than those pages expose. Narrow inputs by city, status, or other public search pages if you need broader coverage.
Does an empty priceHistory mean no price changes?
No. It means the embedded page payload did not expose a history array for that record. The current priceChange and priceChangedAt fields may still be populated separately.
Can I export or schedule the data?
Yes. The dataset can be downloaded in JSON, CSV, and Excel formats and accessed through its dataset endpoint. Schedule repeated runs to maintain time snapshots. Compare them by zpid rather than by address text, which can be reformatted.
Is this data safe to reuse?
Only public page data is collected. Follow the site's terms and applicable privacy laws, and avoid using property or professional contact details for unwanted outreach. Decide the permitted use of the exported data for your project and location.
What if an address resolves to the wrong home?
Use the direct property URL. Address lookup relies on the site's public search redirect and may choose another match when the address is incomplete or ambiguous. Check propertyUrl, zpid, and fullAddress after a lookup.
Integrations
The dataset endpoint can feed reporting jobs, spreadsheets, scheduled comparisons, and webhook based workflows. A common pattern is to run the actor on a schedule, export the latest dataset, match rows by zpid, and write only changed prices or statuses to the destination. Keep the detailAvailable flag in downstream tables so analysts can distinguish a compact search record from a fuller property record.
Support
Open an issue on the Issues tab; we reply within 24h and add fields on request. Include a public property URL, the run date, and the field you expected. This makes it possible to distinguish a missing public field from a parser change or a temporary block.