Zillow Property & Agent Data Scraper avatar

Zillow Property & Agent Data Scraper

Pricing

Pay per event

Go to Apify Store
Zillow Property & Agent Data Scraper

Zillow Property & Agent Data Scraper

Extract Zillow property listings with agent contacts (emails, phones), price history, and 70+ data fields. Three search modes: ZIP codes, ZPID list, or any Zillow URL. 40+ filters including tri-state controls for auctions, foreclosures, and new construction. Volume discounts - save up to 37.5%!

Pricing

Pay per event

Rating

4.7

(3)

Developer

Andrey Afanasenko

Andrey Afanasenko

Maintained by Community

Actor stats

8

Bookmarked

408

Total users

68

Monthly active users

7.7 hours

Issues response

6 days ago

Last modified

Share

Apify Actor

Find homes for sale, rent, and sold across the US — get listing details, photos, and agent contacts in one structured row per property. From $0.05 per property on paid plans, $0.08 on Free.

Zillow's public API only covers properties you own or sell on the Zillow brand network. This actor reads anything Zillow shows in the browser — full filter set, agent emails and phone numbers, price-history arrays, school ratings, photo galleries, and 70+ output columns per row.


🎯 What it does

Three input shapes — pick the one that matches what you have:

ModeInputWhat it returns
1: ZIP Code Search (mode: "zip")ZIP codes + 40+ filtersListings Zillow returns for those ZIPs, enriched. Most-used mode (74% of runs). Cost cap: maxPropertiesPerZip.
2: ZPID List (mode: "zpid")Known ZPIDsEnrichment-only — full property + agent + history per ZPID. Filters and Walk/Photos enrichments ignored.
3: Zillow URL (mode: "url")One zillowUrl (search / sold / single-listing)Whatever the URL resolves to upstream, enriched. Filters embedded in the URL.

Each row carries the listing essentials (price, status, address, beds/baths, sqft, year built), the financial layer (Zestimate, rent Zestimate, HOA fee, property tax, last-sold, full price history), the agent contact layer (agent name, email, phone, license, brokerage), and the property-detail layer (heating, cooling, appliances, view, fireplace, pool, garage, photos, schools).

ZIP-code mode adds 40+ filters that narrow the search before the actor pays for an enrichment. Tri-state filters (isAuction, isNewConstruction, isForSaleForeclosure) accept any / only / exclude, so you can flip a single field to filter foreclosures out without losing the rest of your filter set. Optional enrichments — Walk Score / Transit Score / Bike Score and full photo galleries — attach extra columns when you enable them.


📦 Output sample

One dataset row, ZIP mode, listing in Beverly Hills with full enrichment enabled:

{
"zpid": "20533889",
"hdpUrl": "https://www.zillow.com/homedetails/123-Palm-Dr-Beverly-Hills-CA-90210/20533889_zpid/",
"price": 5500000,
"status": "ForSale",
"homeType": "SINGLE_FAMILY",
"streetAddress": "123 Palm Dr",
"city": "Beverly Hills",
"state": "CA",
"zipcode": "90210",
"county": "Los Angeles County",
"neighborhood": "Beverly Hills Flats",
"latitude": 34.0901,
"longitude": -118.4065,
"bedrooms": 5,
"bathrooms": 4,
"bathroomsFull": 3,
"bathroomsHalf": 2,
"livingArea": 3500,
"lotSize": "10,890 sqft",
"yearBuilt": 2010,
"stories": 2,
"architecturalStyle": "Contemporary",
"agentName": "Jane Doe",
"agentEmail": "jane@example-realty.com",
"agentEmailSource": "property_details",
"cellPhone": "310-555-0199",
"brokerName": "Luxury Real Estate Inc.",
"zestimate": 5600000,
"rentZestimate": 18500,
"pricePerSqft": 1571,
"hoaFee": 500,
"propertyTax": 68500,
"priceChange": -100000,
"datePriceChanged": "2026-04-12",
"hasPool": true,
"hasGarage": true,
"garageSpaces": 3,
"hasBasement": false,
"view": "City, Mountain(s)",
"heating": "Forced Air, Natural Gas",
"cooling": "Central Air",
"daysOnZillow": 14,
"lastSoldDate": "2018-06-22",
"lastSoldPrice": 4250000,
"lastTaxAssessedValue": 4400000,
"priceHistory": [
{"date": "2026-04-12", "price": 5500000, "event": "Price changed", "pricePerSquareFoot": 1571, "source": "Listing", "postingIsRental": false},
{"date": "2018-06-22", "price": 4250000, "event": "Sold", "pricePerSquareFoot": 1214, "source": "Public Record", "postingIsRental": false}
],
"schools": [
{"name": "Beverly Vista Elementary", "level": "Elementary", "rating": 9, "distance": 0.6}
],
"mainPhoto": "https://photos.zillowstatic.com/fp/abc123-uncropped_scaled_within_1536_1152.jpg",
"photos": ["https://photos.zillowstatic.com/fp/abc123-uncropped_scaled_within_1536_1152.jpg"],
"walkScore": 95,
"transitScore": 80,
"bikeScore": 88,
"listingType": "FSBA, openHouse"
}

