Zillow Scraper — Listings, Agents, Tax History — $0.8/1k
Pricing
from $0.80 / 1,000 listings
Zillow Scraper — Listings, Agents, Tax History — $0.8/1k
Zillow Scraper for sale, rent and sold listings by search, address or URL. Agent phone and license, MLS id, tax and price history, building units, new-listing monitor. No login or cookies. MCP-ready for AI agents. $0.8 per 1,000 records.
Pricing
from $0.80 / 1,000 listings
Rating
0.0
(0)
Developer
Fortuitous Pirate
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Zillow Scraper: listings, property details, agents, price and tax history
Zillow Scraper turns any Zillow search, address or listing URL into clean structured records. Search by city, ZIP or neighborhood with the filters Zillow itself offers, paste a Zillow search URL exactly as it appears in your browser, look up properties by street address, or chain a dataset of results into full property details. No login, no cookies, no API key.
It covers all three markets (for sale, for rent, recently sold), returns the listing agent with phone and license number, the broker, the MLS id, the full price history and tax history, schools, parcel id, page views, favorites, mortgage rates and photos, and can expand apartment buildings into one row per unit. A built-in monitor returns only listings you have not seen before, so a daily schedule becomes a new-listing feed.
Price: $0.80 per 1,000 rows plus a $0.001 start fee. A row with full agent, tax and price history costs the same as a search card.
What you can do with it
| Goal | Input to use |
|---|---|
| Listings in a city, ZIP or neighborhood | searchQuery or searchQueries plus filters |
| Reproduce a search you built on zillow.com | paste the URL into startUrls |
| Look up specific properties by address | addresses |
| Full detail records for known Zillow listing URLs | startUrls with /homedetails/ links |
| Every unit in an apartment building | building URL plus extractBuildingUnits |
| Enrich search results with agent, tax and price history | fetchDetails: true |
| Enrich a dataset from an earlier run | searchResultsDatasetId |
| Get only listings that appeared since the last run | onlyNew: true and a monitorId |
| Bulk input from a spreadsheet | listUrl (CSV, TXT or Google Sheet) |
Output: four kinds of rows
Every row has a recordType so you can tell them apart.
| recordType | What it is |
|---|---|
listing | One card from a search result (price, address, beds, baths, sqft, status, days on Zillow, photo, URL) |
property | One property with the full record: agent, broker, MLS, history, schools, facts. Returned for addresses, /homedetails/ URLs, dataset chaining and search rows when fetchDetails is on |
unit | One unit of an apartment building or condo complex (unit number, rent or price, beds, baths, sqft, availability, floor plan, deposit, pets) |
building | The building summary (name, address, phone, floor plans, amenities, pet policy, walk, transit and bike scores) |
Search card fields (listing)
| Field | Example |
|---|---|
zpid | "29388433" |
statusType, statusText, listingSubType | "FOR_SALE", "Active", "For Sale by Agent" |
price, priceText | 485000, "$485,000" |
zestimate, rentZestimate, taxAssessedValue | null, null, 417445 |
address, street, city, state, zipcode | "1905 E 18th St, Austin, TX 78702" |
latitude, longitude | 30.2787, -97.7204 |
beds, baths, livingAreaSqft | 2, 1, 900 |
lotAreaValue, lotAreaUnit | 3920.4, "sqft" |
homeType, homeStatus | "SINGLE_FAMILY", "FOR_SALE" |
daysOnZillow, timeOnZillowText, listedAt | 0, "2 minutes ago", "2026-10-21" |
pricePerSqft, priceChange, datePriceChanged | 539, null, null |
brokerName | "Beycome Brokerage Realty LLC" |
isZillowOwned, has3DTour, isFeatured | false |
imageUrl, detailUrl | listing photo and Zillow page |
searchQuery, scrapedAt | "Austin, TX", ISO timestamp |
Rental cards also carry baseRent, availabilityDate, specialOffer and unitCount where Zillow shows them.
Property detail fields (property, or listing with fetchDetails)
| Group | Fields |
|---|---|
| Listing agent | agentName, agentPhone, agentLicense, agentEmail (only when Zillow publishes it) |
| Co-agent | coAgentName, coAgentPhone, coAgentLicense |
| Broker | brokerName, brokerPhone |
| MLS | mlsId, mlsName, listingAgents[], listingOffices[], listingLastUpdated |
| Price history | priceHistory[] with date, price, event, source, pricePerSqft, priceChangeRate; also listedDate, lastPriceCut, lastSoldPrice |
| Tax history | taxHistory[] with year, date, taxPaid, assessedValue, taxIncreaseRate, valueIncreaseRate |
| Parcel and area | parcelId, county, countyFIPS, neighborhood |
| Demand signals | pageViewCount, favoriteCount |
| Costs | monthlyHoaFee, hoaFee, propertyTaxRate, annualHomeownersInsurance, mortgageRates (30-year fixed, 15-year fixed, 5/1 ARM) |
| Schools | schools[] with name, rating, grades, distanceMiles, link |
| Description and facts | description, yearBuilt, homeType, facts{} (all of Zillow's property facts), appliances, cooling, heating, flooring, parkingFeatures, laundryFeatures |
| Media | photos[] (up to 50 full-size URLs), photoCount, virtualTourUrl, floorPlanUrl |
| Nearby | nearbyHomes[] (up to 10, with zpid, price, beds, baths, address) |
| Rentals | leaseTerm, depositsAndFees, applicationFee, rentalFees{}, petsAllowed, allowedPets, petPolicyText, specialOffers[] |
| Address lookup | input, inputAddress, matchedAddress show which input produced the row |
| Source | detailsSource (graphql or page), detailsFetched |
A real address lookup row
Input 67 Morton St #6E, New York, NY 10014, abbreviated, values as returned:
{"recordType": "property","zpid": "72537851","statusType": "FOR_SALE","price": 1550000,"address": "67 Morton St APT 6E, New York, NY 10014","beds": 2,"baths": 1,"homeType": "CONDO","yearBuilt": 1924,"daysOnZillow": 35,"hoaFee": "$1,765 monthly","monthlyHoaFee": 1765,"agentName": "Deanna Lloyd","agentPhone": "757-572-0107","agentLicense": "10401270268","brokerName": "Brown Harris Stevens","mlsId": "S1847856","mlsName": "StreetEasy","county": "New York County","neighborhood": "West Village","pageViewCount": 747,"favoriteCount": 35,"mortgageRates": { "thirtyYearFixed": 7.583, "fifteenYearFixed": 7.438, "arm5": null },"priceHistory": [{ "date": "2026-09-16", "price": 1550000, "event": "Listed for sale", "source": "StreetEasy", "priceChangeRate": -0.0606 },{ "date": "2026-07-31", "price": 1650000, "event": "Listing removed", "source": "StreetEasy", "priceChangeRate": 0 }],"schools": [{ "name": "Ps 3 Charrette School", "rating": 6, "grades": "PK-5", "distanceMiles": 0.1 }],"detailUrl": "https://www.zillow.com/homedetails/67-Morton-St-APT-6E-New-York-NY-10014/72537851_zpid/"}
A real search card (listing)
{"recordType": "listing","zpid": "29388433","statusType": "FOR_SALE","statusText": "Active","listingSubType": "For Sale by Agent","price": 485000,"priceText": "$485,000","taxAssessedValue": 417445,"address": "1905 E 18th St, Austin, TX 78702","latitude": 30.2787,"longitude": -97.7204,"beds": 2,"baths": 1,"livingAreaSqft": 900,"lotAreaValue": 3920.4,"lotAreaUnit": "sqft","homeType": "SINGLE_FAMILY","daysOnZillow": 0,"timeOnZillowText": "2 minutes ago","brokerName": "Beycome Brokerage Realty LLC","listedAt": "2026-10-21","pricePerSqft": 539,"detailUrl": "https://www.zillow.com/homedetails/1905-E-18th-St-Austin-TX-78702/29388433_zpid/","searchQuery": "Austin, TX"}
A real building unit (unit)
{"recordType": "unit","zpid": "466040793","unitNumber": "Unit 00A-A104","statusType": "FOR_RENT","price": 2206,"baseRent": 2206,"beds": 0,"baths": 1,"livingAreaSqft": 405,"floorPlanName": "S1","availabilityDate": "now","depositsAndFees": 500,"allowedPets": ["Cats"],"monthlyFeesMin": 93,"monthlyFeesMax": 93,"buildingName": "AVA Pacific Beach","buildingZpid": "465266495","street": "3883 Ingraham St","city": "San Diego","state": "CA","zipcode": "92109"}
Input guide
1. Search by location
{ "searchQuery": "Austin, TX", "listingType": "forSale", "maxItems": 50 }
Use searchQueries for a list of locations in one run (ZIP codes, cities, neighborhoods, counties). maxItems applies to each location. Every row carries the searchQuery it came from.
With no input at all the actor returns a 10-listing sample for Austin, TX, so a bare test run always shows real data.
2. Paste a Zillow search URL
Set filters on zillow.com (map area, price, beds, home type, anything), copy the address bar, and paste it:
{ "startUrls": [{ "url": "https://www.zillow.com/homes/for_rent/?searchQueryState=..." }], "maxItems": 100 }
The filters in the URL are replayed as they are, so the results match what you saw in the browser. Verified with a rental search capped at $3,000 and 2+ bedrooms: the filters were honored. You can mix search URLs, property URLs and building URLs in the same list. searchUrls is accepted as an alias of startUrls.
3. Look up addresses
{ "addresses": ["17199 Park Ave, Sonoma, CA 95476", "67 Morton St #6E, New York, NY 10014"] }
Each address is matched to its Zillow property and returned as one full property row. Add the unit for apartments and condos (#6E, Apt 2); without a unit the whole-property match is used. An address Zillow cannot match produces no row, no charge, and a not_found entry in the run's OUTPUT record.
4. Property detail pages
{ "startUrls": [{ "url": "https://www.zillow.com/homedetails/1905-E-18th-St-Austin-TX-78702/29388433_zpid/" }] }
Every /homedetails/ URL returns its full record. detailUrls (older input) still works and does the same.
5. Full filter set
| Input | Meaning |
|---|---|
listingType | forSale, forRent, sold |
sortBy | days, priceLowToHigh, priceHighToLow, newest, beds, baths, sqft, lotSize, relevance |
minPrice, maxPrice | Price, or monthly rent for rentals |
minBeds, maxBeds | 0 includes studios |
minBaths, maxBaths | Halves allowed |
minSqft, maxSqft | Living area |
minLotSize, maxLotSize | Square feet (1 acre = 43,560) |
minYearBuilt, maxYearBuilt | Year built |
maxHoa | Monthly HOA cap, 0 for no HOA |
homeTypes | houses, townhomes, condos/co-ops, multi-family, apartments, lots/land, manufactured |
saleStatus | by agent, by owner (FSBO), new construction, foreclosure, auction, coming soon, pending, accepting backup offers |
soldInLastDays | 7, 30, 90, 180, 365, 1095 (recently sold only) |
daysOnZillow | 1, 7, 14, 30, 90, 6m, 12m, 24m, 36m |
features | pool, A/C, waterfront, basement, garage, single story, city, water, park or mountain view, 3D tour, open house |
rentalFeatures | large dogs, small dogs, cats, in-unit laundry, on-site parking, accepts online applications, income restricted, entire place, room for rent |
keywords | free text such as casita, no hoa, workshop |
Example, new construction houses with a pool under $900,000, newest first:
{"searchQuery": "Phoenix, AZ","listingType": "forSale","homeTypes": ["house"],"saleStatus": ["newConstruction"],"features": ["pool"],"maxPrice": 900000,"sortBy": "newest","maxItems": 100}
Zillow shows about 820 results for any one search. To go deeper, split the search by ZIP code or narrow the price range.
6. Apartment buildings: extractBuildingUnits
Apartment communities and condo complexes appear on Zillow as one card. By default you get one building row. Set extractBuildingUnits to return one row per unit instead:
| Value | Rows returned |
|---|---|
disabled | One row per building (default) |
all | Every unit |
for_rent | Units for rent |
for_sale | Units for sale |
recently_sold | Recently sold units |
off_market | Off-market units |
It works for building URLs (/b/... or /apartments/...) and for building cards found inside a search. Unit rows show unit number, rent or price, beds, baths, sqft, availability date, floor plan, deposit, monthly fees, pet rules and the building's special offers.
Building pages are Zillow's most protected surface. They are occasionally refused; the actor retries with a fresh session several times. If a building page still cannot be loaded inside a search, you get the building card instead of its units, so you never lose the result. Units expanded from a search card are the building's units for the status you chose; they are not re-filtered by the search's price or bed filters.
7. Enrich search results: fetchDetails
{ "searchQuery": "92109", "listingType": "forSale", "maxItems": 20, "fetchDetails": true }
Each search row gets the full property record (agent, MLS, tax and price history, schools, and the rest). It costs a little more time per listing, not more money: the price per row stays the same.
8. Dataset chaining: searchResultsDatasetId
Run a search first, then pass its dataset id:
{ "searchResultsDatasetId": "YOUR_DATASET_ID" }
Every row that has a property URL or zpid (fields detailUrl, url, propertyUrl, hdpUrl or zpid) is fetched with full details. It works with the output of this actor and of other Zillow actors.
9. Only new listings (monitor)
{ "searchQuery": "Austin, TX", "daysOnZillow": "1", "onlyNew": true, "monitorId": "austin-new" }
The actor remembers every listing it returned under that monitor name and returns only listings it has not delivered before. Schedule the actor daily and you get a feed of new listings. Use a different monitorId for each saved search. The run summary reports how many already-seen listings were skipped. You are charged only for the rows returned.
10. Bulk input from a file: listUrl
Link to a CSV, TXT or Google Sheet (shared as "anyone with the link") with one entry per line: street addresses, ZIP codes or cities, and Zillow URLs can be mixed. A header row is skipped; a column named address, url, zip, location or query is used if present, otherwise the first column.
Other inputs
| Input | Meaning |
|---|---|
maxItems | Maximum rows per location, search URL or building. Default 10, maximum 820. Addresses and property URLs are always all returned |
propertyStatus | Optional hint (FOR_SALE, FOR_RENT, RECENTLY_SOLD) for addresses and URLs. Status is detected automatically, so you rarely need it |
datasetName | Write results to a named dataset in your account instead of the run's default dataset |
proxyConfiguration | Defaults to Apify residential proxy in the US. Zillow blocks datacenter IPs, so leave it on |
Run summary
Each run saves an OUTPUT record in the default key-value store with the number of rows, the targets processed, which targets failed and why (not_found, failed), and, for monitors, the number of skipped already-seen listings. A failed target never discards the rows that succeeded.
Use cases
- Lead generation for agents and lenders. Pull recently listed or price-cut homes with the listing agent's name, phone and license number.
- Investor deal flow. Filter by foreclosure, auction, FSBO, coming soon or days on Zillow, then enrich with tax history, price history and parcel id.
- Comparable sales. Run
listingType: soldwithsoldInLastDaysfor a ZIP, then add details for the sold price history. - Rental market analysis. Pull rents by ZIP and bedroom count, expand buildings to unit level with
extractBuildingUnits, and track specials, deposits and pet rules. - Portfolio and address enrichment. Feed a spreadsheet of addresses through
listUrland get parcel id, county, tax history, page views and MLS id for each. - AI agents. Call the actor from an MCP-enabled assistant to answer questions about listings, rents and agents with live data.
Pricing
This actor uses pay-per-event pricing.
| Event | Price |
|---|---|
| Actor start (once per GB of memory, 1 GB here) | $0.001 |
| Each row returned | $0.0008 |
| Rows | Cost |
|---|---|
| 100 | $0.081 |
| 1,000 | $0.801 |
Full property records, unit rows and building rows cost the same as search cards. Rows you do not receive are not charged: unmatched addresses and already-seen monitor listings cost nothing.
Using the data
API (Python):
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("fortuitous_pirate/zillow-listings-scraper").call(run_input={"searchQuery": "92109","listingType": "forRent","maxItems": 50,"fetchDetails": True,})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["address"], row["price"], row.get("agentName"), row.get("agentPhone"))
API (JavaScript):
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('fortuitous_pirate/zillow-listings-scraper').call({addresses: ['17199 Park Ave, Sonoma, CA 95476'],});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items[0].taxHistory);
Schedules and webhooks. Schedule a monitor daily in Apify Console and add a webhook to receive the dataset.
No-code tools. The actor works with Make, Zapier, n8n and Google Sheets through the Apify integrations. Export results as JSON, CSV, Excel or XML from the dataset page.
MCP. The actor can be called as a tool from MCP-compatible AI assistants through the Apify MCP server.
Limits and good to know
- About 820 results per search. That is Zillow's own cap. Split large areas by ZIP code, price band or home type.
- Agent email is often empty. Zillow shows an agent's email only on some listings (mostly not on MLS-fed listings), so
agentEmailis frequentlynull. Name, phone and license are the dependable contact fields. - Some fields depend on the listing. Rental fields (specials, lease term, fees, pet policy) are filled for rentals;
taxHistoryandparcelIddepend on what the county and MLS publish. Missing values arenull, never invented. - Zestimate fields are returned when Zillow includes them in the data and are
nullotherwise. - Building pages are occasionally refused by Zillow and retried with a new session. If one cannot be loaded, the building card is returned instead.
- Residential proxy is used. Zillow rejects datacenter traffic. The default proxy setting is correct; do not switch to a datacenter group.
- If Zillow changes its site, the actor re-reads the current page definitions and retries before falling back to the property page, and
detailsSourcetells you which path produced the row.
FAQ
Do I need a Zillow account or cookies? No.
Can I scrape rentals and sold homes? Yes. Set listingType to forRent or sold.
How do I get the listing agent's phone number? Use addresses, /homedetails/ URLs or fetchDetails: true. The agentPhone and agentLicense fields are filled when Zillow shows them.
Can I paste a search URL from my browser? Yes, in startUrls, with all the filters you set on zillow.com.
How do I get only new listings? Turn on onlyNew and give the search a monitorId, then schedule the actor.
How do I get unit-level data for an apartment building? Pass the building URL and set extractBuildingUnits to for_rent, for_sale, all, and so on.
Is this legal? The actor collects publicly visible listing data. You are responsible for using it in line with Zillow's terms, applicable law and data-protection rules, especially when you use agent contact details for outreach.
Something looks wrong in a run. Open an issue on the actor page with the run link. Zillow changes its site often.