Zillow Property Details Scraper - Zestimate, Price, Tax History
Pricing
$3.00 / 1,000 properties
Zillow Property Details Scraper - Zestimate, Price, Tax History
Get full Zillow property details for URLs or zpids: price, Zestimate, rent Zestimate, beds, baths, area, price history, tax history, schools, brokerage. Change mode sends price, status or Zestimate change alerts to Discord, Telegram, Slack or any webhook. No agent contact data.
Pricing
$3.00 / 1,000 properties
Rating
0.0
(0)
Developer
Luke Hunter
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
For real-estate investors, agents and brokerages, proptech teams and lenders' data pipelines, this Actor takes a list of Zillow property URLs or zpids and returns one clean row per property: address, status, price, Zestimate, rent Zestimate, beds, baths, area, price history, tax history, schools and brokerage.
Pay per delivered property: $0.003 per property — 1,000 properties = $3. No start fee. A property that is blocked, missing or (in monitoring mode) unchanged is not charged.
It is built for the way property data is actually used in a pipeline: you pass a list, you get one row per input back, the field names never change, and anything Zillow does not publish is null instead of a guess. Call it from code, from a schedule, or from Make, Zapier and n8n.
At a glance
- Paste: Zillow property URLs (
zillow.com/homedetails/...) or zpids. - Get, per property:
{"zpid": "20522136", "address": "1001 N Crescent Dr, Beverly Hills, CA 90210", "price": 20995000, "zestimate": 18738900, "bedrooms": 7}, plus price history, tax history, schools andbrokerageName. - Price: $0.003 per delivered property (1,000 properties = $3). Free: blocked, missing, invalid, robots-skipped and (in monitoring mode) unchanged inputs.
- From code and pipelines: API, Make, Zapier and n8n, or as a tool for AI agents (MCP). What it does not do (US only, no agent contact data): Limitations.
Quick start
Paste property URLs (or zpids), keep the defaults, run:
{"urls": ["https://www.zillow.com/homedetails/1003-Juanita-St-Austin-TX-78704/29474600_zpid/","https://www.zillow.com/homedetails/1001-N-Crescent-Dr-Beverly-Hills-CA-90210/20522136_zpid/"],"zpids": [2131539623],"maxItems": 100}
Open the Properties dataset view, or export JSON, CSV or Excel. Every input's result (delivered, blocked, not found, skipped...) is also written to the run's OUTCOMES record so you can join it to your input list.
Input
| Field | Type | Default | Description |
|---|---|---|---|
urls | string[] | – | Zillow property page URLs (zillow.com/homedetails/...). Search pages are rejected with a clear message. |
zpids | string[] / number[] | – | Zillow property IDs, e.g. 29474600. Use instead of, or alongside, urls. |
maxItems | integer | 100 | 1–5000. Hard cap on delivered rows, and your cost cap. |
includePriceHistory | boolean | true | Add the price history list to each row. |
includeTaxHistory | boolean | true | Add the tax history list to each row. |
includeSchools | boolean | true | Add the schools list to each row. |
onlyChangedSinceLastRun | boolean | false | Monitoring mode: deliver a property only when its price, status or Zestimate changed since the last run. |
stateStoreName | string | zillow-property-details-state | Name of the store that remembers each property between monitoring runs. |
discordWebhookUrl | string (secret) | (none) | Discord webhook URL. Must look like https://discord.com/api/webhooks/<id>/<token>. Empty means no Discord messages. |
telegramBotToken | string (secret) | (none) | Telegram bot token from @BotFather. Needs telegramChatId. |
telegramChatId | string | (none) | Telegram chat to post to: a numeric chat id or @channelusername. The bot must be added to that chat or channel. Needs telegramBotToken. |
slackWebhookUrl | string (secret) | (none) | Slack incoming webhook, https://hooks.slack.com/services/.... |
slackCompatibleWebhookUrl | string (secret) | (none) | Mattermost / Rocket.Chat incoming webhook (public https:// URL; Markdown list, no Block Kit). |
teamsWebhookUrl | string (secret) | (none) | Microsoft Teams Workflows webhook (host ending .logic.azure.com or .powerplatform.com). |
googleChatWebhookUrl | string (secret) | (none) | Google Chat space webhook, https://chat.googleapis.com/v1/spaces/.... |
ntfyTopic | string (secret) | (none) | ntfy topic name; setting it turns ntfy phone pushes on. Pick a long, unguessable name. |
ntfyServer | string | https://ntfy.sh | ntfy server. Only change it for your own public https:// ntfy server. |
ntfyToken | string (secret) | (none) | Optional ntfy access token for a self-hosted server or protected topic. Needs ntfyTopic. |
pushoverUserKey | string (secret) | (none) | Pushover user key. Needs pushoverAppToken. |
pushoverAppToken | string (secret) | (none) | Pushover application API token. Needs pushoverUserKey. |
webhookUrl | string (secret) | (none) | Generic JSON webhook (Zapier, Make, n8n, Pipedream, IFTTT, Home Assistant): the changed rows, 100 per POST. Public https:// only. |
maxNotifications | integer | 25 | 1–100. Most property changes sent to chat and phone channels per run (the webhook is not capped). Extra rows are still in the dataset. Only used when a destination is set. |
At least one URL or zpid is required; up to 5,000 per run. A property given twice (as a URL and as a zpid, say) is fetched once. The three include... switches only shorten the row; the price is the same.
What you get per property
| Category | Fields |
|---|---|
| Identity | zpid, url, inputUrl |
| Address | address, addressStreet, addressCity, addressState, addressZipcode, latitude, longitude |
| Status and type | homeStatus, homeType |
| Price and value | price, currency, zestimate, rentZestimate, lastSoldPrice, soldDate |
| Home facts | bedrooms, bathrooms, livingAreaSqft, lotSizeSqft, yearBuilt, daysOnZillow |
| Interest | pageViewCount, favoriteCount (when Zillow shows them) |
| Costs and tax | hoaFee, propertyTaxRate, taxAssessedValue |
| History | priceHistory (date, event, price), taxHistory (year, taxPaid, value) |
| Neighbourhood | schools (name, rating, distance, level) |
| Listing | description, brokerageName, imageUrls (first 10) |
| Freshness | scrapedAt |
Anything Zillow does not publish is null (or an empty list for histories), never an estimate of ours. Zillow sends a price of 0 for off-market homes; that comes back as null, not $0.
Example output
A real row, parsed from a live Zillow page (a for-sale house in Beverly Hills); the description, price history, tax history, schools and photo lists are shortened here for readability, and the actual row carries them in full:
{"zpid": "20522136","url": "https://www.zillow.com/homedetails/1001-N-Crescent-Dr-Beverly-Hills-CA-90210/20522136_zpid/","address": "1001 N Crescent Dr, Beverly Hills, CA 90210","addressStreet": "1001 N Crescent Dr","addressCity": "Beverly Hills","addressState": "CA","addressZipcode": "90210","latitude": 34.08441,"longitude": -118.414795,"homeStatus": "FOR_SALE","homeType": "SINGLE_FAMILY","price": 20995000,"currency": "USD","zestimate": 18738900,"rentZestimate": null,"bedrooms": 7,"bathrooms": 8,"livingAreaSqft": 7585,"lotSizeSqft": 40902,"yearBuilt": 1955,"daysOnZillow": 98,"pageViewCount": 1384,"favoriteCount": 107,"lastSoldPrice": 18550000,"soldDate": null,"description": "Set behind double gates in one of the most coveted pockets of Beverly Hills - North of Sunset, just behind the iconic Beverly Hills Hotel - this extraordinary estate offers both pedigree and privacy ...","hoaFee": null,"propertyTaxRate": 1.18,"taxAssessedValue": 18921000,"priceHistory": [{ "date": "2026-06-26", "event": "Price change", "price": 20995000 },{ "date": "2025-06-17", "event": "Listed for sale", "price": 22495000 }],"taxHistory": [{ "year": 2026, "taxPaid": null, "value": 18921000 },{ "year": 2025, "taxPaid": 223340.81, "value": 18550000 }],"schools": [{ "name": "El Rodeo Elementary School", "rating": 10, "distance": 1.1, "level": "Elementary" },{ "name": "Beverly Hills High School", "rating": 9, "distance": 1.6, "level": "High" }],"brokerageName": "Carolwood Estates","imageUrls": ["https://photos.zillowstatic.com/fp/a3328bfc7f987dc46ffc910291ea65c3-uncropped_scaled_within_1536_1152.jpg","https://photos.zillowstatic.com/fp/5879ddf38c80f2d0f8c0caa2ca10bf58-uncropped_scaled_within_1536_1152.jpg"],"scrapedAt": "2026-10-03T00:00:00.000Z","inputUrl": "https://www.zillow.com/homedetails/1001-N-Crescent-Dr-Beverly-Hills-CA-90210/20522136_zpid/"}
Use cases
- Investors: pull the Zestimate, tax-assessed value, tax history and price-cut history for every property on a deal list, and rank them in a spreadsheet.
- Agents and brokerages: enrich a CRM or comps sheet with live status, days on Zillow, beds, baths and area for the addresses you already track.
- Proptech products: feed an app or valuation model with a stable, flat schema instead of parsing Zillow pages yourself.
- Lenders and servicers: refresh collateral data (status, price, Zestimate, assessed value, tax history) for a loan or portfolio list on a schedule.
Use it from your code
Pass your list, get rows back. JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('lukehunter/zillow-property-details').call({zpids: [29474600, 20522136, 2131539623],includeSchools: false,});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const home of items) {console.log(home.zpid, home.homeStatus, home.price, home.zestimate);}// Which inputs produced a row, and why not for the others:const outcomes = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord('OUTCOMES');
Python:
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("lukehunter/zillow-property-details").call(run_input={"zpids": [29474600, 20522136, 2131539623], "includeSchools": False})for home in client.dataset(run["defaultDatasetId"]).iterate_items():print(home["zpid"], home["homeStatus"], home["price"], home["zestimate"])outcomes = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("OUTCOMES")["value"]
Or call the HTTP API directly: one request runs the Actor and returns the rows (best for lists of up to about 80 properties, because the synchronous endpoint waits at most five minutes):
curl -X POST "https://api.apify.com/v2/acts/lukehunter~zillow-property-details/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"zpids": [29474600, 20522136], "maxItems": 2}'
For longer lists start an asynchronous run (/acts/lukehunter~zillow-property-details/runs) and read the dataset when it finishes. The same Actor works in Make, Zapier and n8n through the Apify integrations. The OUTCOMES record lists one entry per input in the order you gave them: input, zpid, status (ok, unchanged, blocked, rate-limited, not-found, skipped-robots, invalid-input, duplicate, failed, limit-reached or not-attempted) and a plain-English detail for anything that did not produce a row.
Monitor properties for changes
Run the same list on a schedule and only pay for what moved:
- Create an Apify Schedule (daily, say) for a task with your
urls/zpidsand"onlyChangedSinceLastRun": true. - The first run delivers every property and remembers its price, status and Zestimate.
- Every later run delivers a row only when one of those three changed (or the property is new to the list). Unchanged properties are skipped and not charged. Photos, descriptions or page views changing never trigger a row.
- Add a webhook on run success (or use an integration) to push the new rows to Slack, a database or your CRM.
{"zpids": [29474600, 20522136, 2131539623],"onlyChangedSinceLastRun": true,"stateStoreName": "my-deal-list"}
Use a different stateStoreName for each watch list that should keep its own history. A property blocked on one run keeps its previous state and is compared again next time.
Get Zillow alerts in Discord, Telegram, Slack, Teams, Google Chat, your phone (ntfy/Pushover) or any app (webhook)
Want a Zillow property change alert in Discord, Telegram, Slack, Teams, Google Chat or on your phone? Turn on monitoring mode (onlyChangedSinceLastRun), add one or more destinations in the Actor's Notifications (optional) section and each run sends the properties whose price, status or Zestimate changed. It is a monitor that notifies you: it only reads public Zillow property pages and never contacts agents or owners, buys anything or logs in anywhere.
| Channel | Fill in | What you get |
|---|---|---|
| Discord | discordWebhookUrl | One card per property change, 10 per message |
| Telegram | telegramBotToken + telegramChatId | Up to 10 property changes per message, one line each |
| Slack | slackWebhookUrl | Block Kit message, up to 10 property changes per message |
| Mattermost, Rocket.Chat | slackCompatibleWebhookUrl | Slack-style incoming webhook: a Markdown list (these apps do not render Slack Block Kit) |
| Microsoft Teams | teamsWebhookUrl | Adaptive Card from a Teams Workflows webhook, up to 10 property changes per card |
| Google Chat | googleChatWebhookUrl | Card in a space, up to 10 property changes per message |
| ntfy (phone push, no account) | ntfyTopic (optional ntfyServer, ntfyToken) | A push per property change, up to 10, then one "...and N more" |
| Pushover (phone push) | pushoverUserKey + pushoverAppToken | A push per property change, up to 10, then one "...and N more" |
| Any app: Zapier, Make, n8n, Pipedream, IFTTT, Home Assistant | webhookUrl | One JSON POST per run with the changed rows |
Fill in as many as you like; each channel works on its own and a failing one never stops the others.
Setup, channel by channel
- Discord (1 minute): Server Settings → Integrations → Webhooks → New Webhook → pick the channel → Copy Webhook URL.
- Telegram (2 minutes): chat with @BotFather, send
/newbot, paste the token intotelegramBotToken. Add the bot to the chat or channel (administrator for a channel; for a chat with yourself press Start on the bot).telegramChatIdis a numeric id (123456789, or-1001234567890for a group or channel) or a public@channelusername. - Slack: at api.slack.com/apps create an app (From scratch) → Incoming Webhooks → switch it on → Add New Webhook to Workspace → pick the channel → copy the
https://hooks.slack.com/services/...URL. - Mattermost or Rocket.Chat: create an incoming webhook in the app and paste its public
https://URL intoslackCompatibleWebhookUrl. Localhost, private IP addresses and.local/.internalnames are rejected. - Microsoft Teams: in the channel open ... → Workflows → Post to a channel when a webhook request is received → finish the wizard and copy the URL (a host ending in
.logic.azure.comor.powerplatform.com). The old "Office 365 connector" webhooks are retired and not supported. - Google Chat: in the space open Apps & integrations → Webhooks → Add webhook, name it and copy the
https://chat.googleapis.com/v1/spaces/...URL (needs a Google Workspace account that allows webhooks). - ntfy (free, no account): install the ntfy app (or open ntfy.sh), subscribe to a topic with a long random name, and put the same name in
ntfyTopic. Anyone who knows the topic can read it, so make it unguessable. Own server or a protected topic: setntfyServer(publichttps://address) andntfyToken. - Pushover: copy your user key from pushover.net into
pushoverUserKey, create an application at pushover.net/apps/build and put its API token inpushoverAppToken. Pushover itself is a separate paid app after its trial: check their pricing. - Any app (webhook): paste the catch-hook URL from Zapier, Make, n8n, Pipedream, IFTTT or Home Assistant into
webhookUrl. It must be a publichttps://address.
The recipe: a Zillow property watch in five steps
- List the properties to watch in
urlsand/orzpids. - Turn on
onlyChangedSinceLastRun. Alerts only ever cover changes, so they need monitoring mode. - Add your destination(s) from the table above.
- Run it once. The first run is the baseline: it delivers and remembers every property and sends nothing.
- Create a Schedule (for example daily). From then on you hear about a price, status or Zestimate change.
{"zpids": ["20522136"],"onlyChangedSinceLastRun": true,"maxItems": 100,"ntfyTopic": "your-long-random-topic-name","maxNotifications": 25}
The generic webhook (webhookUrl)
Each run sends one POST per 100 changed rows (so usually one) with this body, followed by whatever your tool does with it:
{"source": "apify","actor": "zillow-property-details","runId": "HG7ML7M8z78YcAPEB","count": 2,"total": 2,"part": 1,"parts": 1,"items": [ { "...": "the full dataset rows" } ]}
count is the number of rows in this POST, total the number in the run, and part / parts number the POSTs when a run delivers more than 100 rows. maxNotifications does not cap the webhook. Your endpoint should answer with a 2xx status; redirects are not followed and a failure is reported in the run status, never retried in a loop.
What to expect
- What a message contains: what the property looks like now: the price, status, Zestimate, bedrooms, bathrooms, size, days on Zillow, home type, a photo and the link.
- Only changes are sent. The first run (the baseline) and a normal run without monitoring mode deliver every property rather than changes, so they send nothing and the status message says why. A run where nothing changed sends nothing.
- An alert shows the property as it is now, not "was X". Monitoring remembers a fingerprint of price, status and Zestimate, not the old values, so an alert names the new ones rather than the previous ones.
maxNotifications(default 25, max 100) caps how many property changes go to chat and phone channels per run (the webhook is not capped). The rest are still in the dataset and the status message says so. ntfy and Pushover send at most 10 individual pushes, then one "...and N more" summary.- Cost: notifications are free. You pay only for delivered properties at the usual price, exactly as without alerts. There is no extra charge for any channel.
- Failures never fail the run. A deleted webhook or an unreachable service leaves the run successful and the dataset complete, and the status message says what happened, for example
Notified: Discord 12, Slack 12, ntfy 10 (+summary). Teams failed (HTTP 404) - check the webhook URL.The logs show the channel name and HTTP status only, never a URL or token. - Your URLs, tokens and ntfy topic are stored as secret inputs. Anyone holding a webhook URL can post to that channel, so treat it like a password.
- The dataset is unchanged. The output rows are identical whether or not you set a destination; the run's status message just gains a short note such as
Notified: Discord 12, ntfy 10 (+summary). - It is a monitor that notifies you. It never contacts agents or owners, buys anything or logs in to Zillow, and the messages go only to the destinations you set up.
Use with AI agents (MCP)
This Actor works as a tool for Claude, ChatGPT, Cursor and other MCP clients through Apify's MCP server. A call needs only urls (Zillow property links) or zpids.
Claude Desktop (claude_desktop_config.json), with your own token from Apify Console > Settings > API & Integrations:
{"mcpServers": {"apify-zillow": {"command": "npx","args": ["-y", "mcp-remote","https://mcp.apify.com?tools=lukehunter/zillow-property-details","--header", "Authorization: Bearer ${APIFY_TOKEN}"],"env": { "APIFY_TOKEN": "<YOUR_APIFY_TOKEN>" }}}}
Clients that support OAuth (Claude.ai, VS Code) can connect with just the URL https://mcp.apify.com?tools=lukehunter/zillow-property-details and sign in to Apify. Never paste a real token into a shared file or chat.
Example. You ask: "What's the Zestimate and last sale price for zpid 29474600?" The agent calls the tool lukehunter--zillow-property-details with:
{"zpids": [29474600],"includePriceHistory": true,"maxItems": 5}
It is charged exactly like any run: per delivered property, nothing for properties that are blocked, not found or skipped. Set maxItems to cap spend.
Pricing and cost control
This Actor uses pay per delivered property pricing: $0.003 per property, no start fee.
| Properties delivered | Cost at $0.003/property |
|---|---|
| 1 | $0.003 |
| 100 | $0.30 |
| 1,000 | $3.00 |
| 5,000 | $15.00 |
maxItems and your run's maximum cost limit both cap spending: each property is charged right after it is delivered, and the Actor stops requesting pages once the limit cannot pay for another one. Blocked, missing, invalid, robots-skipped and unchanged inputs cost nothing.
Notifications to Discord, Telegram, Slack, Teams, Google Chat, ntfy, Pushover and webhooks are free: you pay only for delivered properties, never for messages sent.
Reliability and data quality
- One row per delivered property with the same fields every time; missing values are
null, never guessed. - A property is checked to be the one you asked for: a page that turns out to be a different property, a search page or an off-site redirect is discarded unread.
- One bad input never sinks a run. Each URL or zpid gets its own outcome and the rest continue.
- If Zillow blocks or rate-limits requests, that is reported per input and nothing is charged. This Actor does not use proxies, CAPTCHA solving, cookies, logins or User-Agent rotation. After 10 blocked responses in a row it stops asking and marks the remaining inputs
not-attemptedso you can re-run them later. - It identifies itself honestly, reads Zillow's
robots.txton every run, and makes about one request every three seconds.
Changelog
- 2026-10-10: accepts every common way of pasting a property: mobile links (
m.zillow.com), links withouthttps://, short/homes/<zpid>_zpid/links, bare zpids and pasted lists. Inputs that are not property pages (search pages, other sites) no longer fail the run: they are skipped free, with a message saying what works. The run's success rate on the Store page includes failures from before this fix; they age out of its 30-day window.
Limitations
- US properties only (Zillow's coverage), prices in USD.
- About one request every 3 seconds, so roughly 20 properties per minute at most. A single property returns in seconds.
- Up to 5,000 URLs and zpids and 5,000 delivered rows per run.
- Zillow's
robots.txtdisallows some/homedetails/variants (?view=owner,?altId=...); those inputs are skipped and reported asskipped-robots. - Only single property pages (
zillow.com/homedetails/...) are read. For search results by ZIP code use the Zillow ZIP Code Scraper. - Individual listing agents' names, phone numbers, licence numbers and e-mail addresses are never collected.
brokerageNameis the brokerage business. E-mail addresses and phone numbers typed into a listing description are replaced with[email removed]/[phone removed]. hoaFeeis filled only when Zillow publishes it as a plain number or dollar amount;pageViewCountandfavoriteCountonly when the page shows them;priceisnullfor off-market homes.- Every row is a point-in-time observation identified by
scrapedAt; Zillow data changes continuously. - This is an independent tool and is not affiliated with, endorsed by, or connected to Zillow Group, Inc. Zillow is a trademark of its owner. You are responsible for using the data in accordance with applicable terms and laws.
Use it from your code, Make, Zapier or n8n
Built for automated pipelines: small runs, stable field names, one row per item, and you pay only for rows actually delivered.
One API call that runs the Actor and returns the data (replace $APIFY_TOKEN with your token from Apify Console → Settings → Integrations):
curl -s -X POST "https://api.apify.com/v2/acts/lukehunter~zillow-property-details/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"urls": ["https://www.zillow.com/homedetails/1003-Juanita-St-Austin-TX-78704/29474600_zpid/", "https://www.zillow.com/homedetails/1001-N-Crescent-Dr-Beverly-Hills-CA-90210/20522136_zpid/", "https://www.zillow.com/homedetails/100-W-27th-St-APT-5S-New-York-NY-10001/2131539623_zpid/"], "maxItems": 10}'
JavaScript (npm i apify-client):
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('lukehunter~zillow-property-details').call({"urls": ["https://www.zillow.com/homedetails/1003-Juanita-St-Austin-TX-78704/29474600_zpid/","https://www.zillow.com/homedetails/1001-N-Crescent-Dr-Beverly-Hills-CA-90210/20522136_zpid/","https://www.zillow.com/homedetails/100-W-27th-St-APT-5S-New-York-NY-10001/2131539623_zpid/"],"maxItems": 10});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python (pip install apify-client):
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('lukehunter~zillow-property-details').call(run_input={"urls": ["https://www.zillow.com/homedetails/1003-Juanita-St-Austin-TX-78704/29474600_zpid/", "https://www.zillow.com/homedetails/1001-N-Crescent-Dr-Beverly-Hills-CA-90210/20522136_zpid/", "https://www.zillow.com/homedetails/100-W-27th-St-APT-5S-New-York-NY-10001/2131539623_zpid/"], "maxItems": 10})items = client.dataset(run['defaultDatasetId']).list_items().items
Schedules, webhooks and no-code tools: save your input as a Task, add a Schedule (e.g. hourly or daily), and attach a webhook or one of the Integrations tab's connectors (Make, Zapier, n8n, Google Sheets, Slack) to push each run's results into your own system.
Only new items each run: set "onlyChangedSinceLastRun": true on a scheduled Task and every run after the first delivers, and charges for, only items it hasn't delivered before for that same input. That makes it a ready-made change feed.
Reliability: an automated test runs this Actor's parser against the live site every day, and failures are fixed fast.
Feedback: an honest rating on the Store page, good or bad, helps others decide if this Actor fits their needs. Missing a field or found a problem? Open an issue on the Actor page.
FAQ
Can I use just zpids?
Yes. A zpid is the number in a Zillow property URL (.../29474600_zpid/). The Actor requests zillow.com/homedetails/<zpid>_zpid/; if Zillow does not resolve a zpid to a property page, that input is reported as not-found or failed in OUTCOMES and nothing is charged.
Why is price null on some properties?
Zillow shows no asking price for off-market and recently sold homes (it sends 0 internally). The Actor returns null rather than $0. Use lastSoldPrice and soldDate when Zillow publishes them, and zestimate for its own estimate.
Why is zestimate null on a rental?
Zillow publishes a rent Zestimate for most rentals instead; see rentZestimate.
What does a "Price change" in priceHistory mean?
priceHistory reproduces Zillow's own event list: date, event (for example "Listed for sale", "Price change", "Sold", "Listing removed") and the price at that event, newest first. Some events, such as a sale in a non-disclosure state, have no price and return null.
Does it collect agent or owner contact details?
No. Only listing and property fields are returned. See the Limitations section.
Can I look up properties by address or ZIP code?
Not with this Actor: it needs a property URL or zpid. Use the Zillow ZIP Code Scraper to find properties by ZIP, then pass their zpid values here.
Do I need a Zillow account or API key?
No. The Actor reads public property pages as a signed-out visitor and stops if Zillow serves a block or challenge page.
Can I get Zillow alerts by email?
Not natively. There are two routes. (1) Set webhookUrl to a Zapier, Make or n8n catch hook and add an email or Gmail step: the webhook delivers the property changes as JSON, so the email can list them. (2) Apify's own run integrations and run notifications can email you when a run finishes, but they only send a link to the run or dataset, not the property changes themselves. For instant alerts without building anything, Telegram, ntfy or Pushover reach your phone directly.
Can I get Zillow alerts in WhatsApp?
Not natively, and we do not use unofficial WhatsApp APIs, which risk getting your number banned. The official route is the WhatsApp Business Platform (Cloud API) with its own business account, message templates and pricing: point webhookUrl at a Zapier, Make or n8n flow that calls it. For free phone alerts use Telegram or ntfy instead.
Related Actors
Other data tools from the same developer, built to the same standard: official or public sources, hard cost caps, and honest documentation of limits.
- Zillow Price Drop & New Listing Monitor: stateful ZIP-code change events for Zillow: new listings, price cuts and removed listings, run on a schedule.
- Rightmove Property Scraper: UK property listings from Rightmove search results, with price, address, bedrooms and agent details.
- Rightmove Property Details Scraper: full UK property records by URL or ID: price, status, features, history, with a change-only mode.
- UK Tenders Monitor: new UK public-sector tenders from Contracts Finder and Find a Tender, filtered by CPV code, value, region and buyer, with Slack, Discord and Telegram alerts.
- TED EU Tenders Monitor: new EU public tenders, awards and prior information notices from TED (Tenders Electronic Daily), filtered by CPV code, buyer country, value and keyword, with Slack, Discord and Telegram alerts.
- USAspending Federal Contract Awards Monitor: US federal contract awards from the official USAspending API: winners, amounts, agencies and NAICS codes, with new-award alerts to Slack, Discord and Telegram.
- Bank Branch Closings & Merger Radar (FDIC): new US bank branch closings, openings and mergers from the FDIC.
- Chicago New Business License Radar: newly licensed Chicago businesses as opening leads, grouped by category.