74 columns are documented in the .actor/dataset_schema.json — you can see every column's type, description, and example in the Apify Console's dataset view.


⚡ Quick start

  1. Pick a mode: ZIP codes (discover), ZPID list (enrich knowns), or Zillow URL (browser-configured filters).
  2. Fill in the inputs for that mode. The other modes' inputs are ignored.
  3. (Optional) Toggle enrichments — Walk Score and Photos — for ZIP mode.
  4. Run the actor.
  5. Download in JSON / CSV / Excel / XML, or read the dataset programmatically (see § Programmatic / API use).

Minimal ZIP-mode input:

{
"mode": "zip",
"zipCodes": ["94103"],
"maxPropertiesPerZip": 5
}

That's a single ZIP, capped at 5 properties — under $0.50 to test on the free plan.


🛠 Input

The input schema is grouped into the following sections (open the Input tab in the Apify Console for the full UI):

  • Operation Modemode ("zip" / "zpid" / "url").
  • ZIP Mode InputszipCodes, maxPropertiesPerZip.
  • Search Filters (ZIP only)status_type, price_min/max, rentMinPrice/MaxPrice, beds_min/max, baths_min/max, doz, sort, keywords.
  • Home TypeisSingleFamily, isTownhouse, isCondo, isMultiFamily, isApartment, isManufactured, isLotLand.
  • Listing Type & StatusisForSaleByOwner, isForSaleByAgent, isNewConstruction, isAuction, isForSaleForeclosure, includeForeclosed, includePreForeclosure, isPendingUnderContract, isAcceptingBackupOffers.
  • Property Featuressqft_min/max, lotSize_min/max, built_min/max, parkingSpots_min, hasGarage, hasPool, hasAirConditioning, isWaterfront, isBasementFinished, isBasementUnfinished, hoa_max.
  • View FiltersisCityView, isMountainView, isParkView, isWaterView.
  • Tour FiltersisOpenHousesOnly, is3dHome.
  • Rental-Only Filters — pet policies (largeDogsAllowed, smallDogsAllowed, catsAllowed, noPets) + amenities (inUnitLaundry, furnished, hardwoodFloor, utilitiesIncluded, disabledAccess, shortTermLease, outdoorSpace, controlledAccess, highSpeedInternet, elevator, acceptsApplications, incomeRestricted, parkingAvailable).
  • School Filtersschools, schoolsRating, includeUnratedSchools.
  • ZPID Mode Inputszpids.
  • URL Mode InputszillowUrl.
  • Enrichment Options (ZIP only)enrichWalkScore, enrichPhotos.

Highlights:

  • Tri-state filters (isAuction, isNewConstruction, isForSaleForeclosure) accept any (no filter), only (require), or exclude (block). Flip one to exclude to drop foreclosures without losing your other filter logic.
  • Filter and enrichment options are silently ignored in ZPID and URL modes — they're not errors, they just don't apply.
  • Free plan caps: 15 properties / 20 ZIPs per run, agent emails masked. See § Free vs paid plan.

JSON snippets per mode:

