A Zillow API request has two sides. You send parameters, such as price_max. The API returns fields, such as zpid and address. Mixing up those two groups is one of the easiest ways to build code that looks correct but saves the wrong data.

This guide uses the LetsScrape Real Estate Zillow.com API on RapidAPI. It explains which endpoint to choose, which filters belong in the request, and which fields belong in your database. The examples start with the smallest request that is useful.

This guide covers the LetsScrape API contract. LetsScrape is not affiliated with, endorsed by or sponsored by Zillow.

Choose the endpoint first

Do not begin by copying every available filter. First pick the route that matches the type of data you need.

What you needEndpointMain input
Location suggestionsGET /v1/autocompletequery
Homes for saleGET /v1/search/salelocation_or_rid or url, plus page
Rental listingsGET /v1/search/rentlocation_or_rid or url, plus page
Sold listingsGET /v1/search/soldlocation_or_rid or url, plus page
Listings inside a map rectangleGET /v1/search/coordstype, north, south, east, west
One property recordGET /v1/propertySee the warning below before using it
Area-level market dataGET /v1/market-trendslocation

The three regional search routes are separate. Use /sale, /rent or /sold. Do not call the old combined /zillow/v1/search route, and do not add type=sale to a regional sale request. The type parameter belongs to the coordinate search.

Make the smallest useful request

This request asks for the first page of sale listings in the provider's documented Miami region. It keeps the filter list short so each value is easy to check.

GET /v1/search/sale?location_or_rid=12700&page=1&beds_min=2&price_max=500000&sort=newest
X-RapidAPI-Host: real-estate-zillow-com.p.rapidapi.com
X-RapidAPI-Key: supplied from RAPIDAPI_KEY

location_or_rid accepts a location or a region identifier. page=1 selects the first results page. The remaining parameters ask for at least two bedrooms, a maximum sale price of 500000 and the newest sort order.

Keep the RapidAPI key in an environment variable. Do not paste it into source code, a URL, screenshots or logs. If this first request fails, check the HTTP status and the JSON status before changing filters.

Understand request parameters

A parameter changes what you ask the API to return. It is part of the query string and does not have to appear in each listing object.

ParameterPlain meaningBeginner note
location_or_ridA place name or Zillow region IDUse autocomplete when a typed place is ambiguous.
urlA complete Zillow search URLUse this instead of constructing a search from individual location inputs.
pageOne-based result pageStart at 1, then increase it by one.
beds_min, baths_minMinimum bedrooms and bathroomsThese are lower bounds, not exact matches.
price_min, price_maxPrice rangeOn the rent route, these values refer to rent rather than a sale price.
sqft_min, sqft_maxLiving-area rangeDo not confuse living area with lot size.
property_typesProperty categoriesUse values shown by the current endpoint documentation.
sortResult orderSale, rent and sold routes do not share every sort value.
dozDays-on-Zillow or recency filterUse only a value listed for the route you call.

Do not share every filter between routes

Basic range filters are similar, but the route-specific filters answer different questions. Build one small parameter dictionary for each search type. This is easier to debug than one large dictionary with switches.

RouteUseful documented filter groupsExample names
SaleListing source, lot and year ranges, HOA, physical features, views and listing statelisting_types, lot_min, year_min, hoa_max, garage, waterfront, open_houses, keyword
RentPet rules, amenities, access and move-in optionssmall_dogs, cats, laundry, parking, furnished, utilities_included, move_in_date
SoldRecency, physical features and viewsdoz, lot_min, year_min, garage, water_view
CoordinatesMap bounds and listing typetype, north, south, east, west

This table is a practical map, not a promise that every parameter accepts every value forever. Before deploying a saved search, open that endpoint in the RapidAPI playground and check its current type and allowed values. Then save a sanitized successful response as a test fixture.

Paginate without creating an endless loop

Sale, rent and sold searches use page. Request page 1, process its listings, then request page 2. Stop when the API returns no listings or when a page adds no new zpid values. Also set a maximum page count so one job cannot consume the whole request allowance.

