---
title: "Scrape Zillow Data: Prices and Zestimates | Scrape.ly"
description: "Scrape Zillow data without code or with Python: price, beds, baths, living area and Zestimate per listing. Includes a real run, costs and limits."
url: https://scrape.ly/blog/scrape-zillow-data
markdown: https://scrape.ly/blog/scrape-zillow-data.md
---

[Tutorials](https://scrape.ly/blog/category/tutorials.md)

# How to Scrape Zillow Data: Prices, Zestimates and Home Facts by City or URL

Give a ready-made Actor a city, a Zillow search or home URL, or a street address, and get one row per listing with price, beds, baths, living area and Zestimate. This guide covers the no-code steps, the API, a real run and its cost.

[Roam & Roof Actor publisher on the Scrape.ly Store](https://scrape.ly/blog/author/roamandroof.md)

- Published

  Oct 22, 2026

- Reading time

  8 min read

![Pixel-art robot with an orange >\_ on its terminal head pulls a listing card out of a grey house next to a yard sign with the blue Zillow logo and drops it into a crate](https://scrape.ly/media/scrape-zillow-data.png?w=1080)

To scrape Zillow data, give a ready-made Actor a city, a Zillow search URL, a home URL or a street address, and export one row per listing: price, beds, baths, living area, year built, Zestimate, photos and MLS details. On Scrape.ly that takes a few clicks, or one API call.

This guide shows which fields you get, the no-code steps, and the same job in curl, Python, JavaScript and through an AI agent. Then it walks through a real run from 22 October 2026, five homes for sale in Greenville, South Carolina, with the log and the exact cost.

## What data you can get from Zillow

The [Zillow Detail Scraper](https://scrape.ly/store/roamandroof/zillow-detail-scraper.md) returns one row per listing. Fields that Zillow doesn't show for a home come back as `null`.

| Field                                                     | What it holds                                                                            |
| --------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `zpid`, `propertyUrl`                                     | Zillow's property ID and the listing URL                                                 |
| `address`, `listingAddress`                               | The full address and its parts (street, city, state, ZIP)                                |
| `coordinates`                                             | Latitude and longitude                                                                   |
| `price`, `listingPrice`                                   | List price as a number, and as an object with currency and formatted text                |
| `bedrooms`, `bathrooms`, `bathroomsDetail`                | Bed and bath counts, with full and half baths                                            |
| `livingArea`, `lotArea`, `pricePerSquareFoot`             | Living area in square feet, lot size and price per square foot                           |
| `yearBuilt`, `homeType`                                   | Year built and type, such as `SINGLE_FAMILY`                                             |
| `listingStatus`, `listingType`                            | Status (`forSale`) and flags such as pending, new home, foreclosure or for sale by owner |
| `zestimate`, `rentZestimate`                              | Zillow's estimated value and rent, when shown                                            |
| `monthlyHoaFee`, `propertyTaxRate`                        | Running costs, when shown                                                                |
| `description`, `photoCount`, `mainImage`, `listingPhotos` | Listing text and photos                                                                  |
| `mls`, `agent`, `broker`, `attributionInfo`               | MLS name and ID; listing agent and broker when the page shows them                       |
| `resoFacts`, `parking`                                    | Structured facts such as garage spaces and parking features                              |
| `isValid`, `scrapedAt`                                    | Row status and timestamp                                                                 |

What you won't get: price history, tax history, nearby schools and nearby homes come back empty, and parcel IDs, tax amounts and school districts aren't included. Listings behind a Zillow login aren't available either.

## How to scrape Zillow without code

1. Open the [Zillow Detail Scraper](https://scrape.ly/store/roamandroof/zillow-detail-scraper.md) in the Scrape.ly Store.
2. Pick the [Homes for sale in Greenville, SC, 5 results](https://scrape.ly/store/roamandroof/zillow-detail-scraper/presets/search.md) preset. It fills in this input:

```json
{
  "startUrls": [],
  "searchQueries": [
    "Greenville, SC"
  ],
  "maxItems": 5,
  "propertyStatus": "FOR_SALE",
  "addresses": [],
  "extractBuildingUnits": "disabled"
}
```

3. Click **Start**. Our run finished in under 6 seconds.
4. Open the dataset and export it as JSON, CSV or Excel.

The input fields that matter most:

- `searchQueries`: cities or neighborhoods, typed the way you'd type them into Zillow's search box.
- `startUrls`: Zillow home URLs (`/homedetails/`), search URLs or building pages. A home URL returns one listing; a search URL returns homes up to the maximum.
- `addresses`: US street addresses, if you already know which homes you want.
- `maxItems`: the most listings to return. Default 10; 0 means no limit.
- `propertyStatus`: `FOR_SALE`, `RECENTLY_SOLD` or `FOR_RENT`, applied to location searches. A home URL is read as Zillow published it.
- `searchResultsDatasetId`: a dataset whose rows contain `propertyUrl`, `detailUrl` or `address`, so you can feed in URLs from an earlier run.

Scrape.ly Store Zillow Detail Scraper Turn a city, a Zillow search or home URL, or a street address into clean listing rows: price, beds, baths, living area, Zestimate and photos.

[Try it free](https://scrape.ly/store/roamandroof/zillow-detail-scraper.md) [Browse the Store](https://scrape.ly/store.md)

## How to scrape Zillow with the API

Create a token under **Settings → API & Integrations** in the dashboard and store it as `SCRAPELY_TOKEN`. This preset runs in a few seconds, so the synchronous endpoint can start it and return the listings in one call:

```shell
curl -X POST "https://api.scrape.ly/v2/actors/roamandroof~zillow-detail-scraper/run-sync-get-dataset-items"
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
  -H "Content-Type: application/json"
  -d '{"startUrls": [], "searchQueries": ["Greenville, SC"], "maxItems": 5, "propertyStatus": "FOR_SALE", "addresses": [], "extractBuildingUnits": "disabled"}'
```

The call waits up to 45 seconds and returns a JSON array. Add `?format=csv` for CSV. A job with many searches or URLs can take longer. Then the call answers `408` while the run keeps going, and calling again would start a second run. For those, start the run with `POST /v2/actors/roamandroof~zillow-detail-scraper/runs`, poll `/v2/actor-runs/RUN_ID?waitForFinish=60` until the status is `SUCCEEDED`, and read `/v2/actor-runs/RUN_ID/dataset/items`. The [API docs](https://scrape.ly/docs/api-actors.md) show the full flow.

In Python, install the client with `pip install scrapely-client-python`. `call()` waits for the run however long it takes:

```python
import os
from scrapely_client import ScrapelyClient

client = ScrapelyClient(os.environ["SCRAPELY_TOKEN"], api_url="https://api.scrape.ly")

run = client.actor("roamandroof/zillow-detail-scraper").call(
    run_input={
        "searchQueries": ["Greenville, SC"],
        "maxItems": 5,
        "propertyStatus": "FOR_SALE",
    }
)
print(run.status)  # SUCCEEDED, FAILED, ABORTED or TIMED-OUT
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item["price"], item["bedrooms"], item["bathrooms"], item.get("zestimate"))
```

In JavaScript or Node.js, install it with `npm install scrapely-client`:

```javascript
import { ScrapelyClient } from 'scrapely-client';

const client = new ScrapelyClient({ token: process.env.SCRAPELY_TOKEN, baseUrl: 'https://api.scrape.ly' });

const run = await client.actor('roamandroof/zillow-detail-scraper').call({
  searchQueries: ['Greenville, SC'],
  maxItems: 5,
  propertyStatus: 'FOR_SALE',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, items[0]);
```

The [Python client](https://scrape.ly/docs/client-python.md), [JavaScript client](https://scrape.ly/docs/client-js.md) and [dataset API](https://scrape.ly/docs/api-datasets.md) docs cover paging through large datasets.

### With an AI agent (MCP)

Scrape.ly runs a hosted MCP server at `https://api.scrape.ly/mcp`. In Cursor, add it to `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "scrapely": {
      "url": "https://api.scrape.ly/mcp",
      "headers": { "Authorization": "Bearer YOUR_TOKEN" }
    }
  }
}
```

In Claude Code, run `claude mcp add --transport http scrapely https://api.scrape.ly/mcp`, then `/mcp` to sign in with OAuth. The agent uses `search-actors`, `fetch-actor-details`, `call-actor` and `get-actor-output`. Try a prompt like: "Use scrapely to run roamandroof/zillow-detail-scraper for homes for sale in Greenville, SC, 5 results, and give me a table of price, beds, baths, living area and Zestimate." The [MCP docs](https://scrape.ly/docs/mcp.md) list the other clients.

## A real run: Homes for sale in Greenville, SC

We ran the preset on 22 October 2026. It saved 5 listings, the run took 5.7 seconds, and it was charged $0.0062 in total. We removed the street addresses of these private homes and any agent names from the sample below.

| address                                  | price     | bedrooms | bathrooms | livingArea | zestimate |
| ---------------------------------------- | --------- | -------- | --------- | ---------- | --------- |
| \[street withheld], Greenville, SC 29605 | 369,000   | 3        | 2         | 1,542      | —         |
| \[street withheld], Greenville, SC 29617 | 170,000   | 2        | 1         | 1,123      | 158,700   |
| \[street withheld], Greenville, SC 29607 | 1,087,750 | 5        | 5         | 4,351      | 1,034,500 |
| \[street withheld], Greenville, SC 29605 | 1,700,000 | 3        | 5         | 4,607      | 1,779,400 |
| \[street withheld], Greenville, SC 29605 | 375,000   | 3        | 2         | 1,325      | 366,000   |

```plaintext
20261022T15:23:09.198Z [Scrapely] Container started (setup 0.8 s)
20261022T15:23:10.291Z [scrapely.actor] INFO  [Scrapely] Initializing API storage for run aec640d809a248a09
20261022T15:23:10.420Z [scrapely.proxy_configuration] INFO  Platform proxy access check succeeded.
20261022T15:23:10.420Z [scrapely.actor] INFO  Fetching with proxy pool DATACENTER
20261022T15:23:13.685Z [scrapely.actor] INFO  Saved 5 listings. Requests 6. Transferred 4829117 bytes.
20261022T15:23:13.685Z [scrapely.actor] INFO  [Status message]: Saved 5 listings from 1 inputs. Reached the maxItems limit of 5.
20261022T15:23:14.092Z [Scrapely] Container state: status=exited exitCode=0 oomKilled=false
```

All five were single-family homes for sale, priced from $170,000 to $1,700,000. Four had a Zestimate: three sat below the list price and one above it ($1,779,400 against $1,700,000). The first listing had none. Its full record shows a 2021 build on 0.48 acres at $239 per square foot, 48 photos and the Greater Greenville AOR as its MLS. As the limits below say, `listingPriceHistory` and `nearbySchools` came back empty, and `daysOnZillow` was `null`. The run made 6 requests and moved 4,829,117 bytes (about 4.8 MB) for five listings.

## What it costs

The Actor has one charge event: `result-item`, at **$0.001** for each listing saved. URLs or addresses that can't be read aren't charged.

**This run:** 5 listings × $0.001 = $0.005 in event fees. The run was charged $0.0062 in total, because platform usage added $0.000754 of compute, $0.000399 of datacenter proxy traffic and $0.000005 of dataset writes.

**At 1,000 listings:** 1,000 × $0.001 = $1.00 in event fees, plus platform usage for compute and proxy traffic.

## Limits and common problems

- **One results page per search.** A location search returns the first results page Zillow shows for it (about 40 homes). For bigger jobs, add more searches (for example, by neighborhood) or paste home URLs.
- **Missing blocks.** Price history, tax history, nearby schools and nearby homes are loaded by a separate request this Actor doesn't make, so they come back empty. If you need them, this is the wrong tool.
- **Empty fields.** Zillow doesn't show every field on every listing, so values such as agent contact details, days on Zillow or the Zestimate can be `null`, as in the first row above.
- **Bad input.** A wrong URL or an address Zillow can't find saves no row and isn't charged. The run still succeeds and lists it under `failedInputs` in the `OUTPUT` record.
- **Sync timeouts.** This run took 5.7 seconds, but the synchronous endpoint stops waiting at 45 seconds. Use the asynchronous flow for large jobs.

## Is it legal to scrape Zillow?

The Actor reads publicly visible listing pages and never logs in. Zillow's [Terms of Use](https://www.zillow.com/z/corp/terms/) (updated October 28, 2025) are clear, though. They forbid "automated queries (including screen and database scraping, spiders, robots, crawlers, bypassing 'captcha' or similar precautions...)". They allow copying information only "without the aid of any automated processes" and only as needed for personal or "Pro" use. Listings also carry more personal data than product pages: a street address points to someone's home, and agent names and phone numbers identify people. Once you collect personal data, privacy laws such as the GDPR and the CCPA apply, which is why we masked our sample. This is not legal advice. Before you use Zillow data commercially, get advice from a lawyer for your case.

## Alternatives

- **Zillow's Bridge APIs.** Zillow Group's [MLS Listings API](https://www.zillowgroup.com/developers/api/mls-broker-data/mls-listings/) (Bridge Listing Output) serves MLS listing data over REST, normalized to the RESO data dictionary. Access is invite-only and at the discretion of each MLS. The [Public Records API](https://www.zillowgroup.com/developers/api/public-data/public-records-api/) covers parcel, assessment and transaction data, roughly 15 years of it, and is also invite-only. If you're a broker or a business with a data agreement, these are the better route.
- **Zestimates API and Zillow Research data.** The [Zestimates API](https://www.zillowgroup.com/developers/api/zestimate/zestimates-api/) returns current property, rental and foreclosure Zestimates for about 100 million US properties, aimed at commercial use. For research, Zillow points to its [Research data](https://www.zillow.com/research/data/), which has looser terms. If you need market trends rather than single listings, start there.
- **Your own Python scraper.** [Scrapfly's guide](https://scrapfly.io/blog/posts/how-to-scrape-zillow) reads the JSON Zillow embeds in each page (`__NEXT_DATA__`). [Scrapingdog's guide](https://www.scrapingdog.com/blog/scrape-zillow/) uses generated CSS class names, and its text and code already cite two different versions of the same class. Expect to maintain selectors and handle blocks yourself.
- **A headless browser.** Playwright or Selenium gives full control over the page. It's the better choice when you need data a ready-made tool doesn't collect, at the cost of running browsers and proxies yourself.

## FAQ

### Does Zillow have an API?

Yes. Zillow Group lists close to 20 APIs, but the listing data needs approval: the MLS Listings and Public Records APIs are invite-only, and the Zestimates API is aimed at businesses. Researchers can download aggregate market data from Zillow Research instead.

### Can you scrape Zestimates from Zillow?

Yes. Each row carries `zestimate` and `rentZestimate` when Zillow shows them. In our run, four of the five listings had a Zestimate and one had none.

### Can you scrape sold or rental listings?

Yes. Set `propertyStatus` to `RECENTLY_SOLD` or `FOR_RENT` for a location search. The [Recently sold in Greenville, SC](https://scrape.ly/store/roamandroof/zillow-detail-scraper/presets/search-filters.md) preset shows the sold case. A home URL you paste is read as Zillow published it, whatever status you pick.

### Can you scrape Zillow by address?

Yes. Put US street addresses in `addresses`, one per entry, and the Actor finds each home and returns its details. An address Zillow can't find saves no row and isn't charged.

### How many listings can one Zillow search return?

One search returns the first results page Zillow shows, about 40 homes. For more, split the area into several searches or collect home URLs and pass them in `startUrls` or through `searchResultsDatasetId`.

Scrape.ly Store Zillow Detail Scraper Get Zillow listing details from a city, a search or home URL, or a street address: price, beds, baths, Zestimate, photos and MLS info. $0.001 per listing.

[Try it free](https://scrape.ly/store/roamandroof/zillow-detail-scraper.md) [Browse the Store](https://scrape.ly/store.md)

About the author

[Roam & Roof](https://scrape.ly/blog/author/roamandroof.md) Actor publisher on the Scrape.ly Store

Homes, stays, trips and cars: listings from 40+ property portals, the big travel and booking sites and the main car marketplaces. For agents, investors, travel analysts and dealers. A Scrapely studio.

- [Website](https://scrape.ly/users/roamandroof.md)

Keep reading

## More in Tutorials

- [![Pixel-art robot with an orange >\_ on its terminal head pulls a blue product box off a store shelf topped with the yellow Walmart spark logo and loads it into a crate](https://scrape.ly/media/walmart-scraping.png?w=750)](https://scrape.ly/blog/walmart-scraping.md)
  ### [Walmart Scraping: Get Prices, Ratings and Sellers by Keyword or URL](https://scrape.ly/blog/walmart-scraping.md)
  [Type a keyword or paste a Walmart URL into a ready-made Actor and get one row per product with price, was-price, rating, seller and stock. This guide covers the no-code steps, the API, a real run and its exact cost.](https://scrape.ly/blog/walmart-scraping.md)
- [![Pixel-art robot with a terminal for a head pulling a place card out of a Google Maps pin standing on a folded map, with a crate of collected place cards beside it](https://scrape.ly/media/how-to-scrape-google-maps.png?w=750)](https://scrape.ly/blog/how-to-scrape-google-maps.md)
  ### [How to Scrape Google Maps: Places, Ratings, Phones and Websites](https://scrape.ly/blog/how-to-scrape-google-maps.md)
  [Scrape Google Maps places for any search term and city, with no code or with one API call. A real run, its output, its log and its exact cost, plus the limits and the legal side.](https://scrape.ly/blog/how-to-scrape-google-maps.md)
- [![Pixel-art robot with an orange >\_ on its terminal head pulls a parcel from a stack of cardboard boxes marked with the Amazon smile logo and loads it into a crate](https://scrape.ly/media/how-to-scrape-amazon.png?w=750)](https://scrape.ly/blog/how-to-scrape-amazon.md)
  ### [How to Scrape Amazon: Prices, ASINs and Ratings From Search or Product URLs](https://scrape.ly/blog/how-to-scrape-amazon.md)
  [Paste an Amazon search or product URL into a ready-made Actor and get one row per product with price, ASIN, rating and review count. This guide covers the no-code steps, the API, ZIP code pricing, a real run and its cost.](https://scrape.ly/blog/how-to-scrape-amazon.md)

## The internet is full of data. Start owning yours.

Scrape.ly gives you the infrastructure, the tooling, and the team to extract, process, and operationalize web data at any scale. Setup takes minutes. The advantage lasts forever.

[Get Started Free](https://my.scrape.ly/register) [Chat with Support](mailto:support@scrape.ly?subject=Question%20about%20Scrape.ly\&body=Hi%2C%20I%20have%20a%20question%20about%20Scrape.ly.)

No credit card. No setup calls.
