Zillow Property Listings Scraper avatar

Zillow Property Listings Scraper

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Zillow Property Listings Scraper

Zillow Property Listings Scraper

Scrape Zillow search results by city, region or ZIP: about 41 listings per location with zpid, numeric price plus the formatted priceText, beds, baths, areaSqft, address split into street, city, state and zipcode, status, brokerName, photo and exact coordinates. For sale, for rent or sold. No login.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

String

String

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Share

Sweep Zillow across a list of US markets and get the listings back as numbers you can sort โ€” price, beds, baths, square feet and coordinates, not display strings.

What can Zillow Property Listings Scraper do?

Give it locations and it returns the listings on Zillow's search results for each one, one row per listing.

๐Ÿ˜๏ธ For sale, for rent, or sold from the same input, switched with one field.

๐Ÿ”ข Numbers, not strings. price: 500000 alongside Zillow's priceText: "$500,000", and beds, baths and areaSqft as numbers โ€” read from the page's own state blob rather than parsed off the cards.

๐Ÿ“ Coordinates on every row. latitude and longitude, ready to map with no geocoding step.

๐Ÿข The broker on the row. brokerName where the card names one โ€” enough to rank brokers by active inventory in a market.

๐Ÿ”‘ A stable zpid. Zillow's own listing key: de-duplicate on it, diff price between runs, and feed it to the Zillow Property Detail Scraper for one home's full record.

๐Ÿ“ฅ Up to 100 locations per run. Austin, TX, 78704 and a neighbourhood name all work, with about 41 listings back from each.

๐Ÿšซ No login. No Zillow account, cookie or API key anywhere in the run.

Why scrape Zillow?

  • Comps and pricing. Pull sold rows for a ZIP, keep price, beds, baths and areaSqft, and you have a price-per-square-foot distribution for the submarket in one run.
  • Rental yield. Run the same location twice, once as for_sale and once as for_rent, and compare asking rents against asking prices on comparable bed counts.
  • Agent and iBuyer lead lists. brokerName plus the address fields is enough to rank brokers by active inventory in a market.
  • Maps and dashboards. Coordinates are on the row already, so inventory goes onto a map without a geocoding bill.
  • Days-on-market and price-cut tracking. Schedule the Actor on a market, key rows by zpid, and diff price between runs.

How to use it

  1. Open the Actor and click Try for free, or add it to your Apify account.
  2. Put your markets in the Locations field, one per line. Austin, TX and 78704 both work.
  3. Pick a Listing type. Leave it at for_sale, or switch to for_rent or sold.
  4. Set Maximum results if you want a hard ceiling on the dataset, and raise Concurrency if you are running many locations and want them fetched in parallel.
  1. Click Start. Each location is one fetch, so a ten-location run finishes in seconds.
  2. Take the rows from the Dataset tab, or export them as JSON, CSV or Excel. The run's SUMMARY record in the key-value store lists any location that failed, with its error.

To keep a market file current, save the input as a task and schedule it. Rows carry collectedAt, so successive runs stack into a time series without any extra bookkeeping.

Output

One row per listing. The shape below is illustrative โ€” it shows the fields and their types, not a captured run.

{
"zpid": "29502073",
"address": "6310 Needham Ln, Austin, TX 78739",
"street": "6310 Needham Ln",
"city": "Austin",
"state": "TX",
"zipcode": "78739",
"price": 1200000,
"priceText": "$1,200,000",
"beds": 5,
"baths": 4,
"areaSqft": 3496,
"status": "FOR_SALE",
"latitude": 30.192585,
"longitude": -97.89119,
"brokerName": "Compass RE Texas, LLC",
"detailUrl": "https://www.zillow.com/homedetails/6310-Needham-Ln-Austin-TX-78739/29502073_zpid/",
"imageUrl": "https://photos.zillowstatic.com/fp/a1b2c3d4e5f60718293a4b5c6d7e8f90-p_e.jpg",
"searchLocation": "Austin, TX",
"listingType": "for_sale",
"sourceUrl": "https://www.zillow.com/homes/for_sale/Austin,-TX_rb/",
"collectedAt": "2026-08-21T09:14:03.512Z"
}