{ "mode": "zip", "zipCodes": ["94103"], "status_type": "ForSale", "maxPropertiesPerZip": 50, "isAuction": "exclude", "hasPool": true }
{ "mode": "zpid", "zpids": ["20521978", "95547747"] }
{ "mode": "url", "zillowUrl": "https://www.zillow.com/homes/for_rent/?searchQueryState=..." }

💰 Pricing

Pay-per-event. You pay only when the actor finishes enriching a property — not for failed lookups, ZIPs that produced zero matches, or URL fetches that didn't yield a property.

EventTriggerFreeBronzeSilverGoldPlatinumDiamond
apify-actor-startActor starts (1 event per GB of memory, minimum 1)$0.00005$0.00005$0.00005$0.00005$0.00005$0.00005
PROPERTY_ENRICHEDDetailed property info fetched (price, agent contacts, price history, specs)$0.08$0.07$0.06$0.05$0.05$0.05

Cost math:

  • 100 properties on Free ≈ 100 × $0.08 + actor-start ≈ $8.00
  • 100 properties on Diamond ≈ 100 × $0.05 + actor-start ≈ $5.00
  • 1,000 properties on Diamond ≈ 1,000 × $0.05 + actor-start ≈ $50.00

The actor self-bounds via budgetManager — it stops paying for new enrichments once the budget cap is reached, and records freeLimitBudget to the FREE_LIMITS_APPLIED storage record. You can set a custom per-run budget in the input.


🆓 Free vs paid plan

PlanMax properties / runMax ZIPs / runAgent emailsPer-event price
Free1520Masked (j***@e***.com)$0.08 / PROPERTY_ENRICHED
Paid (Bronze → Diamond)Unlimited (budget-bounded)UnlimitedFull (jane@example.com)$0.07 → $0.05 / PROPERTY_ENRICHED

Free-plan ceilings hit during a run are recorded to the FREE_LIMITS_APPLIED storage record so API consumers can switch on them without log-parsing.


🧪 Filter recipes

Single-family for-sale homes in 90210, exclude auctions, must have pool:

{
"mode": "zip",
"zipCodes": ["90210"],
"status_type": "ForSale",
"maxPropertiesPerZip": 50,
"isSingleFamily": true,
"isCondo": false,
"isAuction": "exclude",
"hasPool": true
}

New-construction-only in three Texas ZIPs:

{
"mode": "zip",
"zipCodes": ["78701", "78704", "78745"],
"status_type": "ForSale",
"isNewConstruction": "only",
"maxPropertiesPerZip": 100
}

Furnished pet-friendly rentals in NYC with in-unit laundry:

{
"mode": "zip",
"zipCodes": ["10001", "10011"],
"status_type": "ForRent",
"rentMinPrice": 2500,
"rentMaxPrice": 6000,
"beds_min": 1,
"largeDogsAllowed": true,
"inUnitLaundry": true,
"furnished": true
}

Re-enrich a saved list of ZPIDs (ZPID mode):

{
"mode": "zpid",
"zpids": ["20521978", "95547747", "12345678"]
}

🔁 Resume / checkpoint

Long ZIP-mode runs are checkpointed automatically. If the run is aborted, paused, or hits the platform timeout, resurrecting the run picks up from the last checkpoint instead of restarting — you don't pay for already-enriched properties twice.

Resurrect from the Apify Console: open the aborted run → Resurrect button. The next run instance reads the actor's per-run KVS state and skips the already-processed batch. Live progress is mirrored to the status.html storage record while the run is active.


📡 Live status & storage records

The actor writes structured records to its key-value store on every run. Read them with Actor.getValue(<KEY>) from another actor, or fetch them via the REST API.

KeyWhat it isWhen
RUN_SUMMARYJSON object with search params, property counts, email-discovery rates, billing totals, and any free-tier limits hit during the run.End of every run.
status.htmlAuto-updating HTML status page with live scrape progress, budget, and ETA. Open from the Storage tab while the run is active.Streaming throughout the run.
FREE_LIMITS_APPLIEDArray<{id, message}> — every free-tier ceiling hit during the run (property cap, ZIP cap, budget exhaustion, email masking). Empty / omitted on paid runs.End of every free-plan run.
USER_MESSAGE{id, title, body} onboarding banner shown to a paying user on their 1st and 3rd paid run. Empty / omitted otherwise.First / third paid run only.
SKIPPED_ITEMSPer-item list of zpids / ZIPs / URLs skipped during the run, with reason and category (filter / not_found / error / free_limit). Useful to re-run the error cohort.End of every run.

