Zillow Search Scraper — Listings & Agent Contacts avatar

Zillow Search Scraper — Listings & Agent Contacts

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Zillow Search Scraper — Listings & Agent Contacts

Zillow Search Scraper — Listings & Agent Contacts

Every home for sale or recently sold in one US city, state or ZIP code, exported as rows with the price, beds, baths, size, full address and map coordinates. Enrichment adds what the listing card never shows: the listing agent's name, email address and phone number, and the Zestimate.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

The Netaji

The Netaji

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Zillow Search Scraper

Every home for sale or recently sold in one US city, state or ZIP code, exported as a spreadsheet of listings. Each row carries the asking or sale price, the bedroom and bathroom count, the interior area, the full address, the map coordinates, the listing status and the brokerage behind it. Enrichment adds the part a Zillow page never shows: the listing agent's name, email address and telephone number.

A region is paged automatically. How far one region reaches, and what to do when a market runs past it, is answered under Questions.

Accepted input

region is required and is the region slug from a Zillow URL: the san-francisco-ca in https://www.zillow.com/san-francisco-ca/. A bare state such as ca and a ZIP code such as 94103 are regions to Zillow as well, so the field is validated as a slug shape rather than as a city-state pair. A pasted Zillow search URL is accepted in either spelling the site uses and is reduced to the slug; the sold and 2_p path segments such a URL carries are dropped rather than folded in, because status and startPage are separate fields here.

status selects for_sale, the default, or sold. startPage sets the page the walk begins from and defaults to 1; it is capped at 20, which is the deepest page Zillow will serve for any region. maxItems bounds the rows saved and defaults to 100; a value of 0 removes the bound and lets the walk continue to the last page the region has.

{
"region": "san-francisco-ca",
"status": "for_sale",
"maxItems": 100
}

Response fields

{
"zpid": "2146999031",
"url": "https://www.zillow.com/homedetails/2146999031_zpid/",
"price": 480000,
"price_display": "$480,000",
"bedrooms": 3,
"bathrooms": 2,
"living_area": 1600,
"address": "2114 S Trumbull Ave, Chicago, IL 60623",
"street_address": "2114 S Trumbull Ave",
"city": "Chicago",
"state": "IL",
"zipcode": "60623",
"latitude": 41.84,
"longitude": -87.71,
"status_text": "House for sale",
"status_type": "FOR_SALE",
"marketing_status": "For Sale",
"raw_home_status": "ForSale",
"broker_name": "RE/MAX Partners",
"is_featured_listing": false
}

Fields absent from a listing are returned as null rather than omitted, so every row has the same shape.

zpid is Zillow's own identifier for the home and is the stable key for a property. It is also the exact value Zillow Property Scraper accepts, which is what makes the two Actors compose: a region is walked here, and each home is then read in full there without a URL ever being constructed. That matters more on this site than it sounds. The address half of a Zillow property link is decorative; /homedetails/2146999031_zpid/ and /homedetails/any-slug-at-all/2146999031_zpid/ both resolve to the same home, so a link built from an address is not validated by anything and can quietly address a different property.

price is the number and price_display is the string Zillow rendered, including the /mo and + decorations it sometimes attaches; price is the field to compute with.

status_text, status_type, marketing_status and raw_home_status state the same status at decreasing levels of processing: the rendered label, its machine form, Zillow's simplified marketing code, and the unmapped value from the feed. is_featured_listing reports whether a row is a paid placement, which is worth reading before result order is treated as a ranking.

broker_name is the only attribution a listing row carries. The listing agent's name, email address and telephone number are on the home's own record, and are covered below.

Open houses arrive as has_open_house and open_house_description, the window written the way Zillow writes it, such as "Sat 1-3pm".

Enriching with property details

enrichPropertyDetails reads each listing's own property record and merges it onto the row. It is off by default, costs one further request per home, and is billed per home enriched, only after the record has been read.

Two groups of fields are the reason to turn it on, and neither is rendered anywhere on a Zillow page.

The first is who is selling the home: agent_name, agent_email, agent_phone, broker_phone, mls_id, mls_name, listing_agreement and true_status. agent_email is null more often than not; a telephone number is stated far more consistently than an email address across the listings I have measured.

The second is how much attention the listing is getting: page_view_count, favorite_count and tour_view_count. A save is a logged-in action by somebody who intends to return, so its ratio to the view count behaves as a conversion rate for the individual home. All three are worth reading against days_on_zillow, because 197 views over 23 days describes a different listing from 197 views in one.

