Zillow Scraper — Listings, Agents, Tax History — $0.8/1k avatar

Zillow Scraper — Listings, Agents, Tax History — $0.8/1k

Pricing

from $0.80 / 1,000 listings

Go to Apify Store
Zillow Scraper — Listings, Agents, Tax History — $0.8/1k

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

Fortuitous Pirate

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

3 days ago

Last modified

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

GoalInput to use
Listings in a city, ZIP or neighborhoodsearchQuery or searchQueries plus filters
Reproduce a search you built on zillow.compaste the URL into startUrls
Look up specific properties by addressaddresses
Full detail records for known Zillow listing URLsstartUrls with /homedetails/ links
Every unit in an apartment buildingbuilding URL plus extractBuildingUnits
Enrich search results with agent, tax and price historyfetchDetails: true
Enrich a dataset from an earlier runsearchResultsDatasetId
Get only listings that appeared since the last runonlyNew: true and a monitorId
Bulk input from a spreadsheetlistUrl (CSV, TXT or Google Sheet)

Output: four kinds of rows

Every row has a recordType so you can tell them apart.

recordTypeWhat it is
listingOne card from a search result (price, address, beds, baths, sqft, status, days on Zillow, photo, URL)
propertyOne 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
unitOne unit of an apartment building or condo complex (unit number, rent or price, beds, baths, sqft, availability, floor plan, deposit, pets)
buildingThe building summary (name, address, phone, floor plans, amenities, pet policy, walk, transit and bike scores)

Search card fields (listing)

FieldExample
zpid"29388433"
statusType, statusText, listingSubType"FOR_SALE", "Active", "For Sale by Agent"
price, priceText485000, "$485,000"
zestimate, rentZestimate, taxAssessedValuenull, null, 417445
address, street, city, state, zipcode"1905 E 18th St, Austin, TX 78702"
latitude, longitude30.2787, -97.7204
beds, baths, livingAreaSqft2, 1, 900
lotAreaValue, lotAreaUnit3920.4, "sqft"
homeType, homeStatus"SINGLE_FAMILY", "FOR_SALE"
daysOnZillow, timeOnZillowText, listedAt0, "2 minutes ago", "2026-10-21"
pricePerSqft, priceChange, datePriceChanged539, null, null
brokerName"Beycome Brokerage Realty LLC"
isZillowOwned, has3DTour, isFeaturedfalse
imageUrl, detailUrllisting 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)

GroupFields
Listing agentagentName, agentPhone, agentLicense, agentEmail (only when Zillow publishes it)
Co-agentcoAgentName, coAgentPhone, coAgentLicense
BrokerbrokerName, brokerPhone
MLSmlsId, mlsName, listingAgents[], listingOffices[], listingLastUpdated
Price historypriceHistory[] with date, price, event, source, pricePerSqft, priceChangeRate; also listedDate, lastPriceCut, lastSoldPrice
Tax historytaxHistory[] with year, date, taxPaid, assessedValue, taxIncreaseRate, valueIncreaseRate
Parcel and areaparcelId, county, countyFIPS, neighborhood
Demand signalspageViewCount, favoriteCount
CostsmonthlyHoaFee, hoaFee, propertyTaxRate, annualHomeownersInsurance, mortgageRates (30-year fixed, 15-year fixed, 5/1 ARM)
Schoolsschools[] with name, rating, grades, distanceMiles, link
Description and factsdescription, yearBuilt, homeType, facts{} (all of Zillow's property facts), appliances, cooling, heating, flooring, parkingFeatures, laundryFeatures
Mediaphotos[] (up to 50 full-size URLs), photoCount, virtualTourUrl, floorPlanUrl
NearbynearbyHomes[] (up to 10, with zpid, price, beds, baths, address)
RentalsleaseTerm, depositsAndFees, applicationFee, rentalFees{}, petsAllowed, allowedPets, petPolicyText, specialOffers[]
Address lookupinput, inputAddress, matchedAddress show which input produced the row
SourcedetailsSource (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

InputMeaning
listingTypeforSale, forRent, sold
sortBydays, priceLowToHigh, priceHighToLow, newest, beds, baths, sqft, lotSize, relevance
minPrice, maxPricePrice, or monthly rent for rentals
minBeds, maxBeds0 includes studios
minBaths, maxBathsHalves allowed
minSqft, maxSqftLiving area
minLotSize, maxLotSizeSquare feet (1 acre = 43,560)
minYearBuilt, maxYearBuiltYear built
maxHoaMonthly HOA cap, 0 for no HOA
homeTypeshouses, townhomes, condos/co-ops, multi-family, apartments, lots/land, manufactured
saleStatusby agent, by owner (FSBO), new construction, foreclosure, auction, coming soon, pending, accepting backup offers
soldInLastDays7, 30, 90, 180, 365, 1095 (recently sold only)
daysOnZillow1, 7, 14, 30, 90, 6m, 12m, 24m, 36m
featurespool, A/C, waterfront, basement, garage, single story, city, water, park or mountain view, 3D tour, open house
rentalFeatureslarge dogs, small dogs, cats, in-unit laundry, on-site parking, accepts online applications, income restricted, entire place, room for rent
keywordsfree 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:

ValueRows returned
disabledOne row per building (default)
allEvery unit
for_rentUnits for rent
for_saleUnits for sale
recently_soldRecently sold units
off_marketOff-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

InputMeaning
maxItemsMaximum rows per location, search URL or building. Default 10, maximum 820. Addresses and property URLs are always all returned
propertyStatusOptional hint (FOR_SALE, FOR_RENT, RECENTLY_SOLD) for addresses and URLs. Status is detected automatically, so you rarely need it
datasetNameWrite results to a named dataset in your account instead of the run's default dataset
proxyConfigurationDefaults 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: sold with soldInLastDays for 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 listUrl and 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.

EventPrice
Actor start (once per GB of memory, 1 GB here)$0.001
Each row returned$0.0008
RowsCost
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 ApifyClient
client = 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 agentEmail is frequently null. 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; taxHistory and parcelId depend on what the county and MLS publish. Missing values are null, never invented.
  • Zestimate fields are returned when Zillow includes them in the data and are null otherwise.
  • 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 detailsSource tells 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.