Deduplicate with zpid, not with the result position, URL or formatted address. Positions change when sorting changes. URLs and addresses can be reformatted. Store zpid as text so your database does not perform arithmetic on it.

Read response fields defensively

The successful sale test returned a JSON envelope with description, numeric status and data. Its listings were inside data.listings. The sanitized sample below keeps the observed field names but replaces the property identity and address.

{
  "description": "OK",
  "status": 200,
  "data": {
    "listings": [
      {
        "zpid": "example-zpid",
        "address": "Example address, Austin, TX",
        "unformattedPrice": 425000,
        "beds": 2,
        "baths": 2,
        "area": 1137,
        "detailUrl": "https://www.zillow.com/homedetails/example-zpid/"
      }
    ]
  }
}

The provider documentation also describes listing fields such as price, statusType, daysOnZillow, latitude and longitude. Your code should use the fields present in a response from your subscribed plan instead of assuming that every property has every field.

FieldWhat to storeSafe handling
zpidExternal property identifierConvert it to text and require it before saving a listing.
addressDisplay addressAllow null and do not use it as a primary key.
price or unformattedPriceNumeric observed priceRead the numeric field present in your verified response. Do not calculate with a formatted currency string.
beds, baths, areaPhysical attributesAllow null. Missing does not mean zero.
statusTypeSource status stringStore the original value instead of inventing your own mapping too early.
daysOnZillowNullable durationIt is not an observation timestamp.
latitude, longitudeNullable coordinatesValidate their numeric ranges before map use.
detailUrlSource page linkKeep it as optional display data, not identity.

Normalize only what you need

A small local model is easier to maintain. The function below accepts either documented numeric price name, keeps missing values as None, and adds your own observation time. The observation time is application data. It is not a Zillow API field.

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):
    zpid = row.get("zpid")
    if zpid is None:
        raise ValueError("Listing has no zpid")

    raw_price = row.get("price")
    if raw_price is None:
        raw_price = row.get("unformattedPrice")

    return {
        "zpid": str(zpid),
        "address": row.get("address"),
        "price": decimal_or_none(raw_price),
        "beds": decimal_or_none(row.get("beds")),
        "baths": decimal_or_none(row.get("baths")),
        "area": decimal_or_none(row.get("area")),
        "detail_url": row.get("detailUrl"),
        "observed_at_utc": datetime.now(timezone.utc).isoformat(),
    }

For money comparisons, choose one representation and keep it consistent. A Decimal works well while parsing. A database can store an exact decimal amount or integer cents. Do not mix dollars, cents and formatted strings in one column.

Treat the property endpoint as unverified

The public product description advertises a property endpoint and property-detail fields. However, three subscribed requests made on July 30, 2026, using a live ZPID, a live property URL and the documentation's example ZPID all returned HTTP 200 with JSON status 400 and a missing parameter message.

That result may have been a temporary regression, but there is no later successful test in the available evidence. Do not build a required production step around /v1/property until a request from your own subscription returns a successful JSON status. Do not promise Zestimate, tax history, HOA, school or photo fields based only on the marketing page.

Fix the common mistakes first

  • Old route: replace /zillow/v1/search with the dedicated /v1/search/sale, /rent or /sold route.
  • Wrong filter family: do not send rental pet filters to a sale request.
  • HTTP 200 accepted too early: also check the JSON status before reading data.
  • Null changed to zero: keep missing bedrooms, area, price or coordinates as unknown.
  • Only one page fetched: increment page, deduplicate by zpid, and set a page limit.
  • Secret written to logs: never log request headers that contain the RapidAPI key.

A beginner-friendly integration checklist

  1. Subscribe to the API and put the key in RAPIDAPI_KEY.
  2. Run one /v1/search/sale request with location_or_rid and page=1.
  3. Check the HTTP status, then check the JSON status.
  4. Save a sanitized response and inspect its real listing container and field names.
  5. Normalize only the fields your application needs.
  6. Add one filter at a time and confirm that the returned listings still match your intention.
  7. Add pagination, a page limit, timeout handling and redacted logs.

For a complete implementation, continue with the Python-to-JSON guide. If you need change detection, use the Python and SQLite price-drop monitor.