Arcadium Data Scrapers
Home / Guides / Zillow Scraper

How to use Zillow Scraper

Step by step: in the Apify Store, over the API, from JavaScript or Python, in n8n, and from AI agents through MCP or LangChain.

$2.10 per 1,000 properties on the Free plan, down to $1.20 on higher plans (live Apify price on 2026-11-02).

1. In the Apify Store (no code)

  1. Open arcadium/zillow-properties and sign in to Apify (a free account works).
  2. Fill in the input form. The fields below are the ones the example uses.
  3. Set a maximum cost per run in the run options if you want a hard cap.
  4. Start the run. Rows appear in the Output tab as they arrive.
  5. Export the dataset as JSON, CSV or Excel, or connect an integration.
Input fieldTypeDescription
locationsarrayPlaces to search, as you would type them on Zillow: for example a city ("Austin, TX"), ZIP code ("78704"), county ("Travis County, TX"), neighborhood or state. Each location is searched on its own with the filters below; every row keeps the location and its position in the results. Also accepted as zipCodes, search, searchTerms, queries or addresses (maxcopell actors).
maxResultsPerSearchintegerProperties per location or search URL, e.g. 200 (the default). Zillow lists at most 820 homes per query; larger areas are split into map sections automatically, so whole metros can be read. Also accepted as resultsLimit or maxResults.

Example input:

{
  "locations": [
    "Austin, TX"
  ],
  "maxResultsPerSearch": 50
}

2. Over the Apify API

The synchronous endpoint runs the actor and returns its rows in one call (for runs up to about five minutes; use the asynchronous run endpoint for longer ones).

curl -X POST "https://api.apify.com/v2/acts/arcadium~zillow-properties/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"locations":["Austin, TX"],"maxResultsPerSearch":50}'

3. From JavaScript

