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%!
All notable changes to the Zillow Property & Agent Data Scraper actor are documented here.
The format follows Keep a Changelog .
[2.3.56] - 2026-05-07
Changed
Top-level input-schema description reformatted to a 3-bullet layout — each step on its own line, bold labels (Choose Operation Mode | Inside Selected Mode | Tuning), and a link to the README's Tips & Best Practices anchor for cost / performance / data-quality guidance.
Fixed
README — removed unverified "Off-peak hours tend to have warmer upstream caches" claim from the Tips & Best Practices Performance section. The actor's runtime isn't tied to time-of-day; the surviving performance guidance (per-call upstream timeout, ZIP-batch dedup) lives under a renamed Batching & Bounds sub-block.
[2.3.55] - 2026-05-07
Changed
Top-level input-schema description rewritten to mirror the README's new "How to use it" decision flow (Choose Operation Mode → fill mode-specific input → tune ⚙️ Enrichments + 🔬 Filters). Customers and AI agents reading the schema now see the same 3-step framing as the README, instead of a flat enumeration of modes. Length 322 → 438 chars (in band, ≤500). No code or input-field changes.
[2.3.54] - 2026-05-07
Changed
README — added a 🧭 How to use it (in one screen) decision flow above the per-mode deep dives (Choose Operation Mode → Inside Selected Mode → Tuning) plus a full 💡 Tips & Best Practices section before the FAQ (4 sub-sections: Getting Maximum Results, Cost Optimization, Performance, Data Quality). Customers were getting lost between ZIP / ZPID / URL modes — the new top-of-page flow makes the mode-decision and the per-mode required fields visible in one screen, and the Tips block consolidates cost-capping, sold-listings-defaults, nullable-column, and SKIPPED_ITEMS patterns that previously lived only in inline tips. No code changes.
[2.3.53] - 2026-05-07
Fixed
photos[] column was returning only the main listing photo (single-element array) when enrichPhotos: true was set. Root cause: the upstream photos endpoint returns a {images: [url1, url2, ...]} envelope, but the mapping code expected a top-level array of photo objects. Customers toggling the flag have been getting [mainPhoto] instead of the full gallery since the feature shipped. New code handles both shapes (envelope and array) and both string and object items.
[2.3.52] - 2026-05-07
Fixed
walkScore, transitScore, and bikeScore columns are no longer silently null when enrichWalkScore is enabled. The mapping accessor was reading .score on the upstream response, but the upstream uses distinct lowercase keys per metric (walkscore / transit_score / bikescore) — three columns had been emitting null on every enriched row since the feature shipped. New fallback chain (?.walkscore ?? ?.score ?? null, etc.) keeps it forward-compatible if the upstream ever switches to a unified .score key.
[2.3.51] - 2026-05-07
Changed
Related actors section now lists the full Zillow family — zillow-url-search (paste any Zillow search URL) and zillow-mcp-server (MCP integration for Claude Desktop / Cursor / ChatGPT) added alongside the existing zillow-zip-search row.
[2.3.50] - 2026-05-06
Changed
Related actors section now lists only Zillow-domain actors. Replaced the cross-domain narrative paragraph (Instagram / TikTok / YouTube author-profile pitch) with a 2-row table that surfaces the lighter single-mode zillow-zip-search spinoff as the natural alternative for users who only need ZIP-code input. Discoverability win for both actors — visitors landing on the multi-mode parent now see the simpler ZIP-only option without leaving the page.
[2.3.49] - 2026-05-06
Fixed
Per-field output documentation now visible in the Apify Console and to API/MCP clients. The 74-column dataset schema (titles, descriptions, types, examples for every output field) shipped with 2.3.43 had been silently ignored because .actor/actor.json carried an inline display-only block instead of pointing to ./dataset_schema.json. AI agents reading the dataset shape via API and visitors browsing the Console dataset view now see the same per-column documentation that's always been on disk.
Widened lotAreaValue and daysOnZillow type unions to include string. Both columns occasionally come back from the upstream feed as pre-formatted strings instead of raw numbers; the previous integer/number/null union rejected those rows, producing zero dataset items in the brief window after the wiring fix above and before this build. No change to dataset shape — strings have always been emitted in those columns when upstream returned them.
[2.3.47] - 2026-05-06
Added
Test-run cap on demo input. ZIP-mode runs that leave the ZIP code at the example value 90210 and don't set any filters now cap output at 10 properties (~$0.80 max on FREE tier, ~$0.50 on DIAMOND), making "Try" runs predictable on any plan. Previously, paid customers experimenting with the default seed could trigger uncapped enrichment of however many listings 90210 currently returns ($4–14+ per trial). A console banner explains the cap, and a USER_MESSAGE Storage record with id test_run_default_input_v1 makes the same explanation visible to API-origin runs that never open the run console.
The cap is restored to the normal plan limit (paid: unlimited; free: 15 properties / run) as soon as you change the ZIP code, add at least one filter, or switch to ZPID list / Zillow URL mode.
[2.3.46] - 2026-05-06
Fixed
Same property no longer appears multiple times in the dataset when input ZIPs resolve to overlapping locations. Previously, ZIP-code mode runs whose input ZIPs all mapped to the same city (e.g., 20 Manhattan ZIPs → "New York, NY") fired the same search query once per batch of 5 ZIPs and re-emitted the same listings each time, charging the per-property paid event multiple times for one property. The actor now (a) skips a batch entirely when its ZIPs are already covered by an earlier batch's resolved location, and (b) tracks already-processed zpids and skips re-enrichment if the same property is returned by two different searches.
ZPID-mode runs that pass the same zpid more than once (e.g., a list with accidental duplicates) now charge & emit the property once instead of once per occurrence. Duplicate ZPIDs are recorded in SKIPPED_ITEMS with category duplicate.
[2.3.45] - 2026-05-05
Fixed
URL-mode runs no longer hang for the full platform timeout when an upstream listings request stalls. Each fetch attempt is now bounded at 15 seconds so transient slowdowns surface as a normal retry/error instead of a 12-minute run abort. Same bounding applies to ZIP / ZPID modes — latent there because their endpoints are cache-warmer.
[2.3.44] - 2026-05-05
Fixed
ZIP-code mode now reliably returns listings for every covered ZIP. Previously, ZIP codes that the upstream listings provider did not recognize as a "named place" (most rural and small-town ZIPs, e.g. 20101 Aldie VA, 60019 Des Plaines IL) silently returned zero results — the run completed without errors but produced an empty dataset. The actor now resolves each ZIP to its city/state via a bundled US locality database before searching, and accepts both standard and minimal upstream response shapes. Customers using these ZIPs will start getting data on their next run.
ZIPs that aren't in the US locality database (rare P.O.-only or unassigned codes such as 10809, 11617, 12425) are now recorded in the SKIPPED_ITEMS storage record with category not_resolvable and a clear instruction to use a wider area / city name, instead of silently returning empty.
[2.3.43] - 2026-05-04
Changed
README restructured to the LLM-discoverability template (16 sections, ~370 lines). Added an Apify status badge, an output sample inside the first 25 % of the page, a pay-per-event pricing table (replacing the older Compute-Units prose), a Free-vs-paid table, dedicated Resume / Storage Records / Programmatic-API sections, and a tighter Related-actors pointer.
Every output column now has a per-field description, type, and example available in the Apify Console's dataset view and to clients that read the actor schema programmatically — covers all 74 emit-able columns across the 3 operation modes (ZIP / ZPID / URL).
Top-level Input description rewritten to lead with the 3-mode positioning and pay-per-event pricing model so agent clients pick the right mode without reading the full schema.
SEO description tightened on the Apify Store page (no functional change).
[2.3.42] - 2026-05-03
Fixed
The USER_MESSAGE Storage record (welcome banner on a paid user's 1st run, check-in on the 3rd) now reliably lands. Previously it silently degraded to a no-op due to a per-actor named-storage scoping issue specific to this account.
[2.3.41] - 2026-05-03
Added
New SKIPPED_ITEMS Storage record listing every zpid / ZIP / URL skipped during the run, with reason and category (filter, not_found, error, free_limit). Open the Storage tab → SKIPPED_ITEMS to see exactly which items hit which reason, and which ones errored (re-run those — most errors are transient). The Log also prints up to 3 examples per category at the end of the run.
New FREE_LIMITS_APPLIED Storage record on free-plan runs that hit any of the free-tier ceilings (15-property cap, 20-ZIP cap, $1.20 budget, agent-email masking). Each entry has a stable id code for programmatic consumption. Empty/omitted on paid runs.
New USER_MESSAGE Storage record on a paid user's 1st and 3rd paid run — short onboarding/check-in tips, also embedded in RUN_SUMMARY.
[2.3.38] - 2026-05-01
Fixed
Empty mode-specific input fields (ZIP Codes / ZPID List / Zillow Search URL) now exit with a "Configuration Error" stop reason instead of an unhandled error message, so it's clearer that the run was rejected due to input rather than an actor crash. Run still ends with FAILED status — only the message text changes.
[2.3.37] - 2026-04-30
Fixed
Lifted the hard cleanup deadline from 30 seconds to 60 seconds. With every finalize step now bounded by 2.3.36's 3-second timeouts, normal post-processing budget is roughly 12 seconds of bounded finalize plus the existing 20-second completed-screen display, which was bumping into the 30-second deadline; the 60-second window leaves comfortable headroom while still terminating any truly stuck run well before the 180-second platform timeout.
[2.3.36] - 2026-04-30
Fixed
Bound every async finalization step (run-summary write, run-metadata fetch, first-run timestamp, analytics POST, status-page write) with a 3-second timeout each. Previous attempts assumed only the non-default key-value-store helpers stalled, but logs showed finalization hanging silently before those calls; bounding all of them ensures the run reliably exits within ~25 seconds of "Processing complete!" without falling back to the force-exit safety net.
[2.3.35] - 2026-04-30
Fixed
Bounded the non-default key-value-store calls inside the analytics helpers with a 3-second timeout each, so they fail fast under LIMITED_PERMISSIONS instead of hanging silently.
[2.3.34] - 2026-04-30
Fixed
Added a 30-second cleanup safety net so runs always terminate, even if the post-run analytics or key-value-store calls stall silently. Prevents the run from hitting the 180-second platform timeout when finalization paths hang on permission errors.
[2.3.33] - 2026-04-30
Maintenance build — no user-facing changes.
[2.3.32] - 2026-04-30
Fixed
Followup to 2.3.31: closing the Live View server alone was not enough — keep-alive sockets from outbound HTTP fetches also held the event loop open. Added explicit Actor.exit(0) after the completed-screen window so the run terminates promptly. Completed runs now show SUCCEEDED within ~25 seconds of "Processing complete!" instead of hitting the 180-second hard timeout.
[2.3.31] - 2026-04-30
Fixed
Run no longer hangs ~160 seconds after "Processing complete!" before exiting. The Live View web-server's existing connections are now actively closed before shutdown, so runs terminate within ~20 seconds of completion (the existing completed-screen display window) instead of hitting the 180-second hard timeout. Affects user-visible run status: completed runs now show SUCCEEDED instead of TIMED-OUT.
Changed (internal)
Analytics runStatus field is now computed locally (SUCCEEDED/FAILED) rather than read from the still-in-progress runs/last metadata, which was reliably empty during the analytics POST.
[2.3.30] - 2026-04-29
Maintenance build — no user-facing changes. Internal analytics fixes only;
input schema, output dataset columns, KVS records, console output, error
messages, defaults, and pricing are all unchanged from 2.3.29.