The rest of the record follows as well: zestimate, rent_zestimate, last_sold_price, date_sold, price_change, price_change_date_display, tax_annual_amount, property_tax_rate, monthly_hoa_fee, year_built, lot_size, lot_area_value, lot_area_units, home_type, property_type, listing_type, contingent_listing_type, country, county, neighborhood, community, subdivision, time_zone, description, date_posted, home_status, currency, is_showcase_listing, has_virtual_tour, photos, photo_count and reso_facts.

{
"region": "https://www.zillow.com/san-francisco-ca/",
"status": "sold",
"maxItems": 50,
"enrichPropertyDetails": true
}

Where the record and the listing state the same field, the record wins; it is the home's own document rather than the card Zillow drew for a results page. A null on the record never overwrites a value the listing already carried, so a sparse record cannot blank a column partway down a dataset. The listing-only fields, address, status_text, image_url, the open-house pair and is_featured_listing, are left untouched.

A home whose record cannot be read keeps its listing row unchanged and is not billed for the enrichment.

Questions

How many homes does one region return? At most 820, and usually fewer. Zillow serves 41 homes per page and will hand over 20 pages of any region, so 20 x 41 = 820 is the ceiling, and the last page it serves is normally short. That ceiling belongs to Zillow rather than to this Actor, and no setting here moves it.

Zillow says thousands of homes match the region, so why did the run stop at 820? Because the two numbers Zillow publishes answer different questions: how many homes match, and how many pages it is willing to serve. On sold listings they diverge by more than twentyfold. Measured on San Francisco, for_sale reports 773 matching homes across 19 pages, so every one of them is reachable; sold reports 18,802 matching homes across 20 pages, of which 820 are reachable. Dividing the match count by the page size asks for page 459 of something that stops at 20. The run log prints both numbers on the first page and says plainly when a region is capped. When it is, the result is a sample of the matching set rather than an enumeration of it, and rerunning does not change that.

How is a market larger than 820 homes covered in full? Two routes. A region can be subdivided, because a ZIP code is a region here: 94103 and 94110 are two separate 20-page allowances rather than one, and a city split into its ZIP codes multiplies the ceiling by the number of them. Otherwise Zillow Sitemap Scraper reads Zillow's own published index instead of its rendered search pages and has no per-region cap at all; its property identifiers feed Zillow Property Scraper unchanged. That Actor exists because of this ceiling, not as a variation on this one.

Why did the run return fewer rows than maxItems? Because the region ran out first. The walk ends when Zillow stops naming a next page rather than when a page comes back looking thin, which is deliberate: a page served thin partway through a region is not the end of it.

Can rentals be collected through status? No, and that is a measurement rather than a policy. Zillow's rentals listing answers with a full-size page carrying no property identifiers on it at all; 0 of 3 attempts carried one. Rentals are keyed by something other than the identifier this Actor composes on, so accepting the value would return an empty result set for a page that visibly has listings on it, which reads as "there are no rentals in this city". Rental properties are reachable through Zillow Sitemap Scraper with the for_rent family, where they are filed under ordinary property identifiers.

Why is there an open-house description but no open-house start and end time? Zillow ships machine-form start and end values beside the description, and nothing in the capture pinned down what unit they are in. Unlabelled integers that look like timestamps get read as timestamps and acted on as though they were, so they are left out and the export carries only has_open_house and open_house_description, which state the same window with no guess in them.

Do pages overlap, and does a walk need de-duplication? No. Page 1 and page 2 of a measured region share zero property identifiers, compared as sets rather than by response size. A repeated identifier is dropped if one ever appears, but that guard has not fired on any region I have run.

What happens when a region slug is wrong? The run stops with a message naming the shape a region takes, rather than finishing with an empty dataset. An empty dataset from a mistyped slug is indistinguishable from a genuinely empty region, which is the worse of the two failures. A region that exists and has no matching homes is the second case, and it produces a normal run with no rows.

Why is broker_name populated while agent_name is empty? A listing row carries the brokerage and nothing further about who is selling. The agent's name, email address and telephone number are on the home's own record, so they require enrichPropertyDetails, or a second pass over the zpid column through Zillow Property Scraper.

Is a Zillow account, cookie or API key required? No. No account, session cookie or key of any kind is supplied to the Actor or needed by it.

Zillow Property Scraper reads a home in full from its identifier, or returns its price history, tax history, schools and comparables. It is the cheaper route once the identifiers are already in hand, because it spends no requests discovering them.

Zillow Sitemap Scraper exports property identifiers in bulk from Zillow's published index. It is the right choice when the goal is coverage of a population rather than the current state of one market.