// npm install apify-client
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('arcadium/zillow-properties').call({
  "locations": [
    "Austin, TX"
  ],
  "maxResultsPerSearch": 50
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

4. From Python

# pip install apify-client
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("arcadium/zillow-properties").call(run_input={
    "locations": ["Austin, TX"],
    "maxResultsPerSearch": 50,
})
items = client.dataset(run.default_dataset_id).list_items().items  # apify-client 3.x returns a Run object
print(items)

5. In n8n

Paste this node into a workflow (it is a plain HTTP Request node). Create a Header Auth credential with name Authorization and value Bearer <APIFY_TOKEN>; each returned row becomes one item for the next node.

{
  "nodes": [
    {
      "name": "Run arcadium/zillow-properties",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [
        0,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.apify.com/v2/acts/arcadium~zillow-properties/run-sync-get-dataset-items",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "{\"locations\":[\"Austin, TX\"],\"maxResultsPerSearch\":50}",
        "options": {
          "timeout": 300000
        }
      }
    }
  ],
  "connections": {}
}

6. From an AI assistant (MCP)

Add Apify’s MCP server to Claude Desktop, Cursor, VS Code or any MCP client, limited to this actor:

{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=arcadium/zillow-properties",
      "headers": {
        "Authorization": "Bearer <APIFY_TOKEN>"
      }
    }
  }
}

More on the MCP page.

7. From LangChain

# pip install langchain-apify   (reads APIFY_API_TOKEN from the environment)
from langchain_apify import ApifyActorsTool

tool = ApifyActorsTool("arcadium/zillow-properties")
rows = tool.invoke({"run_input": {
    "locations": ["Austin, TX"],
    "maxResultsPerSearch": 50,
}})
# or give `tool` to an agent: create_react_agent(llm, [tool])

Sample output

One row, from the example in the actor’s README. Long text is shortened and lists are cut to two items.

{
  "rowType": "property",
  "platform": "zillow",
  "propertyId": "70345655",
  "url": "https://www.zillow.com/homedetails/3207-Wickham-Ln-Austin-TX-78725/70345655_zpid/",
  "status": "FOR_SALE",
  "price": 324900,
  "currency": "USD",
  "address": "3207 Wickham Ln, Austin, TX 78725",
  "city": "Austin",
  "state": "TX",
  "zipcode": "78725",
  "latitude": 30.232096,
  "longitude": -97.5937,
  "beds": 4,
  "baths": 3,
  "livingArea": 2575,
  "lotArea": 4800.312,
  "lotAreaUnit": "sqft",
  "homeType": "SINGLE_FAMILY",
  "daysOnMarket": 140,
  "zestimate": null,
  "rentZestimate": null,
  "taxAssessedValue": 365588,
  "priceChange": -15000,
  "priceChangeDate": "2026-10-14",
  "brokerName": "T J Lewis Real Estate",
  "photos": null,
  "detailed": false,
  "searchInput": "Austin, TX",
  "searchRank": 1,
  "scrapedAt": "2026-10-22T10:00:00.000Z"
}
FieldWhat it holds
rowTypeKind of row. Filter on this first. 'property': one Zillow property (charged as 'property', or 'property-details' when detailed is true). 'error': an input could not be read; see code and message (free).
platformAlways 'zillow'.
propertyIdZillow property id (zpid), the number before _zpid in the property URL. Unique per run.
urlProperty page URL on zillow.com.
statusListing status as Zillow states it: FOR_SALE, FOR_RENT, RECENTLY_SOLD, PENDING, OFF_MARKET, ...
statusTextStatus as shown on the card, e.g. 'Active', 'House for rent', 'Sold'.
priceList price in USD; monthly rent for rentals; null for sold homes in search rows (see lastSoldPrice on detail rows).
currencyCurrency of all money fields, normally USD.
addressFull address line, e.g. '3207 Wickham Ln, Austin, TX 78725'.
streetStreet address.
cityCity name of the property address.
stateTwo-letter state code.
zipcodeZIP code of the property address.
latitudeLatitude (WGS84).
longitudeLongitude (WGS84).
bedsNumber of bedrooms.
bathsBathrooms (half baths count 0.5).
livingAreaLiving area in square feet.
lotAreaLot size in lotAreaUnit.
lotAreaUnitUnit of lotArea: sqft or acres.
homeTypeSINGLE_FAMILY, CONDO, TOWNHOUSE, MULTI_FAMILY, APARTMENT, LOT, MANUFACTURED, ...
yearBuiltYear built (detail rows).
daysOnMarketDays on Zillow.
zestimateZillow's estimated market value in USD (Zestimate).
rentZestimateZillow's estimated monthly rent in USD.
taxAssessedValueLatest tax-assessed value in USD.
priceChangeLast price change in USD (negative = price cut).
priceChangeDateISO date of the last price change.
dateSoldISO date of the last sale, when known.
lastSoldPriceLast sold price in USD (detail rows).
brokerNameListing brokerage (company). Agent names, phones and emails are never included.
photosProperty photo URLs (photos.zillowstatic.com).
photoCountNumber of photos on the listing (detail rows).
hasVideoTrue when the listing has a video.
has3DModelTrue when the listing has a 3D home tour.
detailedTrue when the row carries the detail fields (description, facts, priceHistory, taxHistory, schools).
descriptionListing description; emails, phone numbers and agent names removed.
monthlyHoaFeeMonthly HOA fee in USD.
propertyTaxRateProperty tax rate in percent.
mlsIdMLS listing number.
listingDataSourceWhere the listing comes from, e.g. the MLS name or 'Phoenix'.
countyCounty name (detail rows).
parcelIdCounty parcel number.
factsSelected building and lot facts: heating, cooling, appliances, flooring, parkingFeatures, garageParkingCapacity, stories, basement, poolFeatures, view, lotFeatures, sewer, waterSource, associationFee, taxAnnualAmount, school names, atAGlanceFacts and more (keys present only when Zillow has them).
priceHistoryPrice events, newest first: {date, event ('Listed for sale', 'Price change', 'Sold', 'Listed for rent'...), price, pricePerSquareFoot, priceChangeRate, source}. No agent names.
taxHistoryPublic tax record per year: {date, taxPaid, value, taxIncreaseRate, valueIncreaseRate}.
schoolsNearby assigned schools: {name, rating (GreatSchools 1-10), distance (miles), grades, level, link}.
pageViewCountPage views Zillow reports for the listing.
favoriteCountTimes the listing was saved.
searchInputThe location or search URL this row was found by (null for property URLs).
searchRank1-based position in that search's results.
scrapedAtISO time the row was read.
inputError rows: the input that failed.
codeError rows: invalid_input, not_found, blocked or unavailable.
messageError rows: what went wrong, in plain words.

Schedule it

In Apify Console, create a Task from your input and add a Schedule (for example daily). Each run writes a new dataset; integrations can push the rows to Google Sheets, Slack, a webhook or your database.