Zillow API
The TrueScrape Zillow API exposes 3 public endpoints covering Zillow agent profile, Zillow listing details and Search Zillow listings by location. Every call is a GET against public, logged-out pages and returns the same unified schema as every other platform here. Calls cost 1 credit each. A cache hit is free, and a failed or empty response is never charged.
Endpoints
| Endpoint | Returns | Credits | Cacheable | Batchable |
|---|---|---|---|---|
| /v1/zillow/agent | Zillow agent profile | 1 | yes | yes |
| /v1/zillow/property | Zillow listing details | 1 | yes | yes |
| /v1/zillow/search | Search Zillow listings by location | 1 | yes | yes |
Reference
/v1/zillow/agent1 creditcacheablebatchableZillow agent profile
Public Zillow agent/team profile: brokerage, license, rating and review count, where published.
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | yes | Zillow agent profile URL, e.g. https://www.zillow.com/profile/<username> |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns one RealEstateAgent.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | null | always | |
| name | string | null | always | |
| url | string | null | always | |
| photoUrl | string | null | always | |
| brokerageName | string | null | always | |
| licenseNumber | string | null | always | |
| phone | string | null | always | |
| bio | string | null | always | |
| languages | string[] | always | |
| serviceAreas | string[] | always | |
| rating | number | null | always | |
| reviewCount | number | null | always | |
| salesStats | AgentStat[] | always | Sales figures the source publishes for the agent, such as deals closed or average days on market. Which figures appear varies by source. |
| listings | PropertyListing[] | always | Property listings shown on the agent's profile. |
| fetchedAt | string | always | When this record was retrieved, as an ISO 8601 timestamp. |
curl "$API/v1/zillow/agent?url=8XkPqR2nLvE&cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
url: '8XkPqR2nLvE',
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/zillow/agent?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/zillow/agent",
params={
"url": "8XkPqR2nLvE",
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/zillow/property1 creditcacheablebatchableZillow listing details
Public details for a Zillow listing: price, status, beds/baths, area, address and an inline photo set. **Required:** Pass either zpid or url.
| Parameter | Type | Required | Description |
|---|---|---|---|
| zpid | string | no | Zillow property id (zpid), e.g. "120900080" |
| url | string | no | Zillow listing URL, e.g. https://www.zillow.com/homedetails/<slug>/<zpid>_zpid/ |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns one PropertyListing.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | The property id on its source, such as a Zillow zpid. Always a string. |
| url | string | null | always | |
| listingType | sale | rent | null | always | |
| status | active | pending | under_offer | sold | rented | off_market | unknown | null | always | Where the listing is in its lifecycle. `pending` and `under_offer` mean a deal is in progress. `off_market` means withdrawn without a sale and may return, unlike `sold`. `unknown` means the status could not be read as one of the other values. |
| price | number | null | always | Asking price, or the rent for a rental, in `currency`. Read it together with `priceQualifier`. |
| currency | string | null | always | ISO 4217 currency code for the amounts in this record, such as USD or EUR. |
| priceQualifier | string | null | always | Wording that changes what `price` means, such as "offers over", "guide price", "per month" or "starting at". |
| pricePerArea | number | null | always | Price per unit of area, in `currency` per `areaUnit`. |
| address | Address | always | |
| latitude | number | null | always | |
| longitude | number | null | always | |
| beds | number | null | always | |
| baths | number | null | always | Number of bathrooms. Can be fractional, such as 2.5. |
| receptions | number | null | always | Number of reception rooms, a figure UK and European listings state. US listings have no equivalent, so it is null there. |
| area | number | null | always | Interior floor area, in `areaUnit`. |
| areaUnit | sqft | sqm | null | always | Unit of `area`: `sqft` for square feet, `sqm` for square metres. Null when the source gave no unit. |
| lotArea | number | null | always | Area of the plot the property stands on, in `lotAreaUnit`. |
| lotAreaUnit | sqft | sqm | null | always | Unit of `lotArea`: `sqft` for square feet, `sqm` for square metres. Null when the source gave no unit. |
| propertyType | string | null | always | Property type as the source words it, so values differ between sources. |
| yearBuilt | number | null | always | |
| description | string | null | always | |
| imageUrls | string[] | always | |
| floorPlanUrls | string[] | always | |
| agentName | string | null | always | |
| agentPhone | string | null | always | |
| brokerageName | string | null | always | The listing brokerage, or the management company for a rental building. |
| amenities | Record<string, string> | always | Further listing facts as label and value pairs, such as HOA dues, a council tax band or an energy rating. Which labels appear varies by source. |
| schools | School[] | always | |
| priceHistory | PriceEvent[] | always | Past events for the property, such as listings, price changes and sales. |
| listedAt | string | null | always | When the property was listed. Usually an ISO 8601 timestamp; some sources pass their own date text through. |
| updatedAt | string | null | always | When the source last updated the listing. Usually an ISO 8601 timestamp; some sources pass their own date text through. |
| fetchedAt | string | always | When this record was retrieved, as an ISO 8601 timestamp. |
curl "$API/v1/zillow/property?cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/zillow/property?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/zillow/property",
params={
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
/v1/zillow/search1 creditcacheablebatchableSearch Zillow listings by location
Public Zillow search results for a location, as full listing records. **Required:** Pass either location or url.
| Parameter | Type | Required | Description |
|---|---|---|---|
| location | string | no | City/state or ZIP, e.g. "Austin, TX" |
| url | string | no | Zillow search URL, e.g. https://www.zillow.com/austin-tx/ |
| listing_type | sale | rent | no | defaults to sale |
| page | number | no | defaults to 1 |
Also accepts cache_max_age (a hit costs 0 credits) and include_raw (returns the untouched upstream payload under raw).
Returns a list of PropertyListing in data.items.
Fields
| Field | Type | Present | Description |
|---|---|---|---|
| platform | one of 32 strings | always | |
| id | string | always | The property id on its source, such as a Zillow zpid. Always a string. |
| url | string | null | always | |
| listingType | sale | rent | null | always | |
| status | active | pending | under_offer | sold | rented | off_market | unknown | null | always | Where the listing is in its lifecycle. `pending` and `under_offer` mean a deal is in progress. `off_market` means withdrawn without a sale and may return, unlike `sold`. `unknown` means the status could not be read as one of the other values. |
| price | number | null | always | Asking price, or the rent for a rental, in `currency`. Read it together with `priceQualifier`. |
| currency | string | null | always | ISO 4217 currency code for the amounts in this record, such as USD or EUR. |
| priceQualifier | string | null | always | Wording that changes what `price` means, such as "offers over", "guide price", "per month" or "starting at". |
| pricePerArea | number | null | always | Price per unit of area, in `currency` per `areaUnit`. |
| address | Address | always | |
| latitude | number | null | always | |
| longitude | number | null | always | |
| beds | number | null | always | |
| baths | number | null | always | Number of bathrooms. Can be fractional, such as 2.5. |
| receptions | number | null | always | Number of reception rooms, a figure UK and European listings state. US listings have no equivalent, so it is null there. |
| area | number | null | always | Interior floor area, in `areaUnit`. |
| areaUnit | sqft | sqm | null | always | Unit of `area`: `sqft` for square feet, `sqm` for square metres. Null when the source gave no unit. |
| lotArea | number | null | always | Area of the plot the property stands on, in `lotAreaUnit`. |
| lotAreaUnit | sqft | sqm | null | always | Unit of `lotArea`: `sqft` for square feet, `sqm` for square metres. Null when the source gave no unit. |
| propertyType | string | null | always | Property type as the source words it, so values differ between sources. |
| yearBuilt | number | null | always | |
| description | string | null | always | |
| imageUrls | string[] | always | |
| floorPlanUrls | string[] | always | |
| agentName | string | null | always | |
| agentPhone | string | null | always | |
| brokerageName | string | null | always | The listing brokerage, or the management company for a rental building. |
| amenities | Record<string, string> | always | Further listing facts as label and value pairs, such as HOA dues, a council tax band or an energy rating. Which labels appear varies by source. |
| schools | School[] | always | |
| priceHistory | PriceEvent[] | always | Past events for the property, such as listings, price changes and sales. |
| listedAt | string | null | always | When the property was listed. Usually an ISO 8601 timestamp; some sources pass their own date text through. |
| updatedAt | string | null | always | When the source last updated the listing. Usually an ISO 8601 timestamp; some sources pass their own date text through. |
| fetchedAt | string | always | When this record was retrieved, as an ISO 8601 timestamp. |
curl "$API/v1/zillow/search?cache_max_age=7d" \
-H "x-api-key: $KEY"const query = new URLSearchParams({
cache_max_age: '7d',
});
const response = await fetch(`${API}/v1/zillow/search?${query}`, {
headers: { 'x-api-key': KEY },
});
const body = await response.json();
if (!body.success) throw new Error(body.error.code);
// 1 credit, 0 on a cache hit
console.log(body.data, body.meta.creditsCharged);Python
import os, httpx
r = httpx.get(
f"{os.environ['API']}/v1/zillow/search",
params={
"cache_max_age": "7d",
},
headers={"x-api-key": os.environ["KEY"]},
timeout=30,
)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"]["code"])
print(body["data"], body["meta"]["creditsCharged"])Response codes
| 200 | Success |
| 400 | invalid_request. Not charged |
| 401 | missing_api_key / invalid_api_key / revoked_api_key. Never a billing error |
| 402 | insufficient_credits. The key is valid, the balance is not |
| 429 | daily_cap_exceeded or upstream_rate_limited. Not charged |
| 501 | not_configured. This deployment is not set up to serve this endpoint. Not charged. |
| 502 | upstream_blocked / upstream_schema_drift. Not charged |
| 504 | upstream_timeout. Not charged |
Questions
- How much does the Zillow API cost?
- Calls cost 1 credit each. Every endpoint is cacheable, and a cache hit costs nothing. A failed request and an empty result are both free, on every endpoint.
- Does the Zillow API need a login or cookies?
- No. Every endpoint reads public, logged-out pages only — no account, no cookies, no session. An API key identifies your own TrueScrape account and nothing else.
- Can I fetch many Zillow targets in one request?
- Yes. 3 of 3 are batchable: one POST to /v1/jobs/batch takes many targets and returns a job id to poll.
- Can I watch Zillow endpoints for changes?
- Yes, 2 of 3. A subscription polls on your schedule and fires your webhook only when the content changed; the rest carry x-subscribable: false in the spec.