---
title: "Zillow Listings API: Get Property Data as JSON"
description: "One GET to /v1/zillow/search returns listings near a point as JSON with price, beds, baths and address. Parameters, a real response, 1 credit per call."
url: https://perceptlayer.com/blog/zillow-listings-api-json
---

[Blog](https://perceptlayer.com/blog) / [API guides](https://perceptlayer.com/blog/category/api-guides)

# Zillow Listings API: Get Property Data as JSON

22 Oct 2026 Perceptlayer 7 min read

You can get Zillow listings as JSON with one GET request to `/v1/zillow/search` on the Perceptlayer API. Pass a latitude, longitude and radius, and the response lists properties with address, price, bedrooms, bathrooms and photos. Each successful call costs 1 credit, and a failed call costs nothing. This guide shows the request, the parameters, a trimmed real response and the cost per 1,000 calls.

## Key takeaways

-   `GET /v1/zillow/search` takes a point and radius ( `latitude`, `longitude`, `radius_mi`) or a bounding box, and returns listings under `data.listings`.
-   Filters include `min_price`, `max_price`, `min_beds`, `min_baths`, `home_statuses[]` and `sort_order`. All of them are optional.
-   Look up one property with `GET /v1/zillow/property?zpid[]=<id>`, using the `zpid` from a search result.
-   Every Zillow endpoint costs 1 credit per successful call: 1,000 calls is 1,000 credits, or $0.80 on the Starter pack.
-   The free tier gives 1,000 credits a month after you verify an email address. No credit card.

## Is there an official Zillow listings API?

Zillow Group runs a [developer site](https://www.zillowgroup.com/developers/) that lists APIs for MLS listings, rentals feeds, public data and Zestimates, offered to the public and to partners. Those programs have their own terms and eligibility. If your use fits one, check that route first, because it's the authoritative one.

If you aren't, or you need a plain search-by-location call returning JSON today, that's the gap the Perceptlayer [Zillow API](https://perceptlayer.com/apis/zillow) fills. It exposes 10 endpoints under one key, with the same authentication and credit model as every site in the catalogue: Zillow is one of 248 websites and 1,659 endpoints in the catalogue.

Data is collected from publicly available sources and returned as found at the time of the call. Listing fields can change between calls, so store the timestamp of each pull.

## How do you get a key and make the first call?

Sign up, verify your email and copy a key that starts with `sk_live_`. Send it in the `X-API-Key` header on every request. If you can't set headers, the `api_key` query parameter works instead. The free tier is 1,000 credits a month, enough for 1,000 Zillow calls, so you can run everything below without paying. The [authentication docs](https://perceptlayer.com/docs#authentication) cover both options.

[Get a free API key](https://perceptlayer.com/signup), export it, then run this search for listings within 5 miles of a point in Seattle (latitude 47.6062, longitude -122.3321):

```bash
export API_KEY=sk_live_your_key_here

curl "https://api.perceptlayer.com/v1/zillow/search?latitude=47.6062&longitude=-122.3321&radius_mi=5&listing_category=category1&page_size=20" \
  -H "X-API-Key: $API_KEY"
```

The response is JSON with a `data` object. The listings sit in `data.listings`, one object per property. The [requests docs](https://perceptlayer.com/docs#requests) explain the general conventions that apply to every endpoint.

## Which parameters does the search endpoint take?

`/v1/zillow/search` has no required parameters, but you'll always want to say where to look. Use a centre point with `radius_mi`, a bounding box made of four coordinates, `region_ids[]`, or a `polygon` string. Everything else narrows the results by price, size, status or keyword. The table groups all 29 parameters by job.

| Group | Parameter | Type |
| --- | --- | --- |
| Point and radius | `latitude`, `longitude`, `radius_mi` | number |
| Bounding box | `north_latitude`, `south_latitude`, `east_longitude`, `west_longitude` | number |
| Region | `region_ids[]` | list of integer |
| Region | `region_id_type` | integer |
| Shape | `polygon` | string |
| Category | `listing_category` | string: `all`, `category1`, `category2` |
| Status | `home_statuses[]` | list of string |
| Status | `include_off_market`, `allow_empty` | boolean |
| Price | `min_price`, `max_price` | integer |
| Size | `min_beds`, `max_beds`, `min_baths`, `max_baths` | integer |
| Size | `living_area_min`, `lot_size_min`, `year_built_min` | integer |
| Text | `keywords` | string |
| Map | `zoom_level` | integer |
| Sorting | `sort_order` | string, see below |
| Sorting | `sort_ascending` | boolean |
| Paging | `page`, `page_size` | integer |

`sort_order` accepts one of `baths`, `yearBuilt`, `price`, `relevance`, `beds`, `daysOn`, `featured`, `livingArea`, `lotArea`, `nearby`, `recentlyChanged`, `rentalDays` or `rentalPriorityScore`.

The reference doesn't say what `category1` and `category2` select, so try each on your area and compare the results before you build on one. The example request above uses `category1`.

### Narrowing the search

Add filters as plain query parameters. This request asks for homes with at least 3 bedrooms and 2 bathrooms between $500,000 and $900,000, sorted by price:

```bash
curl "https://api.perceptlayer.com/v1/zillow/search?latitude=47.6062&longitude=-122.3321&radius_mi=5&min_price=500000&max_price=900000&min_beds=3&min_baths=2&sort_order=price&sort_ascending=true&page_size=20" \
  -H "X-API-Key: $API_KEY"
```

A tight filter can return few or no listings, so loosen one filter at a time if a search comes back thin. The search endpoint also takes an `allow_empty` boolean.

## What does a search response look like?

The response wraps results in `data.listings`. Each listing carries a `zpid` (the property ID), a `location`, an `address`, a `media` block with photo links, and the facts a valuation or lead tool needs: `bedrooms`, `bathrooms`, `livingArea`, `yearBuilt`, `propertyType`, a `listing` status object and a `price` object. This is a trimmed excerpt of a recorded response to the Seattle request above:

```json
{
  "data": {
    "listings": [
      {
        "zpid": 2068074790,
        "location": {
          "latitude": 47.592564,
          "longitude": -122.386925
        },
        "address": {
          "streetAddress": "1124 Sunset Avenue SW",
          "zipcode": "98116",
          "city": "Seattle",
          "state": "WA"
        },
        "media": { … },
        "currency": "usd",
        "country": "usa",
        "bestGuessTimeZone": "America/Los_Angeles",
        "bathrooms": 6,
        "bedrooms": 4,
        "livingArea": 7870,
        "yearBuilt": 2015,
        "lotSizeWithUnit": {
          "lotSize": 0.2652,
          "lotSizeUnit": "acres"
        },
        "propertyType": "singleFamily",
        "listing": {
          "listingStatus": "forSale",
          "marketingStatus": "active",
          "palsId": "39001_2591845"
        },
        "price": {
          "value": 14000000,
          "pricePerSquareFoot": 1779
        …
```

Field names are camelCase and nested. Price is at `price.value`, the street at `address.streetAddress`, and the lot size is an object with a value and a unit. The excerpt also holds media flags and recommendation blocks that we've cut with `…`. Treat any field you don't see in your own response as absent, and check for it in code rather than assuming it's there.

## How do you fetch one property by ID?

Take the `zpid` from a search result and pass it to `/v1/zillow/property`. The endpoint has no required parameters and accepts a `zpid[]` list. Per-endpoint pages, such as [Zillow API: Property](https://perceptlayer.com/apis/zillow/property), list the parameters and let you try the call.

```bash
curl "https://api.perceptlayer.com/v1/zillow/property?zpid[]=2068074790" \
  -H "X-API-Key: $API_KEY"
```

We haven't recorded a property response for this guide, so we won't show one. Run the call on your own key and inspect the JSON before you map fields.

The other Zillow endpoints follow the same pattern:

| Endpoint | Use it for | Credits |
| --- | --- | --- |
| `/v1/zillow/autocomplete` | Turn a typed place name into suggestions ( `query` required) | 1 |
| `/v1/zillow/photos` | Photos for one or more `zpid[]` | 1 |
| `/v1/zillow/photo` | One photo by `photo_id`, with optional `size` | 1 |
| `/v1/zillow/building` | A building by `slug`, `lot_id` or coordinates | 1 |
| `/v1/zillow/schools` | Schools by ID or bounding box | 1 |
| `/v1/zillow/market-data` | Market statistics ( `family` and `geography` required) | 1 |

## How do you call it from Python?

The same request in Python needs only `requests`. This script searches around the same Seattle point, then prints address, bedrooms and price for each listing. It reads the key from the environment and checks the status before parsing, so a failed call raises an error instead of returning bad data.

```python
import os
import requests

resp = requests.get(
    "https://api.perceptlayer.com/v1/zillow/search",
    headers={"X-API-Key": os.environ["API_KEY"]},
    params={
        "latitude": 47.6062,
        "longitude": -122.3321,
        "radius_mi": 5,
        "listing_category": "category1",
        "page_size": 20,
    },
    timeout=30,
)
resp.raise_for_status()

for item in resp.json()["data"]["listings"]:
    print(
        item.get("zpid"),
        (item.get("address") or {}).get("streetAddress"),
        item.get("bedrooms"),
        (item.get("price") or {}).get("value"),
    )
```

To page through more results, increase `page` and keep `page_size` fixed. Each page is its own call and its own credit, so pick the smallest `page_size` that covers your need.

## What does it cost per 1,000 calls?

Every Zillow endpoint costs 1 credit per successful call, so 1,000 search calls use 1,000 credits. Failed calls cost nothing and come back with `X-Credits-Used: 0`. The free tier of 1,000 credits a month covers 1,000 calls. Beyond that, purchased credits last 12 months, with no subscription and no seats. The [credits docs](https://perceptlayer.com/docs#credits) and [pricing page](https://perceptlayer.com/pricing) have the detail.

| Plan | Price | Credits | Cost per 1,000 calls |
| --- | --- | --- | --- |
| Free tier | $0 | 1,000 a month | $0 |
| Starter | $10 | 12,500 | $0.80 |
| Growth | $50 | 83,000 | $0.60 |
| Scale | $200 | 400,000 | $0.50 |

A worked example: refreshing 10 search areas twice a day for 30 days is 10 × 2 × 30 = 600 calls, or 600 credits, which fits inside the free tier. A job making 10,000 calls a month uses 10,000 credits, within the Starter pack's 12,500, at $0.80 per 1,000 calls.

## What happens when a call fails?

A failed call returns an HTTP status and a JSON body shaped as `{"error": {"code", "message", "request_id"}}`, and it isn't billed. The codes you'll most likely meet are `invalid_api_key` (401), `insufficient_credits` (402), `invalid_parameters` (422), `rate_limited` (429) and `source_error` (502). The [errors docs](https://perceptlayer.com/docs#errors) list all of them.

Handle them by code, not by message text. Retry `rate_limited`, `source_error` and `temporarily_unavailable` (503) with a growing delay between attempts. A 429 is the standard "too many requests" status, defined in [RFC 6585](https://www.rfc-editor.org/rfc/rfc6585#section-4) (2012). Fix `invalid_parameters` before you retry, since repeating the same request will fail the same way. See the [rate limits docs](https://perceptlayer.com/docs#limits) for the limits on your key.

## Can an AI agent call these endpoints?

Yes. The MCP server at `https://api.perceptlayer.com/mcp` exposes `search_endpoints`, `get_endpoint` and `call_endpoint`, so an agent can find the Zillow search endpoint and call it without custom glue code. In Claude Code, add it with the command below, then ask for listings in a city. The [MCP docs](https://perceptlayer.com/docs#mcp) cover other clients.

```bash
claude mcp add --transport http perceptlayer https://api.perceptlayer.com/mcp --header "Authorization: Bearer $API_KEY"
```

Only successful calls are billed and failed calls cost nothing, so cap the number of calls a task may make. For more real estate sources, see the [real estate APIs](https://perceptlayer.com/verticals/real-estate).

Ready to try it? [Get a free API key](https://perceptlayer.com/signup), run the Seattle search above, and check the [Zillow API page](https://perceptlayer.com/apis/zillow) for the other nine endpoints.

## APIs in this post

-   [Zillow **1 credit per call** · 10 endpoints](https://perceptlayer.com/apis/zillow)

## Frequently asked questions

### Does Zillow have a public API for listings?

Zillow Group lists official APIs on its [developer site](https://www.zillowgroup.com/developers/), covering MLS listings, rentals feeds, public data and Zestimates, for the public and for partners. If you qualify for a program, use it. If you need a key-based search call that returns JSON now, the Perceptlayer Zillow API provides one.

### How much does one Zillow search call cost?

One credit per successful call. That's $0.80 per 1,000 calls on the Starter pack ($10 for 12,500 credits), $0.60 on Growth and $0.50 on Scale. The free tier includes 1,000 credits a month after you verify an email address, with no credit card. Failed calls return `X-Credits-Used: 0`.

### How do I search by area instead of a radius?

Use the bounding box: `north_latitude`, `south_latitude`, `east_longitude` and `west_longitude`. You can also pass `region_ids[]` with `region_id_type`, or a `polygon` string. All are optional parameters on `/v1/zillow/search`, and each search is one call and one credit.

### Can I filter by price and bedrooms?

Yes. Use `min_price` and `max_price` for price, and `min_beds`, `max_beds`, `min_baths` and `max_baths` for rooms. Add `living_area_min`, `lot_size_min` or `year_built_min` to cut further. Combine them in one request and you still pay one credit.

### Is the data complete and current?

Data is collected from publicly available sources and returned as found at the time of the call. We don't promise completeness or freshness beyond that. For anything time-sensitive, such as a price change, call again and compare against your stored copy.

zillow real estate listings property data api

## More from the blog

1.  [AI agents](https://perceptlayer.com/blog/category/ai-agents) 22 Oct 2026 Perceptlayer 7 min read
    
    ## [AI Agent API Cost Control: Cap Web Data Spend](https://perceptlayer.com/blog/ai-agent-web-data-costs)
    
    Cap an agent's web data spend per run: credit arithmetic for 8 and 20 calls per task, a Python budget wrapper, and why failed calls cost 0 credits.
    
2.  [AI agents](https://perceptlayer.com/blog/category/ai-agents) 22 Oct 2026 Perceptlayer 8 min read
    
    ## [Claude MCP Web Search: Live Results for an Agent](https://perceptlayer.com/blog/claude-agent-live-search-mcp)
    
    Add the Perceptlayer MCP server to Claude, let the agent call the Google Search endpoint, and count its cost: 1 credit per search call.