Reliability

Measured across 30 US cities in one run: 30 of 30 locations succeeded and 1,230 listings came back, with every field in the schema populated by at least some rows. No column is always empty.

Reading the page's own state blob is what makes that possible. The rendered Zillow search page is around 650KB, well past what a model-backed extractor will accept, and the numbers it shows are formatted for display. The blob carries the same results with prices and areas already as integers.

A location that cannot be read is recorded in the run's SUMMARY under failures rather than quietly returning fewer rows, and a run in which every location failed exits with an error instead of reporting success on an empty dataset.

There are no retries by design. The String Unblocker behind this Actor owns proxy rotation, session reuse and anti-bot solver selection, so a retry loop out here would re-roll the same block and spend your budget doing it.

Limitations

One search page per location, so this samples a market rather than crawling it end to end. Widen coverage by listing more ZIP codes rather than expecting deeper paging from a single city. Detail pages are not opened, so tax history, price history, Zestimate detail, schools and photo galleries are out of scope. Only zillow.com is targeted, which means US listings only.

How much does it cost?

A run that returns 1,000 rows costs $1.50 on a paid plan, or $1.75 with no subscription. You are charged per result row written to the dataset, so a run that returns nothing costs nothing, and maxItems is the budget dial.

PlanPer 1,000 rows
Free$1.75
Bronze$1.50
Silver$1.25
Gold$1.00
Platinum$0.75
Diamond$0.25

Apify bills its own platform usage for the run on top of this.

A location that fails produces no rows and costs you nothing, and the run never writes a row it could not charge for.

Runs started from an Apify free plan stop at 250 requests and 250 results, and the run says so in its status message. Any paid plan runs the full input and whatever maxItems you set. The cap exists because this Actor fetches through String's own infrastructure, which Apify does not reimburse on free-plan runs; it binds on requests as well as rows so that a long input list cannot spend those fetches on rows the run will not return.

Using it with the Apify API

import { ApifyClient } from "apify-client";
const client = new ApifyClient({ token: "<YOUR_APIFY_TOKEN>" });
const run = await client.actor("usestring/zillow-listings").call({
locations: ["Austin, TX", "Denver, CO"],
listingType: "for_sale",
maxItems: 1000
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, items[0]);
const summary = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord("SUMMARY");
console.log(summary?.value);

The Python client and the plain REST endpoints take the same input object; Apify's API documentation has the equivalents.

FAQ

Do I need a Zillow account, API key or cookies? No. The Actor reads the public search page as a logged-out visitor and never signs in.

How many listings do I get per location? Around 41, which is one Zillow search page. Ten locations therefore return roughly 410 rows for ten requests. There is no deeper paging, so more coverage means more locations, not a bigger page.

Can I get rentals and sold homes? Yes. Set listingType to for_rent or sold. The default is for_sale.

Is price a number or a string? A number. priceText carries Zillow's formatted version next to it, and beds, baths, area and coordinates are numbers too.

How do I de-duplicate across runs? Key on zpid. It is Zillow's own identifier, it is stable, and it is also what the Zillow Property Detail Scraper accepts as input.

Does it work outside the US? No. It targets zillow.com, so US listings only. There is no country or language input.

What happens if one location fails? The rest of the batch still returns. The failed location and its error are written to the run's SUMMARY record, and only a run where every location failed exits with an error.

How fresh is the data? Every row is stamped with collectedAt and reflects what Zillow was showing at that moment. Schedule the run to build a series.

Feedback

Found a field parsed wrong, a market that fails, or something missing from the schema? Open an issue from the Issues tab on this Actor's Store page. A report that includes the input which reproduces the problem gets fixed fastest.