# Zillow Sold Comps Scraper | 26 Fields, Up to 730 Days Back (`themineworks/zillow-recently-sold`) Actor

Scrape Zillow recently sold properties by city or zip for CMA reports, investment analysis, and market research. Filter by sold date range (30 to 365 days), price, beds, and property type. Extract sold price, date, address, beds, baths, sqft, Zestimate and listing URL.

- **URL**: https://apify.com/themineworks/zillow-recently-sold.md
- **Developed by:** [The Mine Works](https://apify.com/themineworks) (community)
- **Categories:** Real estate, Lead generation, MCP servers
- **Stats:** 35 total users, 15 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 zillow 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 Sold Comps Scraper | 26 Fields, Up to 730 Days Back

[![984 Phoenix home sales, every one priced: a recorded run returned 984 Phoenix, AZ sales of the last 30 days, each with its sale price and sold date](https://api.apify.com/v2/key-value-stores/cUXz95yxflDho41nn/records/zillow-recently-sold-hero-fix0930.png)](https://console.apify.com/actors/fiWuQcfObGWn1dm4J/input?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

From **The Mine Works**, makers of [Threads Scraper](https://apify.com/themineworks/threads-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) and [B2B Leads Finder](https://apify.com/themineworks/b2b-leads-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), with nearly 139,000 runs across our actors. This actor ranks #1 for "zillow recently sold" in Apify Store search.

### Why choose this actor?

- **Up to Zillow's full page of results, each with its sale price.** A recorded run of the current version asked for Phoenix, AZ homes sold in the last 30 days and returned 984 sales, every one with `soldPrice`, `soldDate` and `soldDateIso`. Zillow counted 1,286 and serves about 1,000 of any one search. No Zillow account, no API key, no browser.
- **You pay only for sales that have a price.** Texas, Utah and other non-disclosure states keep sale prices private. Those sales come free and labelled (`priceDisclosed: false`), or are left out if you choose, and are never charged.
- **A sold window you set to the day, 1 to 730 days.** `soldInLast` goes straight into Zillow's own date filter, and a second check drops any row older than the window. In the recorded Phoenix run, 0 rows had to be dropped.
- **No duplicate charges, and only new sales on repeat runs.** A sale is delivered and charged once per run even when Zillow repeats a page, and monitor mode skips sales it already delivered to you in earlier runs, so a weekly comps watch pays only for new closings.

[![Run it on Apify](https://api.apify.com/v2/key-value-stores/cUXz95yxflDho41nn/records/button-run.png)](https://console.apify.com/actors/fiWuQcfObGWn1dm4J/input?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Part of The Mine Works Real estate family:** [Zillow Rentals Scraper](https://apify.com/themineworks/zillow-rental-listings?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [India Real Estate MCP](https://apify.com/themineworks/india-real-estate-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [Housing.com Scraper](https://apify.com/themineworks/housing-com-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [MagicBricks Scraper](https://apify.com/themineworks/magicbricks-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [Zillow Property Scraper](https://apify.com/themineworks/zillow-property-details?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral), [99acres Scraper](https://apify.com/themineworks/99acres-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral).

### Try it in one minute

Paste this into the input's JSON tab and start the run. It returns 20 Phoenix, AZ homes sold in the last 30 days, each with its sale price.

```json
{
  "location": "Phoenix, AZ",
  "soldInLast": 30,
  "maxItems": 20
}
```

`location` takes a city and state (`"Phoenix, AZ"`, `"Palo Alto, CA"`), a ZIP code (`"85016"`), or a neighborhood name. The actor looks it up with Zillow's own location search and uses the first region Zillow suggests, so a specific city and state or a ZIP code works best. One location per run.

Apify's free plan includes $5 of credit every month, which covers about 2,500 sold homes with a price at this actor's price (the Free plan rate of $0.002 per home; there is no start fee, and sales without a price are free).

**Texas and other non-disclosure states:** Zillow's search results carry no sale price for sales in states that keep prices private. We checked Texas; Utah, Idaho, Kansas, Louisiana, Mississippi, Missouri, Montana, New Mexico, North Dakota, Wyoming and Alaska also keep prices private, and a row without a price is handled the same way wherever it comes from. In a recorded Austin, TX run of the last 30 days, none of the 148 rows had a price, so none was charged: each came with `priceDisclosed: false`, a `priceNote`, the sold date, the home's details and usually Zillow's `zestimate`. Set `rowsWithoutSalePrice` to `"skip"` to leave such sales out. A search that finds only unpriced sales earns nothing, so the run stops after about 11 page requests (up to about 450 free rows) to bound its cost. In disclosure states such as Arizona, Washington, Colorado and Oregon, every row in our recorded runs carried `soldPrice`.

#### Copy to your AI assistant

```
themineworks/zillow-recently-sold on Apify. Returns homes sold on Zillow in one US city, ZIP code or neighborhood within the last N days, with sale date, sale price where the state publishes it, beds, baths, square feet, Zestimate, address and coordinates. Call ApifyClient("TOKEN").actor("themineworks/zillow-recently-sold").call(run_input={...}), then client.dataset(run["defaultDatasetId"]).list_items().items. Required: location (for example "Phoenix, AZ" or "85016"). Optional: soldInLast (days, default 90, 1 to 730), maxItems (default 100, up to 2000, but Zillow serves about 1,000 per search), minPrice, maxPrice (USD), minBeds, minBaths, propertyType (Zillow home type such as "SINGLE_FAMILY", "CONDO", "TOWNHOUSE", "MULTI_FAMILY", "MANUFACTURED", "LOT"; "LAND" means "LOT"; any case; blank for all), rowsWithoutSalePrice ("deliverFree" default, or "skip"), monitorMode (default false). soldDate is epoch milliseconds as Zillow sends it (for example 1790665200000); soldDateIso holds the same date as "2026-09-29". priceDisclosed is false on sales with no public price (Texas and other non-disclosure states); those rows are never charged. Sale rows have no _type field; each run adds one row with _type "summary" and, when it delivered sales, one with _type "info"; neither is charged. Full spec: GET https://api.apify.com/v2/acts/themineworks~zillow-recently-sold/builds/default (Bearer TOKEN), which returns inputSchema and readme. Token: https://console.apify.com/account/integrations?fpr=ymnoit&utm_source=apify-readme&utm_medium=referral
```

### Key features

- **25 fields per priced sale in our recorded runs.** Sale date (`soldDate` in epoch milliseconds, `soldDateIso` as YYYY-MM-DD), sale price (number and Zillow's own label), whether the price is public, beds, baths, square feet, property type, days on Zillow, Zillow's value and rent estimates, address in five parts, coordinates, photo and listing link. A field Zillow does not publish for a sale is left out of that row rather than sent empty.
- **Only priced sales are charged.** A sale without a public price is delivered free with `priceDisclosed: false` and a `priceNote`, or left out with `rowsWithoutSalePrice: "skip"`.
- **Any window from 1 to 730 days.** `soldInLast` is sent to Zillow as its own "sold in the last N days" filter, which takes any whole number of days, not only 30, 90 or 365.
- **Filters sent to Zillow's search.** `minPrice`, `maxPrice`, `minBeds`, `minBaths` and `propertyType` narrow the search on Zillow's side, so a lot or condo search pages through that type only. `APARTMENT` is the one home type Zillow has no search filter for; it is checked on each row after it arrives.
- **About 1,000 sales per search, no duplicates.** The run follows Zillow's pages to the real end of the results and stops when Zillow starts repeating itself, so no sale is charged twice in a run.
- **Monitor mode.** With `monitorMode` on, the actor remembers each sale it delivered to you, keyed on `zpid`, and later runs deliver only new closings.
- **A summary row on every run.** It shows Zillow's own count for your search (`total_available`), how many rows were delivered and charged, and why the run stopped.

### How to use it

#### Basic: comps for one ZIP code

```json
{
  "location": "78704",
  "soldInLast": 180,
  "maxItems": 300
}
```

#### Comps that match a subject property

```json
{
  "location": "Denver, CO",
  "soldInLast": 90,
  "minPrice": 600000,
  "maxPrice": 900000,
  "minBeds": 3,
  "minBaths": 2,
  "propertyType": "SINGLE_FAMILY",
  "maxItems": 200
}
```

`propertyType` takes one of Zillow's home types: `SINGLE_FAMILY`, `CONDO`, `TOWNHOUSE`, `MULTI_FAMILY`, `MANUFACTURED`, `LOT` or `APARTMENT`. Case does not matter, and `LAND` works too (Zillow calls land `LOT`). The first six are sent to Zillow as its own home type filter: in a recorded Phoenix, AZ run of the last 90 days, `LAND` returned 20 of 20 rows as lots, from the 108 lot sales Zillow counted, where an unfiltered page holds about one lot in 41 sales. The summary's `total_available` then counts that type only.

#### Several markets at once

The actor reads one `location` per run. For several ZIP codes, save one task per market or start runs in a loop from the API:

```python
from apify_client import ApifyClient
client = ApifyClient("TOKEN")
rows = []
for zip_code in ["98103", "98107", "98117"]:
    run = client.actor("themineworks/zillow-recently-sold").call(
        run_input={"location": zip_code, "soldInLast": 90, "maxItems": 1000})
    rows += client.dataset(run["defaultDatasetId"]).list_items().items
```

ZIP codes are also the way past Zillow's limit of about 1,000 sales per search in a large metro. Dedupe on `zpid` if your areas overlap.

#### Monthly market report

```json
{
  "location": "Seattle, WA",
  "soldInLast": 30,
  "maxItems": 1000
}
```

Schedule it on the first of each month. Group the rows by `zipCode` and `propertyType`, then take the median `soldPrice` and `daysOnZillow` over rows with `priceDisclosed: true`. In Texas and other non-disclosure states, where those rows are absent, `zestimate` on the free rows is the nearest price signal.

#### Weekly new closings watch

```json
{
  "location": "Hood River, OR",
  "soldInLast": 30,
  "maxItems": 500,
  "monitorMode": true
}
```

Save it as a task and schedule it weekly. The first run delivers every sale in the window. Each later run delivers and charges only sales it has not delivered to you before, and the summary row counts the rest in `already_delivered_in_earlier_run`. Keep the location and filters the same between runs.

#### Gross yield screen for investors

Run this actor and [Zillow Rentals Scraper](https://apify.com/themineworks/zillow-rental-listings?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) on the same ZIP codes. Divide the typical rent for a bedroom count by the typical sale price for the same bedroom count to get a gross yield by ZIP. Sold rows also carry `rentZestimate`, Zillow's own rent estimate for that home, when Zillow has one.

### Input parameters

| Parameter | Type | Default | What it does |
|---|---|---|---|
| `location` | string | none (required) | City and state, ZIP code or neighborhood, for example `"Phoenix, AZ"` or `"85016"`. One per run. |
| `maxItems` | integer | `100` | Most sales to deliver, 1 to 2000. Zillow serves about 1,000 per search, so a larger value stops there. This is also your cost cap. |
| `soldInLast` | integer | `90` | Only homes sold in the last N days, 1 to 730. Any whole number works. |
| `minPrice` | integer | none | Lowest sale price in USD. Sent to Zillow's search. |
| `maxPrice` | integer | none | Highest sale price in USD. Sent to Zillow's search. |
| `minBeds` | integer | none | Fewest bedrooms, 0 to 10. |
| `minBaths` | integer | none | Fewest bathrooms, 0 to 10. |
| `propertyType` | string | blank (all types) | One of Zillow's home types: `SINGLE_FAMILY`, `CONDO`, `TOWNHOUSE`, `MULTI_FAMILY`, `MANUFACTURED`, `LOT` (or `LAND`), `APARTMENT`. Any case. Sent to Zillow's search, except `APARTMENT`, which is checked on each row. |
| `rowsWithoutSalePrice` | string | `"deliverFree"` | What to do with sales that have no public price (Texas and other non-disclosure states). `"deliverFree"` delivers them free with `priceDisclosed: false` and a `priceNote`; `"skip"` leaves them out. Never charged either way. |
| `monitorMode` | boolean | `false` | Delivers and charges only sales not delivered to you in an earlier run. Keep the location and filters the same across runs. |

### What data do you get?

One row per sold home, plus one summary row per run. Sale rows have no `_type` field.

**The sale:** `soldDate` (the sale date as Zillow sends it, epoch milliseconds, for example `1790665200000`; unchanged from earlier versions), `soldDateIso` (the same date as `YYYY-MM-DD`, for example `"2026-09-29"`, the date Zillow shows as "Sold 09/29/26"), `soldPrice` and `price` (the sale price in USD, the same number in both, present where the sale price is public), `priceLabel` (Zillow's own text for it, for example `"$367,500"`), `priceDisclosed` (`true` when the row has a sale price and was charged, `false` when it has none and was delivered free), `priceNote` (on unpriced rows only, why there is no price), `daysOnZillow`, `statusType` (always `RECENTLY_SOLD`), `statusText` (Zillow's own word, `Sold` or `Closed`).

**The home:** `beds`, `baths`, `sqft`, `propertyType` (`SINGLE_FAMILY`, `CONDO`, `TOWNHOUSE`, `MULTI_FAMILY`, `APARTMENT`, `MANUFACTURED`, `LOT`), `zestimate` (Zillow's value estimate), `rentZestimate` (Zillow's rent estimate).

**Location and links:** `address`, `addressLine1`, `city`, `state`, `zipCode`, `latitude`, `longitude`, `detailUrl`, `imgSrc`, `zpid` (Zillow's property ID). `imgSrc` is the listing photo, or a satellite map image of the lot when Zillow has no photo for the sale (382 of 862 rows in a recorded 90 day Austin run, 67 of 148 in a 30 day one).

**Summary row** (`_type: "summary"`, never charged): `location`, `sold_in_last_days`, `total_available` (Zillow's own count for the search), `pages_fetched`, `total_scraped`, `charged_for`, `rows_without_sale_price` (your setting), `delivered_free_no_sale_price`, `skipped_no_sale_price` (with `"skip"`), `duplicates_skipped`, `filtered_out_by_property_type` (when `propertyType` is set), `filtered_out_stale`, `stop_reason`, `ended_on_deadline`, `already_delivered_in_earlier_run`, the monitor counts, and a few cost guard counters.

`stop_reason` is `max_items` (reached your limit), `end_of_results` (Zillow had no more), `repeated_page` (Zillow started repeating sales, its way of signalling the end), `page_failed` (Zillow blocked a page three times), `deadline` (the run's timeout came first), or `yield_guard` / `profit_guard` (the run stopped paying for pages that delivered nothing, or, for `profit_guard`, for pages of unpriced sales that earn nothing; the log then says so).

**Info row** (`_type: "info"`, never charged): on runs that delivered at least one sale, the count and a note on scheduling.

#### Stable fields for automations

These fields were present in every row of our recorded runs of the current version (984 Phoenix, AZ rows and 148 Austin, TX rows); all but `priceDisclosed` and `soldDateIso` were also on every row of our earlier Austin, Seattle, Denver and Hood River runs. Their names will not change, so a sheet, Zapier zap or n8n flow can map them once.

| Field | What it is |
|---|---|
| `zpid` | Zillow property ID, the key to store and join on |
| `address` | Full address |
| `addressLine1` | Street line, with the unit when there is one |
| `city` | City |
| `state` | Two letter state code |
| `zipCode` | ZIP code |
| `soldDate` | Sale date, epoch milliseconds |
| `soldDateIso` | Sale date, `YYYY-MM-DD` |
| `priceDisclosed` | `true` for a priced (charged) sale, `false` for a free one |
| `propertyType` | Zillow home type |
| `statusType` | Always `RECENTLY_SOLD` |
| `statusText` | `Sold` or `Closed` |
| `daysOnZillow` | Days on Zillow as Zillow reports it for the sale |
| `detailUrl` | Link to the home on Zillow |
| `imgSrc` | Photo, or a satellite map image |

`soldPrice`, `price` and `priceLabel` were on every row in Arizona, Washington, Colorado and Oregon and on none in Texas; filter on `priceDisclosed` rather than on their presence. `beds`, `baths`, `sqft`, `zestimate`, `latitude` and `longitude` are missing on some rows (for example `beds` was missing on 67 of the 984 Phoenix rows, and on 185 of 862 rows in a 90 day Austin run).

#### Output examples

**A single family sale with its price** (recorded Phoenix, AZ run of the current version; photo and link as delivered):

```json
{
  "zpid": "7469424",
  "address": "7728 W CHEERY LYNN Road, Phoenix, AZ 85033",
  "addressLine1": "7728 W CHEERY LYNN Road",
  "city": "Phoenix",
  "state": "AZ",
  "zipCode": "85033",
  "price": 367500,
  "priceLabel": "$367,500",
  "beds": 4,
  "baths": 2,
  "sqft": 1570,
  "propertyType": "SINGLE_FAMILY",
  "statusType": "RECENTLY_SOLD",
  "statusText": "Sold",
  "daysOnZillow": 1,
  "zestimate": 367600,
  "rentZestimate": 2086,
  "latitude": 33.483936,
  "longitude": -112.22516,
  "detailUrl": "https://www.zillow.com/homedetails/7728-W-Cheery-Lynn-Rd-Phoenix-AZ-85033/7469424_zpid/",
  "imgSrc": "https://photos.zillowstatic.com/fp/52f473460b27065855a9d20c0143220c-p_e.jpg",
  "soldPrice": 367500,
  "priceDisclosed": true,
  "soldDate": 1790665200000,
  "soldDateIso": "2026-09-29"
}
```

**A townhouse sale** (same run):

```json
{
  "zpid": "7480682",
  "address": "9020 W HIGHLAND Avenue #115, Phoenix, AZ 85037",
  "addressLine1": "9020 W HIGHLAND Avenue #115",
  "city": "Phoenix",
  "state": "AZ",
  "zipCode": "85037",
  "price": 199999,
  "priceLabel": "$199,999",
  "beds": 2,
  "baths": 2,
  "sqft": 863,
  "propertyType": "TOWNHOUSE",
  "statusType": "RECENTLY_SOLD",
  "statusText": "Sold",
  "daysOnZillow": 1,
  "zestimate": 200100,
  "rentZestimate": 1456,
  "latitude": 33.50657,
  "longitude": -112.25347,
  "detailUrl": "https://www.zillow.com/homedetails/9020-W-Highland-Ave-UNIT-115-Phoenix-AZ-85037/7480682_zpid/",
  "imgSrc": "https://photos.zillowstatic.com/fp/b9e5eb7e7bc15e61e60435dd290f0c5a-p_e.jpg",
  "soldPrice": 199999,
  "priceDisclosed": true,
  "soldDate": 1790665200000,
  "soldDateIso": "2026-09-29"
}
```

**A Texas sale with no public price, delivered free** (recorded Austin, TX run of the current version, last 30 days):

```json
{
  "zpid": "29366381",
  "address": "6026 Tributary Ridge Dr, Austin, TX 78759",
  "addressLine1": "6026 Tributary Ridge Dr",
  "city": "Austin",
  "state": "TX",
  "zipCode": "78759",
  "beds": 4,
  "baths": 4,
  "sqft": 3654,
  "propertyType": "SINGLE_FAMILY",
  "statusType": "RECENTLY_SOLD",
  "statusText": "Sold",
  "daysOnZillow": 1,
  "zestimate": 1373500,
  "rentZestimate": 5931,
  "latitude": 30.411043,
  "longitude": -97.76304,
  "detailUrl": "https://www.zillow.com/homedetails/6026-Tributary-Ridge-Dr-Austin-TX-78759/29366381_zpid/",
  "imgSrc": "https://photos.zillowstatic.com/fp/7986b80322175a079a4b9cfc30e33c98-p_e.jpg",
  "priceDisclosed": false,
  "soldDate": 1790665200000,
  "soldDateIso": "2026-09-29",
  "priceNote": "No sale price on Zillow for this sale: TX does not make sale prices public. Delivered free, not charged."
}
```

**The summary row** (the recorded Phoenix run: Zillow counted 1,286 sales in the window and served 984, all delivered and charged):

```json
{
  "_type": "summary",
  "location": "Phoenix, AZ",
  "sold_in_last_days": 30,
  "total_available": 1286,
  "pages_fetched": 24,
  "total_scraped": 984,
  "charged_for": 984,
  "rows_without_sale_price": "deliverFree",
  "delivered_free_no_sale_price": 0,
  "duplicates_skipped": 0,
  "filtered_out_stale": 0,
  "stop_reason": "end_of_results",
  "ended_on_deadline": false,
  "charge_failures": 0,
  "already_delivered_in_earlier_run": 0,
  "monitor": false,
  "scraped_at": "2026-09-30T08:02:00.217Z"
}
```

The summary above is trimmed: the real row also carries the cost guard counters (`requests`, `est_spend_usd` and similar).

### Pricing

Pay per event: one `property-scraped` event for each sold home with a sale price delivered to your dataset. There is no start fee, no per page fee and no subscription.

| Event | Free | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Sold home with its sale price (`property-scraped`), per row | $0.002 | $0.00175 | $0.0015 | $0.001 |
| Per 1,000 priced sold homes | $2.00 | $1.75 | $1.50 | $1.00 |

**Start fee:** none. This actor has no `apify-actor-start` or other per run event, so a run that finds nothing costs nothing.

**Charged:** every sold home delivered with a sale price (`priceDisclosed: true`).

**Never charged:** a sale without a public price (Texas and other non-disclosure states), whether delivered free or skipped, a sale that Zillow repeats within the same run, sales dropped as older than your window, rows that do not match `propertyType`, sales skipped by monitor mode, pages that fail, and the summary and info rows.

**What real jobs cost on Gold:** the recorded Phoenix run of 984 priced sales costs $0.98. A 300 sale ZIP code pull in a disclosure state costs $0.30. An Austin, TX pull costs nothing, since none of its sales carries a price.

There is no price change scheduled for this actor. The Pricing tab on this page always shows the rate for your own plan.

### FAQ

**What does this actor read from Zillow?**
Zillow's public search results for recently sold homes in one location, the same cards a visitor sees when filtering Zillow to "Sold". It does not open each home's own page, so price history, tax history, schools and agent names are not included. For those, feed the `zpid` or `detailUrl` into [Zillow Property Details](https://apify.com/themineworks/zillow-property-details?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral).

**Why is there no sale price on my Texas rows, and am I charged for them?**
Texas and some other states do not make sale prices public, and Zillow's search results for those sales carry none: 0 of 148 rows in a recorded 30 day Austin run of the current version, and 0 of 862 in an earlier 90 day one. Those rows are not charged. By default they are delivered free with `priceDisclosed: false`, a `priceNote`, the sale date, the home's details and usually `zestimate`; set `rowsWithoutSalePrice` to `"skip"` to leave them out. A search of only unpriced sales stops after about 11 page requests (up to about 450 free rows), because those pages earn nothing. If you need prices in a non-disclosure state, this actor alone will not give them to you.

**How many sales can I get?**
Up to about 1,000 per search; Zillow stops serving a search past that point. The summary's `total_available` shows Zillow's count. For a big metro or a long window, split by ZIP code or into price bands with `minPrice` and `maxPrice`.

**How far back can I go?**
Up to 730 days with `soldInLast`. Zillow applies the window itself, and the actor drops any row older than the window as a second check. Remember the 1,000 per search limit: a two year window in a big city needs ZIP codes or price bands.

**How fresh is the data?**
Live. Each run reads Zillow at the moment it runs. A sale appears once Zillow has recorded it, and that lag varies by market, so the most recent week can be incomplete.

**Do I need a Zillow account, cookies or an API key?**
No. You only need an Apify account.

**Do I need to set up a proxy?**
No. The actor uses Apify's US residential proxy on its own, and the proxy cost is inside the per row price. A page Zillow blocks is retried up to three times on a fresh proxy session. On a day when Zillow blocks heavily, a large run can end with fewer rows than asked for; the summary then says `page_failed`.

**How do I read `soldDate`?**
It is the sale date in epoch milliseconds, as Zillow sends it, the same as in earlier versions. For a plain date use `soldDateIso` instead, for example `"2026-09-29"`, the date Zillow shows on the listing as "Sold 09/29/26"; spreadsheets read it as a date directly.

**Which `propertyType` values work?**
`SINGLE_FAMILY`, `CONDO`, `TOWNHOUSE`, `MULTI_FAMILY`, `MANUFACTURED`, `LOT` and `APARTMENT`, in any case; `LAND` means `LOT`, and `single family` works too. A value that matches none of these returns nothing, and the run log says so. The summary's `filtered_out_by_property_type` shows how many rows the per-row check removed.

**What if my location is not found?**
The run stops with an error and nothing is charged. Use a specific city and state or a ZIP code; the run log shows which Zillow region your text matched.

**How do I run it on a schedule and get only new sales?**
Save your input as a task, then add a schedule in Apify Console (Schedules, then Create new). Turn on `monitorMode`: the actor keeps the `zpid` of every sale it delivered to you in a storage named `monitor-zillow-recently-sold` in your Apify account, and later runs skip those.

**How do I export the data?**
From the run's Storage tab as JSON, CSV, Excel, XML or HTML, or through the Apify API.

**Can I use it from Claude, ChatGPT or another AI assistant?**
Yes. Add Apify's MCP server at `https://mcp.apify.com/?tools=themineworks/zillow-recently-sold` to any MCP client and ask in plain words, for example "get homes sold in 78704 in the last 90 days with 3 or more bedrooms". The block under "Copy to your AI assistant" gives an assistant everything it needs to call the API directly. The same data is part of our [Real Estate MCP](https://apify.com/themineworks/real-estate-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral).

**Is it legal to scrape Zillow sold data?**
The actor reads only Zillow's public search pages, with no login and nothing behind an account. The rows describe properties, not people, but addresses can still count as personal data in some places. You are responsible for how you use the data, including Zillow's Terms of Use and data protection law such as GDPR and CCPA. This is general information, not legal advice.

### Integrations

- **Google Sheets:** send each run's sales to a sheet with Apify's Google Sheets integration.
- **Make, Zapier and n8n:** start runs and read datasets with the official Apify apps and nodes.
- **Webhooks:** get a call to your own URL when a run succeeds, then fetch its dataset.
- **API and SDKs:** the Apify API and the Python and JavaScript clients, as in the loop above.
- **MCP clients:** Claude, ChatGPT, Cursor and others through `https://mcp.apify.com/?tools=themineworks/zillow-recently-sold`.

For the rental side of the same markets, [Zillow Rentals Scraper](https://apify.com/themineworks/zillow-rental-listings?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral) returns current for-rent listings with the monthly rent on every charged row and rent by bedroom count for apartment communities. It takes the same `location`, `maxItems` and `monitorMode` inputs.

### More from The Mine Works

**Real estate**

- [Zillow Rentals Scraper](https://apify.com/themineworks/zillow-rental-listings?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [India Real Estate MCP](https://apify.com/themineworks/india-real-estate-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Housing.com Scraper](https://apify.com/themineworks/housing-com-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [MagicBricks Scraper](https://apify.com/themineworks/magicbricks-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Zillow Property Scraper](https://apify.com/themineworks/zillow-property-details?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [99acres Scraper](https://apify.com/themineworks/99acres-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Zillow Photos Scraper](https://apify.com/themineworks/zillow-photos?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Real Estate MCP](https://apify.com/themineworks/real-estate-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Airbnb Scraper](https://apify.com/themineworks/airbnb-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Domain.com.au Property Scraper](https://apify.com/themineworks/domain-property-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [realestate.com.au Scraper](https://apify.com/themineworks/realestate-com-au-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Zillow ZIP Code Bulk Search Scraper](https://apify.com/themineworks/zillow-zip-bulk-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Social media and video**

- [Threads Scraper](https://apify.com/themineworks/threads-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Reddit Scraper](https://apify.com/themineworks/reddit-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Threads Search Scraper](https://apify.com/themineworks/threads-search-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Instagram Profile Scraper](https://apify.com/themineworks/instagram-profile-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Leads and business directories**

- [B2B Leads Finder](https://apify.com/themineworks/b2b-leads-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google Maps Email Scraper](https://apify.com/themineworks/maps-leads?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Skip Trace Lookup](https://apify.com/themineworks/skip-trace-lookup?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [JustDial Scraper](https://apify.com/themineworks/justdial-business?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Marketing, SEO and reviews**

- [Facebook Ad Library Scraper](https://apify.com/themineworks/meta-ad-library-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Similarweb Scraper](https://apify.com/themineworks/similarweb-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google News Scraper](https://apify.com/themineworks/google-news?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Google Ads Transparency Scraper](https://apify.com/themineworks/google-ads-transparency?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**LinkedIn**

- [LinkedIn Company Scraper](https://apify.com/themineworks/linkedin-company-details?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Post Scraper](https://apify.com/themineworks/linkedin-post-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Employees Scraper](https://apify.com/themineworks/linkedin-employees?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [LinkedIn Profile Scraper](https://apify.com/themineworks/linkedin-profile-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Science, health and government data**

- [CourtListener Scraper](https://apify.com/themineworks/courtlistener-court-records?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [data.gov.in Scraper](https://apify.com/themineworks/india-data-gov-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Socrata Open Data Scraper](https://apify.com/themineworks/socrata-open-data?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [OpenAlex Scraper](https://apify.com/themineworks/openalex-scholarly-works?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Jobs and hiring**

- [Foundit Monster India Jobs](https://apify.com/themineworks/foundit-jobs-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Hirist Jobs Scraper](https://apify.com/themineworks/hirist-jobs-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [India Jobs MCP](https://apify.com/themineworks/india-jobs-mcp?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Shine.com Jobs Scraper](https://apify.com/themineworks/shine-jobs-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Company and business data**

- [Company Domain Finder](https://apify.com/themineworks/company-domain-finder?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GST Taxpayer Lookup](https://apify.com/themineworks/gst-taxpayer-lookup?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [World Bank Trade Scraper](https://apify.com/themineworks/global-trade-data?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Y Combinator Scraper](https://apify.com/themineworks/y-combinator-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**E-commerce and marketplaces**

- [Ozon.ru Scraper](https://apify.com/themineworks/ozon-product-search?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Amazon Product Scraper](https://apify.com/themineworks/amazon-products?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [⭐ Amazon Reviews Scraper](https://apify.com/themineworks/amazon-reviews?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Carsales.com.au Scraper](https://apify.com/themineworks/carsales-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Food and local services**

- [NoBroker Scraper](https://apify.com/themineworks/nobroker-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Swiggy Restaurant Scraper](https://apify.com/themineworks/swiggy-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [Zomato Scraper](https://apify.com/themineworks/zomato-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**Developer and AI tools**

- [Website to Markdown Crawler](https://apify.com/themineworks/rag-crawler?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GitHub Skill Finder](https://apify.com/themineworks/github-skill-discovery?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GitHub Repo Scraper](https://apify.com/themineworks/github-repo-intelligence?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)
- [GitHub Trending Scraper](https://apify.com/themineworks/github-trending-scraper?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

**More tools**

- [Tennis Match & Player Data Scraper](https://apify.com/themineworks/tennis-match-data?fpr=ymnoit\&utm_source=apify-readme\&utm_medium=referral)

### Support

Found a bug or need a field? Open an issue on the Issues tab of this actor. To ask for a new source, email dmineworks@gmail.com.

*Zillow Sold Comps Scraper returns the homes sold in a US city or ZIP code over the last 1 to 730 days, with sale dates, sale prices where the state publishes them, and home details, from $1 per 1,000 priced sales; sales without a public price are free.*

# Actor input Schema

## `location` (type: `string`):

City, zip code, or neighborhood (e.g. 'Phoenix, AZ', '85016', 'Palo Alto, CA'). Texas, Utah and other non-disclosure states have no public sale prices: see 'Sales with no public sale price' below.

## `maxItems` (type: `integer`):

Maximum number of recently sold properties to return. Zillow serves roughly the first 1,000 results of any one search, so a larger value stops there.

## `soldInLast` (type: `integer`):

Only return homes sold within the last N days. Common values: 30, 90, 180, 365.

## `minPrice` (type: `integer`):

Minimum sale price in USD, to exclude cheaper closings from the results, e.g. 300000.

## `maxPrice` (type: `integer`):

Maximum sale price in USD, to exclude pricier closings from the results, e.g. 800000.

## `minBeds` (type: `integer`):

Minimum number of bedrooms a sold property must have to be included, e.g. 3.

## `minBaths` (type: `integer`):

Minimum number of bathrooms a sold property must have to be included, e.g. 2.

## `propertyType` (type: `string`):

Filter by property type: SINGLE_FAMILY, CONDO, TOWNHOUSE, MULTI_FAMILY, MANUFACTURED or LOT (LAND also works and means LOT). Not case sensitive. Leave blank for all types.

## `rowsWithoutSalePrice` (type: `string`):

Texas, Utah and other non-disclosure states keep sale prices private, so Zillow shows none. These sales are never charged. 'Deliver free' keeps them in the results, labelled priceDisclosed false, with sold date, address and home facts. 'Skip' leaves them out so you get only sales with a price.

## `monitorMode` (type: `boolean`):

Run this on a schedule and get ONLY sales not delivered in a previous run, so a daily comps watch bills you for new closings instead of the whole history every morning. You are never charged twice for the same property. Keep the location and filters the same across runs.

## Actor input object example

```json
{
  "location": "Phoenix, AZ",
  "maxItems": 100,
  "soldInLast": 90,
  "propertyType": "SINGLE_FAMILY",
  "rowsWithoutSalePrice": "deliverFree",
  "monitorMode": false
}
```

# Actor output Schema

## `results` (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 = {
    "location": "Phoenix, AZ",
    "maxItems": 100,
    "soldInLast": 90,
    "propertyType": "SINGLE_FAMILY"
};

// Run the Actor and wait for it to finish
const run = await client.actor("themineworks/zillow-recently-sold").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 = {
    "location": "Phoenix, AZ",
    "maxItems": 100,
    "soldInLast": 90,
    "propertyType": "SINGLE_FAMILY",
}

# Run the Actor and wait for it to finish
run = client.actor("themineworks/zillow-recently-sold").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 '{
  "location": "Phoenix, AZ",
  "maxItems": 100,
  "soldInLast": 90,
  "propertyType": "SINGLE_FAMILY"
}' |
apify call themineworks/zillow-recently-sold --silent --output-dataset

```

## MCP server setup

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

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/fiWuQcfObGWn1dm4J/builds/9Q70DM2rk50twBz1o/openapi.json
