Zillow property data explained: fields, filters and endpoints
The current LetsScrape Zillow offer has separate endpoints for sale, rental and sold searches, plus autocomplete, map bounds, property detail and market trends. This guide maps each job to the right route and shows which returned fields are safe to normalize, which are optional, and why zpid is the best property key.
Key Takeaways
- Use the three dedicated search routes; the current offer does not expose a generic
/v1/searchendpoint. pageapplies to sale, rent and sold searches, while the coordinate endpoint documents only a type and four bounds.- Store
zpidas a string and treat estimates, media, brokerage and several physical attributes as nullable. - Normalize numeric values separately from display strings such as
price_, and record your own UTC observation time.
Property integrations usually fail at a boundary, not in the HTTP client. A search parameter gets mistaken for a returned field, a filter from the sale endpoint is sent to rentals, or an address is used as a database key and changes formatting on the next run. The safest starting point is the contract that is actually exposed by the LetsScrape Zillow API today.
This guide documents the current LetsScrape offer on RapidAPI. LetsScrape is not affiliated with, endorsed by or sponsored by Zillow.
The active API surface contains seven GET endpoints. The listing workflow is deliberately split into sale, rent and sold routes. There is no current generic /v1/search route, and the paths do not use the older /zillow/v1 prefix.
Endpoint decision table
| Goal | Endpoint | Required request input | Use it when |
|---|---|---|---|
| Resolve a location | GET /v1/autocomplete | query | You want suggestions and a stable regionId before searching. |
| Find homes for sale | GET /v1/search/sale | page; provide location_or_rid or url | You need active sale inventory and sale-specific filters. |
| Find rentals | GET /v1/search/rent | page; provide location_or_rid or url | You need monthly-rent searches, pet rules or rental amenities. |
| Find recently sold homes | GET /v1/search/sold | page; provide location_or_rid or url | You need sold inventory and the supported recency choices in doz. |
| Search a map viewport | GET /v1/search/coords | type, north, south, east, west | Your UI already knows the visible bounding box. |
| Expand one property | GET /v1/property | zpid_or_url | You have a search result and need the detail-page record. |
| Read market indicators | GET /v1/market-trends | location | You need market-level data such as ZHVI or ZORI, not listings. |
Search endpoints return collections suitable for discovery, feeds and snapshots. The property endpoint expands one known record. Market trends are a third data shape: they describe an area rather than a property. Keep these models separate in your application even if they share a location label.
Request parameters versus response fields
Names in a query string control the request. They are not guaranteed to appear in each returned listing. For example, price_max is a request filter; price is a response field. Likewise, location_or_rid chooses an area, while address, latitude and longitude describe an individual result.
| Endpoint | Current parameter contract | Important constraint |
|---|---|---|
/v1/autocomplete | query (required string) | Use returned regionId as a region input to a search. |
/v1/search/sale | location_or_rid, url, filters; page required | url represents a direct search URL and supersedes constructed search input. |
/v1/search/rent | location_or_rid, url, rental filters; page required | Price bounds represent monthly rent in this route. |
/v1/search/sold | location_or_rid, url, sold filters; page required | doz accepts only the currently declared recency values. |
/v1/search/coords | type = sale, rent or sold, plus four required numeric bounds | No page or price/bed filter is declared for this endpoint today. |
/v1/property | zpid_or_url (required string) | Send either the property identifier or a property URL in the same parameter. |
/v1/market-trends | location (required string) | This is not the older slug parameter. |
Filters that exist today
The three listing routes share the basic range filters but diverge after that. Comma-separated enum values should come from the current endpoint options. Do not send a rental amenity to the sale route simply because another scraper supports it.
| Route | Supported filters and enum values |
|---|---|
| Shared by sale, rent and sold | location_or_rid, url, property_types, sort, page, beds_min, baths_min, price_min, price_max, sqft_min, sqft_max, doz. Property types: house, condo, townhouse, multi_family, apartment, lot, manufactured. Recency: 7, 30, 90, 6m, 12m, 36m. |
| Sale only | listing_types (agent, owner, new_construction, coming_soon, auction, foreclosure), lot_min, lot_max, year_min, year_max, hoa_max, pool, garage, ac, waterfront, storage, has_basement, basement_finished, basement_unfinished, parking_spaces_min, city_view, mountain_view, park_view, water_view, tour_3d, open_houses, accepting_backup_offers, sale_pending, coming_soon_only, keyword. |
| Sold only | The sale/sold physical and view filters above, but no listing_types. The current contract declares parking_spaces_min as a boolean on this route; do not silently coerce it to the numeric sale definition. |
| Rent only | small_dogs, large_dogs, cats, no_pets, pool, laundry, parking, storage, controlled_access, ac, furnished, high_speed_internet, outdoor_space, hardwood_floors (currently declared as a string), utilities_included, disability_access, income_restricted, short_term_lease, city_view, mountain_view, park_view, water_view, tour_3d, accepts_applications, instant_tour, exclude_55plus, move_in_date, hide_no_date. |
Sort values also differ. Sale and sold declare relevant, price_asc, price_desc, newest, beds, baths, size and lot. Rent declares verified_score, payment_asc, payment_desc, recommended, newest, beds, baths, size and lot.
Pagination and location input
page is a required numeric parameter on sale, rent and sold searches, with a documented default value of 1. Increment it explicitly and stop when the returned listing collection is empty or when a page adds no new zpid values. Do not invent a total-page field, cursor or page size unless the response you receive actually contains one.
location_or_rid accepts either a human location such as a city or a region identifier. Autocomplete is useful when a user types partial text: call /v1/autocomplete?query=..., present the suggestions, retain the returned regionId, and send that value to the chosen listing route. This avoids ambiguous place names. A direct url is the alternative when your application already has a Zillow search URL.
Map search behaves differently. Supply north, south, east and west as numeric latitude/longitude bounds plus the required type. The current coordinate endpoint does not declare pagination or the listing filters above, so a map client should not assume feature parity.
Response field groups
Successful calls use a top-level status and data wrapper. The listing collection inside data can be source-dependent, so find the array of objects containing zpid rather than hard-coding an undocumented container. The current public response contract documents these listing fields:
| Group | Exact response fields | Handling guidance |
|---|---|---|
| Identity | zpid, detailUrl | Require zpid for persistence; keep the URL as a navigational attribute. |
| Location | address, latitude, longitude | Coordinates and formatted address may be absent or change formatting. |
| Price and estimates | price, price_, zestimate, rentZestimate | Use numeric price for calculations and preserve price_ only for display. |
| Status and source | statusType, listingType, daysOnZillow, brokerName | Expect source-specific enum strings and nullable brokerage metadata. |
| Property attributes | beds, baths, area, lotAreaValue, lotAreaUnit | Lots, apartments and incomplete listings do not expose the same attributes. |
| Media | imgSrc | Treat media URLs as optional, external and replaceable. |
The property-detail route is for richer, nested data after search. The offer describes details such as price and address, physical attributes, estimates, tax and price history, HOA information, schools, photos, agent data and description. Those groups depend on what the source page exposes. Do not manufacture missing keys or promise that a rental, land parcel and sold home share one complete detail schema.
The market endpoint returns area-level indicators including the Zillow Home Value Index (ZHVI) and Zillow Observed Rent Index (ZORI). Keep those series out of your property table: a market observation is keyed by its location and observation period, not by zpid.
Compact listing sample
This valid JSON shows one documented listing object. The placeholder collection name is intentional because the surrounding collection is source-dependent.
{
"status": 200,
"data": {
"<listing collection>": [{
"zpid": "19977945",
"address": "Example address, Miami, FL",
"price": 450000,
"price_": "$450,000",
"beds": 3,
"baths": 2,
"area": 1450,
"statusType": "FOR_SALE",
"daysOnZillow": 4,
"latitude": 25.7617,
"longitude": -80.1918,
"imgSrc": "https://example.invalid/photo.jpg",
"detailUrl": "https://www.zillow.com/homedetails/19977945_zpid/"
}]
}
}
zpid is the identity; price is the calculation value; price_ is presentation; coordinates are numbers; and media is nullable. Example hostnames and addresses are illustrative, while field casing follows the verified response contract.
Normalization pattern
| Input | Normalized representation | Rule |
|---|---|---|
zpid | String | Convert once with str(value); never use a formatted address as the primary key. |
price, estimates | Decimal or integer minor units | Reject booleans and non-finite values; do not parse price_ when numeric price exists. |
area, lotAreaValue | Decimal plus explicit unit | Keep lotAreaUnit; do not assume every lot value is square feet. |
latitude, longitude | Nullable decimal/float | Validate latitude from -90 to 90 and longitude from -180 to 180. |
daysOnZillow | Nullable integer duration | It is not a timestamp. Record a separate ingestion time such as observed_at_utc. |
| Detail-response dates | Nullable ISO 8601 UTC or source date | Parse only fields actually present; retain the original value when timezone or precision is unclear. |
from datetime import datetime, timezone
from decimal import Decimal, InvalidOperation
def decimal_or_none(value):
if value is None or isinstance(value, bool):
return None
try:
number = Decimal(str(value))
return number if number.is_finite() else None
except (InvalidOperation, ValueError):
return None
def normalize_listing(row):
return {
"zpid": str(row["zpid"]),
"price": decimal_or_none(row.get("price")),
"area_sqft": decimal_or_none(row.get("area")),
"lot_value": decimal_or_none(row.get("lotAreaValue")),
"lot_unit": row.get("lotAreaUnit"),
"latitude": decimal_or_none(row.get("latitude")),
"longitude": decimal_or_none(row.get("longitude")),
"observed_at_utc": datetime.now(timezone.utc).isoformat(),
}
Common integration mistakes
- Using an old route. The active routes start with
/v1and split sale, rent and sold searches. Do not call a generic/zillow/v1/search. - Sending
typeto a regional search. Choose/sale,/rentor/sold;typebelongs to/v1/search/coords. - Assuming every endpoint shares filters. The coordinate route has only five declared inputs, while rentals and sales have different filter sets and sort enums.
- Confusing numeric and display values. Calculate with
price, notprice_. - Treating estimates as guaranteed prices.
zestimateandrentZestimateare optional estimates and may be absent. - Stopping after one page. Increment
pagefor the three regional listing routes and deduplicate byzpid. - Assuming all HTTP failures use the success wrapper. Handle 400, 429, 500 and 504 responses before reading
data; gateway authentication errors may have a different JSON body. - Overwriting null with zero. Missing beds, area, estimates or coordinates mean unknown/not supplied, not necessarily zero.
Choosing a stable internal identifier
Use zpid as the external property key and store it as text. It survives price, status, photo and address-format changes better than a URL or a concatenated address. A practical unique constraint is (source, zpid), where source is your own constant such as zillow. Keep regionId separate: it identifies a search region, not a property.
For history, do not update one row and discard the old value. Store an observation keyed by your internal property ID and observed_at_utc, then compare price and status between snapshots. This preserves provenance while letting the current-property table remain small.