Zillow Property Listings Scraper

Scrape public Zillow sale, rent, and sold property search results with prices, addresses, beds, baths, brokers, images, and map coordinates.

Data fields

FieldTypeDescription
zpidstring | nullZillow's stable property identifier when present.
urlstringCanonical Zillow property detail URL.
addressstring | nullFormatted listing address as shown in the search result.
addressStreetstring | nullStreet portion of the address when provided.
addressCitystring | nullCity from the search result.
addressStatestring | nullUS state abbreviation when provided.
addressZipcodestring | nullListing ZIP code when provided.
pricestring | nullFormatted price text.

Input preview

startUrlsZillow search URLs
locationsLocations
resumeSearchUrlsResume search URLs
listingTypeListing type for locations
extractionMethodExtraction method
maxItemsMaximum listings

API and agents

This actor can be run through Apify API, datasets, webhooks, schedules, and the official Apify MCP server.

How this actor works

See example inputs, outputs, API usage, and practical limits before running this actor on Apify.

Open Apify page

Scrape public Zillow property search results and export structured sale, rental, or recently sold listings to CSV, JSON, Excel, or the Apify API.

Use it to monitor housing inventory, collect comparable properties, enrich market research, build relocation shortlists, or track public listing changes by city or Zillow search URL.

What does this Actor do?

Zillow Property Listings Scraper turns one or more Zillow locations or filtered search URLs into clean, deduplicated property-listing rows. It preserves search-card provenance, enforces explicit numeric filters before charging, and reports partial or empty outcomes without pretending a blocked response succeeded.

At a glance

  • Search by city, ZIP code, neighborhood, or Zillow search URL.
  • Preserve filters embedded in Zillow URLs with searchQueryState.
  • Export stable ZPIDs, prices, address parts, beds, baths, area, status, coordinates, broker attribution, public card images, Zestimates when present, and provenance.
  • Deduplicate before saving and charging.
  • Keep valid rows when one search source fails, with per-source diagnostics in RUN_SUMMARY.
  • Stop before the platform deadline and expose resumable URLs in RUN_CHECKPOINT.

Who is it for?

  • Real-estate investors tracking prices, inventory, and comparable homes.
  • Agents and brokerages monitoring public listings in target markets.
  • Proptech and data teams building internal dashboards from public property search results.
  • Relocation teams creating shortlists across multiple cities.
  • Market researchers comparing public sale and rental inventory over time.

Example input

{
  "locations": ["San Francisco, CA"],
  "listingType": "for_sale",
  "extractionMethod": "AUTO",
  "minBeds": 2,
  "maxItems": 25,
  "maxPages": 1,
  "proxy": { "useApifyProxy": true }
}

You can also paste Zillow search result URLs directly:

{
  "startUrls": [
    { "url": "https://www.zillow.com/homes/for_rent/Austin,-TX_rb/" }
  ],
  "maxItems": 50,
  "maxPages": 2
}

Output example

{
  "zpid": "12345678",
  "url": "https://www.zillow.com/homedetails/12345678_zpid/",
  "address": "123 Market St, San Francisco, CA 94103",
  "addressCity": "San Francisco",
  "addressState": "CA",
  "addressZipcode": "94103",
  "price": "$1,250,000",
  "unformattedPrice": 1250000,
  "currency": "USD",
  "beds": 3,
  "baths": 2,
  "area": 1450,
  "propertyType": "SINGLE_FAMILY",
  "homeStatus": "FOR_SALE",
  "statusText": "For sale",
  "zestimate": 1210000,
  "rentZestimate": 5200,
  "latitude": 37.7749,
  "longitude": -122.4194,
  "brokerName": "Example Realty",
  "imageUrl": "https://photos.zillowstatic.com/...jpg",
  "imageUrls": ["https://photos.zillowstatic.com/...jpg"],
  "daysOnZillow": 12,
  "isFeatured": false,
  "listingType": "for_sale",
  "sourceUrl": "https://www.zillow.com/homes/for_sale/San-Francisco,-CA_rb/",
  "sourcePage": 1,
  "sourceRoute": "HTML",
  "scrapedAt": "2026-07-08T08:00:00.000Z"
}

Input settings

Setting API key Type Description
Zillow search URLs startUrls array Search-result URLs. Filtered URLs with searchQueryState preserve their map and filter state.
Locations locations array City, ZIP code, neighborhood, or area names converted to Zillow search URLs.
Resume URLs resumeSearchUrls array URLs copied from RUN_CHECKPOINT after a bounded deadline stop. They replace fresh URLs and locations.
Listing type listingType string for_sale, for_rent, or sold for generated location searches.
Extraction method extractionMethod string AUTO, PAGINATION, or SEARCH_STATE. AUTO is recommended.
Maximum listings maxItems integer Global maximum unique rows, from 1 to 10,000.
Pages per search maxPages integer Maximum pages per source, from 1 to 20.
Minimum price minPrice number Keep rows at or above this numeric price.
Maximum price maxPrice number Keep rows at or below this numeric price.
Minimum bedrooms minBeds number Keep rows with at least this many bedrooms.
Minimum bathrooms minBaths number Keep rows with at least this many bathrooms.
Proxy configuration proxy object Existing runs default to a US residential Apify Proxy session. Omit groups for that default, use an explicit empty group list for standard Apify datacenter routing, supply other authorized groups, or disable the proxy.

