# Zillow ZIP Code Property Scraper — Zillow Search by ZIP (`afanasenko/zillow-zip-search`) Actor

Scrape Zillow listings by US ZIP code or city — address, price, beds and baths, agent email and phone, FSBO owner name and phone, Zestimate, schools, photos, price and tax history, climate risk, comps. Homes for sale, for rent and sold. Export to CSV, JSON or Excel, run via API, or schedule runs.

- **URL**: https://apify.com/afanasenko/zillow-zip-search.md
- **Developed by:** [Andrey Afanasenko](https://apify.com/afanasenko) (community)
- **Categories:** Real estate, Lead generation
- **Features:** Limited permissions
- **Stats:** 17 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 properties

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Zillow ZIP Code Property Scraper — Zillow Search by ZIP

[![Apify Actor](https://apify.com/actor-badge?actor=afanasenko/zillow-zip-search)](https://apify.com/afanasenko/zillow-zip-search)

> **Extract Zillow real estate listings by ZIP code or city — enter ZIP codes or places like Phoenix, AZ, get 70+ output fields per property including agent contacts (or the owner's name and phone on FSBO listings), price history, Zestimate, and schools. 70+ filters for sale, rent, and sold searches. Built for real-estate lead generation and market research.**

Zillow's public API doesn't expose ZIP-level discovery with filters. This actor reads anything Zillow shows in the browser for a given ZIP — full filter set, agent emails and phones, photo galleries, price-history arrays, school ratings, and 70+ output columns per row.

### 🎯 What it does

You point the actor at a list of US ZIP codes or places with their state (a city like `Phoenix, AZ`, a county, a neighborhood) and get one structured row per property in the dataset. Each row includes:

- **Address & location** — street, city, state, ZIP, county, neighborhood, lat/lng
- **Listing data** — price, status (For Sale / For Rent / Recently Sold), days on Zillow, page views, favorites, listing type
- **Property details** — beds, baths, square footage, lot size, year built, home type, architectural style, flooring, heating/cooling, roof, appliances, fireplaces, garage, pool, basement, view types
- **Financial data** — Zestimate, Rent Zestimate, price per sqft, HOA fees, property tax, price history, last sold date
- **Agent contacts** — agent name, email, phone, license number, broker name, broker phone
- **Owner contacts on FSBO listings** — `contactRole: "owner"`, `ownerName`, `ownerPhone`
- **Optional enrichment** — Walk Score, Transit Score, Bike Score, full photo gallery URLs

**Filter the output with 70+ knobs**: status, price range, beds/baths, square footage, lot size, year built, home type (single family / townhouse / condo / multi-family / manufactured / lot-land), days on Zillow, keyword search, school ratings, listing type (FSBO / agent / new construction / auction / foreclosure), property features (pool, garage, view, basement, 3D tour, waterfront, accessibility), and rental-specific filters (pets, parking, furnished, in-unit laundry, lease length, utilities).

### 📦 Output sample

A real row from a single-family Austin TX listing — 25 most-used columns shown:

```json
{
  "zpid": "119617641",
  "hdpUrl": "https://www.zillow.com/homedetails/10124-Pinnacle-Crest-Loop-Austin-TX-78747/119617641_zpid/",
  "price": 375000,
  "status": "FOR_SALE",
  "homeType": "SINGLE_FAMILY",
  "streetAddress": "10124 Pinnacle Crest Loop",
  "city": "Austin",
  "state": "TX",
  "zipcode": "78747",
  "county": "Travis County",
  "bedrooms": 5,
  "bathrooms": 3,
  "livingArea": 2385,
  "yearBuilt": 2014,
  "agentName": "Hillary Smith",
  "agentEmail": "hillary@homesmithatx.com",
  "agentEmailSource": "agent_profile_direct",
  "cellPhone": "512-585-1947",
  "brokerName": "HOMESMITH REALTY, LLC",
  "pricePerSqft": 157,
  "hoaFee": 47,
  "propertyTax": 7749,
  "hasPool": true,
  "daysOnZillow": "6 days",
  "schools": [{"name": "Blazier Elementary School", "level": "Primary", "rating": 5, "distance": 1.3}]
}
```

**+68 more columns in the dataset** — climate risks (flood, wildfire, wind, heat and air quality on a 1–10 scale, FEMA flood zone), the nearby homes with a calculated comparison of the property's price per square foot against their median, full price-history array, full photo gallery, neighborhood, lot size, garage spaces, view, heating/cooling, last tax assessed value, etc. See [`dataset_schema.json`](.actor/dataset_schema.json) for every column.

### ⚡ Quick start

1. **Paste this input** into the Input tab in the Apify Console.
2. **Click Run** — the first run takes 30–60 seconds.
3. **Open the Output tab** — preview the dataset, export as JSON / CSV / Excel.

```json
{
  "zipCodes": ["78704"],
  "status_type": "ForSale",
  "maxPropertiesPerZip": 5
}
```

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

### 🎯 Example tasks

Ready-to-run examples — each opens a pre-configured task you can run in one click (no setup):

- **[Scrape homes for sale by ZIP code on Zillow](https://apify.com/afanasenko/zillow-zip-search/examples/homes-for-sale-by-zip-code)** — Enter any ZIP code and export every for-sale home — price, beds, baths, square footage, agent contact, and Zestimate — as clean structured data.
- **[Find recently sold homes by ZIP for comps](https://apify.com/afanasenko/zillow-zip-search/examples/recently-sold-homes-by-zip-code)** — Enter a ZIP code and export recently sold homes with sale price, sold date, beds, baths, and size — ideal for pricing comps and market research.
- **[Scrape homes for rent by ZIP code on Zillow](https://apify.com/afanasenko/zillow-zip-search/examples/homes-for-rent-by-zip-code)** — Enter a ZIP code and export every rental listing — monthly rent, beds, baths, square footage, and contact details — refreshed whenever you run it.

### 🧭 When to use it

1. **Real-estate lead generation** — collect agent emails + phones across a target metro by ZIP-code coverage.
2. **Market research** — pull all For Sale / Recently Sold properties in a geo for a price/sqft analysis.
3. **Brokerage outreach** — segment by listing type (FSBO, new construction, auction, foreclosure) and contact the listing agent — or, on an FSBO listing, the owner (`ownerName`, `ownerPhone`).
4. **Rental sourcing** — find For Rent listings with specific filters (pet policy, parking, furnished).
5. **Price tracking** — re-run weekly across the same ZIPs to track new listings, price changes, and days on market.

### 🛠 Input

The actor accepts 70+ input fields. The most-used:

- **`zipCodes`** *(required, array of strings)* — US ZIP codes or places with their state (`Phoenix, AZ`, `Maricopa County, AZ`, `Downtown, Phoenix, AZ`). Each entry gets its own search, so every home returned is inside the ZIP or place you asked for. A place without its state is not searched. Free plan: up to 20 ZIPs or places per run.
- **`maxPropertiesPerZip`** *(integer, default 0=unlimited)* — homes to fetch from each ZIP or place. Their count × this number is the most the run can return, and every home returned is billed.
- **`status_type`** *(enum, default ForSale)* — `ForSale` / `ForRent` / `RecentlySold`.
- **Price** — `price_min`, `price_max`, `rentMinPrice`, `rentMaxPrice`.
- **Property dimensions** — `beds_min/max`, `baths_min/max`, `sqft_min/max`, `lotSize_min/max`, `built_min/max`.
- **`doz`** — days on Zillow (`1`, `7`, `14`, `30`, `90`).
- **`sort`** — `Newest`, `Highest_Price`, `Lowest_Price`, `Bedrooms`, `Square_Feet`, `Lot_Size`, `Year_Built`, `Days_on_Zillow`.
- **`keywords`** — free-text keyword filter (e.g. `"pool, hardwood floors"`).
- **Home types** — `isSingleFamily`, `isTownhouse`, `isMultiFamily`, `isCondo`, `isLotLand`, `isApartment`, `isManufactured`.
- **Listing types** — `isForSaleByOwner`, `isForSaleByAgent`, `isNewConstruction`, `isAuction`, `isForSaleForeclosure` (tri-state where applicable).
- **Property features** — `hasGarage`, `hoa_max`, `hasPool`, `hasAirConditioning`, `isWaterfront`, `isBasementFinished`, view filters, `is3dHome`, `isOpenHousesOnly`.
- **Rental features** — pet policies, parking, furnished, in-unit laundry, utilities, lease length, accessibility.
- **Schools** — `schools` (Public/Private/Charter), `schoolsRating` (1–10), `includeUnratedSchools`.
- **Enrichment** — `enrichWalkScore` (Walk/Transit/Bike scores), `enrichPhotos` (full photo gallery URLs).

See the **Input** tab in Apify Console for the full list with descriptions, types, defaults, and examples.

### 💰 How much will scraping Zillow cost?

**From $0.05 per property** on paid plans, $0.08 on Free. Pay-per-event: you pay only when the actor finishes enriching a property — properties filtered out by your input filters before enrichment are free.

| Plan | Price per `PROPERTY_ENRICHED` |
|---|---|
| **Free** | $0.08 |
| **Bronze** | $0.07 |
| **Silver** | $0.06 |
| **Gold / Platinum / Diamond** | $0.05 |

Cost math (Diamond tier): **100 properties = $5**, **1,000 properties = $50**.

A small `apify-actor-start` fee ($0.00005 × memory GB, minimum 1 event per run) covers platform startup — usually $0.0001–$0.001 per run.

**Cap costs hard with Apify's "Maximum cost per run"** Run option in the right panel — covers all events.

### 🆓 Free vs paid plan

| | Free plan | Paid plan |
|---|---|---|
| Properties per run | up to **15** | unlimited |
| ZIP codes per run | up to **20** | unlimited |
| Runs per calendar month | up to **15** (demo runs don't count) | unlimited |
| Per-run budget ceiling | **$1.20** | unlimited |
| Agent email visibility | domain masked (`name@xxx`) | full email |
| All filters + features | ✅ | ✅ |

The first paid run unlocks unlimited properties + ZIPs + budgets + full agent emails immediately — no waiting period.

Free runs that start at the same time are counted exactly. A free run you stop (abort) or that times out counts as one of the 15, like a finished run (resurrecting it does not count again); a run that fails, or whose maximum cost cannot pay for a single property, does not. If the run count cannot be checked, the free run stops before any work, charges nothing and says so — run it again in a minute.

While an unusually large number of new free accounts run this Actor at once, free runs from new accounts may be reduced to one property for a short while — the first ZIP code, from the property's own page, without the agent-email lookups, Walk Score or photos. The run says so in its message and still counts as one of the 15. Paid plans are never affected.

### 🧪 Filter recipes

**Single-family For Sale homes in Austin TX, $400k–$900k:**

```json
{
  "zipCodes": ["78704", "78745", "78751"],
  "status_type": "ForSale",
  "isSingleFamily": true,
  "isCondo": false,
  "isTownhouse": false,
  "price_min": 400000,
  "price_max": 900000,
  "beds_min": 3,
  "doz": "30",
  "sort": "Newest"
}
```

**Recently sold luxury condos in Miami FL:**

```json
{
  "zipCodes": ["33139", "33140", "33141"],
  "status_type": "RecentlySold",
  "isCondo": true,
  "isSingleFamily": false,
  "price_min": 1500000,
  "sort": "Highest_Price"
}
```

**Pet-friendly furnished rentals in Brooklyn NY:**

```json
{
  "zipCodes": ["11201", "11215", "11217"],
  "status_type": "ForRent",
  "rentMaxPrice": 4500,
  "largeDogsAllowed": true,
  "catsAllowed": true,
  "furnished": true,
  "inUnitLaundry": true
}
```

### 📡 Live status & storage records

Every run writes records to the run's Storage tab:

| Key | What it holds |
|---|---|
| `RUN_SUMMARY` | Full run statistics — input, properties (found / enriched / skipped), email yield, billing, plan tier, error info, plus `zipScope`: which ZIPs were searched directly, which had to be searched through their city (and how many rows were dropped unbilled), and which returned nothing. |
| `status.html` | Auto-refreshing status page rendered live during the run. View via the **Live View** tab. |
| `SKIPPED_ITEMS` | Per-item list of every ZIP / property skipped, with reason and category (`filter`, `not_found`, `error`, `temporarily_unavailable`, `free_limit`, `not_resolvable`). |
| `FREE_LIMITS_APPLIED` | Free-tier ceilings hit during the run. Empty on paid runs. |
| `USER_MESSAGE` | Per-run message: zero-result diagnosis with the fix, input-error explanation, free-cap interrupt with the real held-back numbers, monthly-allowance note, a note when a ZIP had to be searched through its city, demo-run note, workspace-export status, or paid onboarding. |
| `UNKNOWN_INPUT_KEYS` | Lists any input field names not part of the actor's schema (e.g. `mode`, `zpids` — fields from the parent multi-mode actor). |

### 🔌 Export to your workspace (MCP connectors)

Optionally deliver each run's property rows straight into your own tools — without pasting any API keys into the actor.

- **Notion** — the run creates a `Zillow ZIP Search Export <date>` database (address, price, status, beds/baths, Zillow URL, agent contacts) with up to 100 rows per run.
- **Airtable** — the run adds a `Zillow ZIP Search <date>` table to your `Apify Exports` base (created automatically on first export; feel free to move it to any workspace), up to 500 rows per run.
- **monday.com** — the run creates a `Zillow ZIP Search Export <date>` board with typed columns, up to 50 items per run.

One-time setup: authorize a connector under **Settings → API & Integrations → MCP connectors** in Apify Console (a standard OAuth popup, takes under a minute), then pick it in the **Export destination** input field. Your credentials stay with Apify — the actor only talks to a proxy that injects them server-side, and you control which tools the connector permits.

Export is best-effort: it runs after scraping completes and never affects scraping results. If it fails, the dataset still holds every row, and the run explains what happened in `USER_MESSAGE` and `RUN_SUMMARY.connectorExport`. If your provider adds new tools later, re-authorize the connector to pick them up.

### 🤖 Programmatic API

**Start a synchronous run + read the dataset directly:**

```bash
TOKEN="<your-apify-token>"
curl -X POST "https://api.apify.com/v2/acts/afanasenko~zillow-zip-search/run-sync-get-dataset-items?token=$TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"zipCodes":["78704"],"status_type":"ForSale","maxPropertiesPerZip":20}'
```

The actor exposes its schema for MCP / agent consumption — `dataset_schema.json` declares every output column with type and description, and `input_schema.json` declares every input field. For a dedicated MCP wrapper with narrow tools per mode, see [zillow-mcp-server](https://apify.com/afanasenko/zillow-mcp-server).

### 💡 Tips & Best Practices

#### Getting maximum results

- **Validate before scaling.** Start with one ZIP and `maxPropertiesPerZip: 5`, spot-check the first row, *then* expand.
- **Layer filters that drop matches pre-enrichment.** Tri-state listing-type filters, school rating, and home-type checkboxes narrow the candidate set before paid events fire.
- **For sold-listing runs**, set at least one home-type filter — sold queries return zero with no home types selected (the actor sets defaults if you forget).

#### Cost optimization

- **Use Apify's Maximum cost per run** Run option for a hard ceiling — covers all events.
- **Toggle enrichments on demand.** `enrichWalkScore` and `enrichPhotos` are off by default — turn on only when downstream consumers need those columns.
- **Schedule, then re-process offline.** Pull once, transform repeatedly in Excel / SQL / pandas — don't re-run the actor for filter tweaks.

#### Performance

- One search per ZIP, so a ZIP that returns nothing never affects the others. Duplicate ZIPs in the input are searched once.
- Avoid huge nationwide ZIP lists in a single run — split into smaller scheduled runs and aggregate downstream for predictable cost and latency.
- A few ZIPs — PO-box and non-residential ones — cannot be searched directly. For those the actor searches the surrounding city and keeps only the homes inside your ZIP; the dropped homes are never billed, and `RUN_SUMMARY.zipScope` records what happened.

#### Data quality

- **Know what's nullable.** FSBO listings have no agent — the contact is the owner, in `ownerName` / `ownerPhone`; rentals may omit `priceHistory`; year-built is missing on some new construction.
- **Trace email confidence via `agentEmailSource`** — `property_details` is the strongest source, `agent_search_fallback` is name-match heuristic.
- **Walk Score / photos require their toggles** — they don't fire by default to keep the dataset lean.

### ❓ FAQ

**Is it legal to scrape Zillow?**
Scraping public data is legal in most jurisdictions — see § Is it legal to scrape Zillow? below. The actor only reads what's already public on the listing page; private user data is never touched.

**Can I get banned for using this actor?**
No. The actor is the one making requests, not your account — nothing is sent from your IP, and no Zillow login is involved.

**Why are some fields null?**
Not every Zillow listing has every field populated — agent emails are missing on some listings, year-built is missing on new construction, lot size is missing on condos. Null in the dataset means the source listing didn't expose that data.

**Where do the climate risks and the nearby-home comparison come from?**
From the property's own Zillow page, read in the same lookup — no extra charge. The flood, wildfire, wind, heat and air-quality columns are the risk scores (1–10) and labels Zillow shows in the page's climate-risk section, with the FEMA flood zone; about 95% of properties carry them. `nearbyHomes` lists the homes around the property (usually eight), each with what its price is (`priceKind`: Zestimate, sale, asking price or rent) — neighbours, not a hand-picked set of comparable sales. `compsMedianPricePerSqft` and `pricePerSqftVsCompsPct` are **calculated by this actor**: the median price per square foot of the nearby homes whose price is a value (rents left out; same home type when at least three are), and how far this property sits above or below it, in percent. The property is compared by its price only when it is for sale, pending or sold; a foreclosed or off-market home's page price is often its tax-assessed value, so it is compared by its Zestimate, or not at all (`pricePerSqftVsCompsBasis`: `no_sale_price`).

**Is there a tax history and a list of rooms?**

Yes, from the same lookup and at no extra charge: `taxHistory` lists the county tax record by year — tax paid, assessed value and how each changed on the year before — and `rooms` lists the rooms the listing names, with level, dimensions and area in square feet. Listing agents type the rooms, so off-market homes usually have none.

**Why did my run return 0 properties?**
Usually the ZIP itself: PO-box and non-residential ZIPs have no listings by design, and thin rural ZIPs can have zero matches for a given status type. When many searches run at the same moment, a run waits its turn; a ZIP code it still could not search before its timeout is listed in `SKIPPED_ITEMS` under `temporarily_unavailable`, is not charged, and usually goes through when you run it again a few minutes later. Every 0-result run writes a `USER_MESSAGE` record to the run's Storage tab naming the exact cause and the fix, and the run's status line points to it. Quick sanity check that always returns data: ZIP `90210` with no filters.

**Do I pay for runs that return nothing?**
No. Billing is per successfully enriched property — a run that finds or delivers nothing charges $0 (only the fractions-of-a-cent platform start fee applies).

**Can AI agents use this actor?**
Yes — this actor is agent-friendly out of the box: every output column is declared in `dataset_schema.json`, and zero-result runs surface the pointer in the run status message so an agent can self-correct the input. For narrow per-tool schemas in Claude Desktop, Cursor, or ChatGPT, use [zillow-mcp-server](https://apify.com/afanasenko/zillow-mcp-server).

**Can I schedule runs?**
Yes — use Apify's built-in **Schedules** feature in the Console. Common pattern: run weekly on the same ZIP cohort to track new listings + price changes.

**What happens when a run is aborted mid-way?**
Properties already enriched and pushed to the dataset are persisted. The next run starts from scratch (this single-mode actor doesn't checkpoint between runs). For checkpointed runs use the parent multi-mode actor. On the free plan an aborted run counts as one of the 15 free runs of the month.

**How do I avoid the test-mode property cap on demo input?**
Don't use the default ZIP `90210` with no filters. Any ZIP other than `90210` (or `90210` with at least one filter set) runs at the normal property cap for your plan.

**Why does my paid run still show free-plan limits?**
Confirm the run was started under your paid plan (the `RUN_SUMMARY.plan` field will say `paid`). API-origin runs sometimes hit a stale auth context — re-running through Console should resolve.

**Can I do ZPID lookups or paste a Zillow search URL?**
Not in this actor. This is the **single-mode ZIP search** version. For ZPID or URL inputs, use [zillow-property-agent-data-scraper](https://apify.com/afanasenko/zillow-property-agent-data-scraper) (multi-mode) or [zillow-url-search](https://apify.com/afanasenko/zillow-url-search).

**Can I search a whole city instead of ZIP codes?**
Yes — type the place with its state into `zipCodes`: `Phoenix, AZ`, `Austin TX`, `Maricopa County, AZ` or a neighborhood like `Downtown, Phoenix, AZ`. It is searched the way Zillow's own search box does, and you can mix places and ZIP codes in one list. A name without its state (`Phoenix`) is not searched and not charged — there are dozens of towns with the same name.

**How do I get the owner's contact on for-sale-by-owner listings?**
Turn on **Owner Posted (FSBO)** and turn off **Agent Listed**. You then get only homes the owner posted: Zillow's by-owner search also returns bank-owned and new-construction listings, and those are dropped before enrichment, so they are never charged. Each FSBO row carries `contactRole: "owner"` with the owner's name and phone in `ownerName` and `ownerPhone`, as the listing shows them; agent-listed rows carry `contactRole: "listing_agent"`.

**How fresh is the data?**
Each run hits live Zillow listing pages, so data is as fresh as Zillow itself — typically within minutes for new listings and price changes.

**How fast is one run?**
A 50-property ZIP run finishes in 60–120 seconds. Larger runs scale roughly linearly: 1,000 properties ≈ 15–25 minutes.

**Can I cap the per-run cost?**
Yes — set Apify's **Maximum cost per run** in the Run options panel. The free-plan budget ceiling ($1.20) acts as another belt-and-suspenders cap.

### 🔗 Related actors

| Actor | Description |
|---|---|
| [zillow-zip-search](https://apify.com/afanasenko/zillow-zip-search) | **This actor** — ZIP-code-only, simpler input for discovery runs. |
| [zillow-property-agent-data-scraper](https://apify.com/afanasenko/zillow-property-agent-data-scraper) | Parent — multi-mode (ZIP + ZPID + URL), full filter control. |
| [zillow-url-search](https://apify.com/afanasenko/zillow-url-search) | URL-only — paste any Zillow search page. |
| [zillow-mcp-server](https://apify.com/afanasenko/zillow-mcp-server) | MCP server — connect Claude Desktop, Cursor, or ChatGPT to Zillow data with narrow tools per mode. |

More lead-generation actors from the same author:

| You want leads from… | Use this actor |
|---|---|
| LinkedIn job postings — salary data + hiring contacts | [linkedin-jobs-scraper](https://apify.com/afanasenko/linkedin-jobs-scraper) |
| Instagram profiles — emails, engagement, 38 fields per profile | [instagram-profile-scraper](https://apify.com/afanasenko/instagram-profile-scraper) |

### 🛟 Support & feedback

Found something useful, broken, or worth improving? Three ways to help and stay in the loop:

- ⭐ **Leave a review on the Apify Store** — if this actor saved you time, a quick review helps other users find it and helps the author prioritize.
- 🔖 **Bookmark the actor** — open Apify Console → click the ★ Save icon on the actor page so it shows up in your sidebar for the next run.
- 🐞 **Open an issue on the actor's Apify Store page** — bug reports, feature requests, and edge cases all welcome via the Issues tab.

### ⚖️ Is it legal to scrape Zillow?

Scraping publicly available data — including Zillow listings — is legal in the United States and most other jurisdictions. The seminal case is *hiQ Labs v. LinkedIn* (9th Cir. 2019, reaffirmed 2022), which held that scraping public web data does not violate the Computer Fraud and Abuse Act. See [Apify's overview of web-scraping legality](https://blog.apify.com/is-web-scraping-legal/) for a deeper read.

That said, three responsibilities sit with you:

1. **Zillow's Terms of Service** — review them and use the data in line with what they permit.
2. **Personal data laws** (GDPR / CCPA / CAN-SPAM / similar) — listings include personal information for licensed agents (a public role), which still falls under data-protection regimes. Make sure you have a legitimate basis to process it, especially for outreach.
3. **Downstream use** — the data is provided as-is. The author makes no representation about Zillow's underlying accuracy or fitness for any specific purpose.

If unsure about a specific use case, consult legal counsel.

# Changelog

This Actor's version history is a separate document: https://apify.com/afanasenko/zillow-zip-search/changelog.md

# Actor input Schema

## `zipCodes` (type: `array`):

Enter US ZIP codes or places with their state: a city (Phoenix, AZ), a county (Maricopa County, AZ) or a neighborhood. Each entry is searched on its own, so every home you get back is inside the ZIP or place you asked for. A place without its state is not searched. Residential ZIPs work best — PO-box and non-residential ZIPs return no listings. For a quick verified test, 90210 always returns data. Free plan: up to 20 ZIP codes or places per run.

## `maxPropertiesPerZip` (type: `integer`):

How many homes to fetch from each ZIP code or place. 10 ZIP codes with this set to 5 returns up to 50 homes, and every home returned is billed — so this number times your count of ZIPs and places is the most the run can cost. Set to 0 for no limit. Free plan: maximum 15 properties, 20 ZIP codes per run.

## `status_type` (type: `string`):

Filter properties by their listing status.

## `price_min` (type: `integer`):

For Sale/Sold properties.

## `price_max` (type: `integer`):

For Sale/Sold properties.

## `rentMinPrice` (type: `integer`):

For Rent properties.

## `rentMaxPrice` (type: `integer`):

For Rent properties.

## `beds_min` (type: `integer`):

Minimum number of bedrooms.

## `beds_max` (type: `integer`):

Maximum number of bedrooms (0 for any).

## `baths_min` (type: `integer`):

Minimum number of bathrooms.

## `baths_max` (type: `integer`):

Maximum number of bathrooms (0 for any).

## `doz` (type: `string`):

Filter by how recently the property was listed or sold.

## `sort` (type: `string`):

Choose how to sort the search results.

## `keywords` (type: `string`):

e.g., 'pool, ocean view'

## `isSingleFamily` (type: `boolean`):

Include single-family homes.

## `isTownhouse` (type: `boolean`):

Include townhouses.

## `isMultiFamily` (type: `boolean`):

Include multi-family properties.

## `isCondo` (type: `boolean`):

Include condos and co-ops.

## `isLotLand` (type: `boolean`):

Include lots and land.

## `isApartment` (type: `boolean`):

Include apartments. **Best practice: turn ON for rental searches.** Apartments are the majority of rental inventory in most US ZIPs; leaving this off when status_type=ForRent typically yields zero or near-zero results. The actor auto-flips this on if it detects you took the form home-type defaults for a ForRent run, but it's cleaner to set it explicitly.

## `isManufactured` (type: `boolean`):

Include manufactured homes.

## `isForSaleByOwner` (type: `boolean`):

Include For Sale By Owner listings. On these rows the contact is the owner: contactRole is owner, with the owner's name and phone in ownerName and ownerPhone. With Agent Listed turned off you get only homes the owner posted: Zillow's by-owner search also returns bank-owned and new-construction listings, and those are dropped before anything is charged.

## `isForSaleByAgent` (type: `boolean`):

Include agent-listed properties.

## `isNewConstruction` (type: `string`):

'Any' shows all, 'Only' shows only new construction, 'Exclude' hides new construction.

## `isAuction` (type: `string`):

'Any' shows all, 'Only' shows only auctions, 'Exclude' hides auctions.

## `isForSaleForeclosure` (type: `string`):

'Any' shows all, 'Only' shows only foreclosures, 'Exclude' hides foreclosures.

## `includeForeclosed` (type: `boolean`):

Add foreclosed properties to results (excluded by default).

## `includePreForeclosure` (type: `boolean`):

Add pre-foreclosure properties to results (excluded by default).

## `isPendingUnderContract` (type: `boolean`):

Only include properties that are pending or under contract.

## `isAcceptingBackupOffers` (type: `boolean`):

Only include properties accepting backup offers.

## `sqft_min` (type: `integer`):

Minimum property size in square feet.

## `sqft_max` (type: `integer`):

Maximum property size in square feet.

## `lotSize_min` (type: `string`):

Minimum lot size.

## `lotSize_max` (type: `string`):

Maximum lot size.

## `built_min` (type: `integer`):

Earliest year of construction.

## `built_max` (type: `integer`):

Latest year of construction.

## `parkingSpots_min` (type: `integer`):

Minimum number of parking spots.

## `hasGarage` (type: `boolean`):

Only include properties with a garage.

## `hoa_max` (type: `integer`):

Maximum monthly HOA fee.

## `hasPool` (type: `boolean`):

Only include properties with a pool.

## `hasAirConditioning` (type: `boolean`):

Only include properties with air conditioning.

## `isWaterfront` (type: `boolean`):

Only include waterfront properties.

## `isBasementFinished` (type: `boolean`):

Only include properties with a finished basement.

## `isBasementUnfinished` (type: `boolean`):

Only include properties with an unfinished basement.

## `isCityView` (type: `boolean`):

Only properties with a city view.

## `isMountainView` (type: `boolean`):

Only properties with a mountain view.

## `isParkView` (type: `boolean`):

Only properties with a park view.

## `isWaterView` (type: `boolean`):

Only properties with a water view.

## `isOpenHousesOnly` (type: `boolean`):

Only include properties with scheduled open houses.

## `is3dHome` (type: `boolean`):

Only include properties with a 3D tour.

## `largeDogsAllowed` (type: `boolean`):

Only rentals that allow large dogs.

## `smallDogsAllowed` (type: `boolean`):

Only rentals that allow small dogs.

## `catsAllowed` (type: `boolean`):

Only rentals that allow cats.

## `noPets` (type: `boolean`):

Only rentals that do not allow pets.

## `inUnitLaundry` (type: `boolean`):

Only rentals with in-unit laundry.

## `parkingAvailable` (type: `boolean`):

Only rentals with on-site parking.

## `furnished` (type: `boolean`):

Only furnished rentals.

## `hardwoodFloor` (type: `boolean`):

Only rentals with hardwood floors.

## `utilitiesIncluded` (type: `boolean`):

Only rentals with utilities included.

## `disabledAccess` (type: `boolean`):

Only rentals with disabled access.

## `shortTermLease` (type: `boolean`):

Only rentals with short term lease available.

## `outdoorSpace` (type: `boolean`):

Only rentals with outdoor space.

## `controlledAccess` (type: `boolean`):

Only rentals with controlled access.

## `highSpeedInternet` (type: `boolean`):

Only rentals with high speed internet.

## `elevator` (type: `boolean`):

Only rentals with elevator access.

## `acceptsApplications` (type: `boolean`):

Only rentals accepting Zillow applications.

## `incomeRestricted` (type: `boolean`):

Only income-restricted rentals.

## `schools` (type: `string`):

Filter by nearby school types (comma-separated: elementary, middle, high, public, private, charter).

## `schoolsRating` (type: `integer`):

Minimum school rating (1-10).

## `includeUnratedSchools` (type: `boolean`):

Include schools with no rating in the search.

## `enrichWalkScore` (type: `boolean`):

Enrich results with Walk, Transit, and Bike scores for each property.

## `enrichPhotos` (type: `boolean`):

Get the complete photo gallery for each property. By default, only the main photo is included.

## `exportConnector` (type: `string`):

Optional MCP connector that delivers this run's property rows to your own Notion workspace, Airtable base, or monday.com board after scraping completes. Pick a connector authorized in your Apify account — your credentials never enter the Actor. Export is best-effort and never affects scraping results.

## Actor input object example

```json
{
  "zipCodes": [
    "90210"
  ],
  "maxPropertiesPerZip": 0,
  "status_type": "ForSale",
  "price_min": 0,
  "price_max": 0,
  "rentMinPrice": 0,
  "rentMaxPrice": 0,
  "beds_min": 0,
  "beds_max": 0,
  "baths_min": 0,
  "baths_max": 0,
  "doz": "any",
  "sort": "Homes_for_You",
  "keywords": "",
  "isSingleFamily": true,
  "isTownhouse": true,
  "isMultiFamily": false,
  "isCondo": true,
  "isLotLand": false,
  "isApartment": true,
  "isManufactured": false,
  "isForSaleByOwner": false,
  "isForSaleByAgent": true,
  "isNewConstruction": "any",
  "isAuction": "any",
  "isForSaleForeclosure": "any",
  "includeForeclosed": false,
  "includePreForeclosure": false,
  "isPendingUnderContract": false,
  "isAcceptingBackupOffers": false,
  "sqft_min": 0,
  "sqft_max": 0,
  "lotSize_min": "",
  "lotSize_max": "",
  "built_min": 0,
  "built_max": 0,
  "parkingSpots_min": 0,
  "hasGarage": false,
  "hoa_max": 0,
  "hasPool": false,
  "hasAirConditioning": false,
  "isWaterfront": false,
  "isBasementFinished": false,
  "isBasementUnfinished": false,
  "isCityView": false,
  "isMountainView": false,
  "isParkView": false,
  "isWaterView": false,
  "isOpenHousesOnly": false,
  "is3dHome": false,
  "largeDogsAllowed": false,
  "smallDogsAllowed": false,
  "catsAllowed": false,
  "noPets": false,
  "inUnitLaundry": false,
  "parkingAvailable": false,
  "furnished": false,
  "hardwoodFloor": false,
  "utilitiesIncluded": false,
  "disabledAccess": false,
  "shortTermLease": false,
  "outdoorSpace": false,
  "controlledAccess": false,
  "highSpeedInternet": false,
  "elevator": false,
  "acceptsApplications": false,
  "incomeRestricted": false,
  "schools": "",
  "schoolsRating": 0,
  "includeUnratedSchools": true,
  "enrichWalkScore": false,
  "enrichPhotos": false
}
```

# Actor output Schema

## `liveStatus` (type: `string`):

No description

## `results` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("afanasenko/zillow-zip-search").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("afanasenko/zillow-zip-search").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call afanasenko/zillow-zip-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,afanasenko/zillow-zip-search"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/gONfwT1QqcAjeLyFI/builds/q0X1W0Z4qYQ0c3mNH/openapi.json