🤖 Programmatic / API use

Start a run from your own code via the Apify REST API:

TOKEN="<your-apify-token>"
ID=YwkoMBHoFxCLI4gpM
# Start a synchronous run + read dataset
curl -s -X POST "https://api.apify.com/v2/acts/$ID/run-sync-get-dataset-items?token=$TOKEN&format=json" \
-H 'Content-Type: application/json' \
-d '{"mode":"zip","zipCodes":["94103"],"maxPropertiesPerZip":5}'

Read the run-end summary from another script:

RUN_ID="<run-id-from-the-launch-call>"
curl -s "https://api.apify.com/v2/actor-runs/$RUN_ID/key-value-store/records/RUN_SUMMARY?token=$TOKEN"

The actor is also available via the Apify MCP server (https://mcp.apify.com) — any MCP-aware client (Claude Desktop, Cursor, etc.) can call it as a tool. Input + output schemas in this repo are the source of truth the MCP client reads to build the call signature.


❓ FAQ

The actor extracts only publicly available property listing data; private user data is never touched. Listings include personal information for licensed agents (a public role), which can fall under GDPR and similar regimes — make sure you have a legitimate basis to process it. If unsure, consult legal counsel.

What's the difference between ZIP, ZPID, and URL modes?

  • ZIP — discovery from scratch, full filter control.
  • ZPID — enrichment of properties you already know.
  • URL — Zillow's own UI does the filtering; you paste the resulting URL.

ZIP mode is the only mode where input-schema filters and enrichment toggles take effect.

Can I get agent emails and phone numbers?

Yes. agentEmail, cellPhone, agentLicenseNumber, brokerPhoneNumber ship in the output when Zillow exposes them. The agentEmailSource column tells you which lookup path produced the email (property_details → from the Zillow listing page; agent_profile_direct → from the agent's Zillow profile; agent_search_fallback → name-search match).

On the free plan emails are masked (j***@e***.com); upgrade to a paid plan for the unmasked value.

How do I get a Zillow URL for URL mode?

Configure your filters at zillow.com in the browser, then copy the full address-bar URL (it includes a long searchQueryState=... query string) and paste it into zillowUrl.

Why are some fields null?

Zillow doesn't always publish every field for every listing. Common reasons:

  • The data isn't in Zillow's feed for this property.
  • An enrichment toggle was off (walkScore / transitScore / bikeScore need enrichWalkScore: true; full photos needs enrichPhotos: true).
  • The listing is incomplete (e.g. agent details on FSBO listings).

Missing values are returned as null, not the string "N/A".

Can I schedule runs?

Yes — use Apify's built-in Schedules tab on the actor's detail page to trigger the run hourly / daily / on a cron. Each scheduled run is its own paid run.

What happens when a run is aborted mid-way?

The actor checkpoints progress per ZIP / per batch. Resurrecting the aborted run resumes from the last checkpoint (see § Resume / checkpoint). The status.html storage record reflects live progress while the run is active.


You want to scrape Zillow by…Use this actor
Multi-mode (ZIP + ZPID + URL) — full flexibilityThis actor
ZIP code only — simpler input, single-modezillow-zip-search
Search URL — paste any Zillow search pagezillow-url-search
MCP server — connect Claude Desktop / Cursor / ChatGPT to Zillow toolszillow-mcp-server

🛟 Support & feedback

  • Bug or feature request — file an issue from the actor's Issues tab on the Apify Console.
  • Custom solutions / enterprise needs — reach out via the actor's Apify Store page.

⚖️ Disclaimer

This actor is a tool for automated retrieval of publicly available data. You're responsible for using it in compliance with Zillow's terms of service, your jurisdiction's data-protection laws (GDPR, CCPA, etc.), and any third-party licenses. The author makes no representation about the accuracy or fitness of Zillow's underlying data for any purpose.