AUTO uses Zillow's structured search-state response when a URL already contains valid searchQueryState; otherwise it reads structured data embedded in search pages. SEARCH_STATE is strict and rejects location-only inputs or URLs without valid state instead of silently dropping filters.

Input recipes

Austin rentals

{"locations":["Austin, TX"],"listingType":"for_rent","maxItems":20,"maxPages":1}

Denver homes between $500,000 and $1,500,000 with at least two bedrooms

{"locations":["Denver, CO"],"minPrice":500000,"maxPrice":1500000,"minBeds":2,"maxItems":25,"maxPages":2}

Exact filtered Zillow search

Open Zillow, apply filters, copy the resulting URL containing searchQueryState, and paste it into startUrls with "extractionMethod":"AUTO".

Tips for better results

  • Start with a small maxItems value for your first run.
  • Prefer a copied Zillow search URL when exact map bounds or Zillow-native filters matter.
  • Keep maxPages conservative. Ordinary Zillow result pagination is commonly capped near 20 pages for one region/filter slice.
  • If one source fails after other sources save rows, inspect RUN_SUMMARY instead of assuming the entire dataset is complete.
  • Copy RUN_CHECKPOINT.resumeSearchUrls into the resumeSearchUrls input after a deadline-bounded partial run.
  • Explicit numeric filters are applied before saving and charging. A run can legitimately finish EMPTY_FILTERED when Zillow returned candidates but all were excluded.

Limits and practical notes

  • Zillow can change its search-state or page payload. HTTP 200 challenge pages are treated as blocks, not as empty searches.
  • Requests are sequential and retry budgets are bounded; the Actor does not promise unlimited throughput.
  • Only public listing/search data is extracted. The actor does not access private accounts, messages, saved homes, or owner-only data.
  • It detects but does not solve CAPTCHA/challenge pages.
  • Search-card output is not the same as full property-detail output. Tax history, complete price history, schools, descriptions, agent contacts, and full photo galleries are outside this Actor's contract.

API usage

Run the actor from cURL:

curl "https://api.apify.com/v2/acts/fetch_cat~zillow-property-listings-scraper/runs?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"locations":["San Francisco, CA"],"listingType":"for_sale","maxItems":20}'

Run it from Node.js:

import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('fetch_cat/zillow-property-listings-scraper').call({
  locations: ['San Francisco, CA'],
  listingType: 'for_sale',
  maxItems: 20,
});
console.log(run.defaultDatasetId);

Run it from Python:

from apify_client import ApifyClient
import os

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('fetch_cat/zillow-property-listings-scraper').call(run_input={
    'locations': ['San Francisco, CA'],
    'listingType': 'for_sale',
    'maxItems': 20,
})
print(run['defaultDatasetId'])

MCP and agents

Use this actor from Apify MCP-compatible agents with:

https://mcp.apify.com?tools=fetch_cat/zillow-property-listings-scraper

Add it to Claude Desktop or Claude Code with a command like:

claude mcp add apify-zillow --url "https://mcp.apify.com?tools=fetch_cat/zillow-property-listings-scraper"

Example MCP server JSON config:

{
  "mcpServers": {
    "apify-zillow": {
      "url": "https://mcp.apify.com?tools=fetch_cat/zillow-property-listings-scraper"
    }
  }
}

Example prompts:

  • "Scrape up to 20 Zillow for-sale listings in San Francisco and summarize median price."
  • "Collect rental listings for Austin and return address, price, beds, baths, and URL."
  • "Compare public Zillow inventory for Denver and San Francisco using this actor."

Legality and responsible use

Use this Actor only within your authorization and applicable law. It extracts listing/search information without collecting Zillow login credentials. Do not use it for private account data, messages, saved homes, or purposes outside your permitted data scope. Keep request volume and retention within your authorization.

Support

If a run fails or the output looks wrong, open an issue or report a bug from the Actor page. Include the Apify run ID or run URL, input JSON, expected output, actual output, and one reproducible public URL from a Zillow search. Remove any credentials or private data before posting.

Privacy and data handling

This Actor runs with Apify limited permissions and processes the location/search inputs needed for the documented run. Results, RUN_SUMMARY, and RUN_CHECKPOINT remain in the run's Apify storage. FetchCat does not use your inputs or outputs for advertising or model training and does not retain them outside Apify run storage except for transient support debugging when you explicitly share run details. You are responsible for lawful use, authorized retention, and avoiding unnecessary personal or sensitive data.

Common questions

Questions and answers reused from the canonical actor README.

Does this actor need a Zillow account?

No. It is designed for public search result pages only.

Can it scrape rentals and sold properties?

Yes. Use listingType for location inputs or paste matching Zillow search URLs in startUrls.

Why did my run stop with a block message?

Zillow may block automated traffic. Lower maxPages, keep concurrency low, and use Apify residential proxy settings.

Can I use exact Zillow filter URLs?

Yes. Paste the filtered Zillow search URL into startUrls. AUTO preserves a valid searchQueryState; SEARCH_STATE requires it explicitly.

Does it use Zillow GraphQL?

No. GraphQL evidence currently applies mainly to full property-detail queries. This Actor uses Zillow search-card state and search-page data so it does not multiply detail requests or silently expand the paid output contract.