Zillow batch lookup
POSThttps://api.propertiesapi.com/v1/zillow/batch
Up to 50 Zillow URLs or addresses in one request. Each item is looked up exactly as GET /v1/zillow/property would, and comes back with its own ok flag.
At a glance
- Billing: 1 credit per successful live lookup, by Zillow link or address. Repeat lookups of the same home within 24 hours come from cache and are free. Errors aren't billed.
- Auth:
x-api-keyheader. - Latency: typically 6 seconds, up to about 20 for a live lookup; repeat lookups within 24 hours come from the cache, with no live lookup.
Parameters
No query parameters. Send the items in the request body.
Request body
items: 1 to 50 entries. Each is a string (a zillow.com link, an address, or a zpid of 1–12 digits) or an object with exactly one of url, address or zpid. Optional status (for_sale, sold or for_rent) applies to every item; optional raw adds data.raw only when it is the JSON boolean true (any other value, such as the string "true", is ignored).
{
"items": [
"https://www.zillow.com/homedetails/2640-Steiner-St-San-Francisco-CA-94115/15073305_zpid/",
"1 Nowhere Rd, San Francisco, CA 94115",
{
"address": "2640 Steiner St, San Francisco, CA 94115"
},
{
"zpid": "2064142765"
}
],
"status": "for_sale"
}Example
curl "https://api.propertiesapi.com/v1/zillow/batch" -H "x-api-key: $PROPERTIESAPI_KEY" \
-H "content-type: application/json" \
-d '{"items":["https://www.zillow.com/homedetails/2640-Steiner-St-San-Francisco-CA-94115/15073305_zpid/","2640 Steiner St, San Francisco, CA 94115"]}'{
"data": [
{
"index": 0,
"ok": true,
"data": {
"zpid": "15073305",
"detailUrl": "https://www.zillow.com/homedetails/2640-Steiner-St-San-Francisco-CA-94115/15073305_zpid/",
"address": "2640 Steiner St, San Francisco, CA 94115",
"streetAddress": "2640 Steiner St",
"unit": null,
"city": "San Francisco",
"state": "CA",
"zipcode": "94115",
"county": "San Francisco County",
"neighborhood": null,
"latitude": 37.79,
"longitude": -122.44,
"price": 525000,
"currency": "USD",
"homeStatus": "FOR_SALE",
"statusText": "For sale",
"homeType": "SINGLE_FAMILY",
"beds": 3,
"baths": 2,
"livingArea": 1840,
"lotSize": 6970,
"yearBuilt": 1998,
"pricePerSquareFoot": 285,
"zestimate": 512000,
"rentZestimate": 2650,
"daysOnZillow": 12,
"datePosted": "2026-10-07",
"dateSold": null,
"lastSoldPrice": null,
"monthlyHoaFee": null,
"taxAnnualAmount": 9840,
"taxAssessedValue": 498000,
"propertyTaxRate": 1.98,
"pageViewCount": null,
"favoriteCount": null,
"parcelId": null,
"description": "Three-bedroom home near downtown.",
"imgSrc": "https://photos.example.com/15073305-1.jpg",
"photos": [
"https://photos.example.com/15073305-1.jpg",
"https://photos.example.com/15073305-2.jpg"
],
"photoCount": 2,
"brokerName": "Example Realty",
"brokerPhone": null,
"agentName": null,
"agentPhone": null,
"agentLicenseNumber": null,
"mlsId": null,
"mlsName": null,
"priceHistory": [
{
"date": "2026-10-07",
"event": "Listed for sale",
"price": 525000,
"pricePerSquareFoot": 285,
"priceChangeRate": null,
"source": "Example MLS"
}
],
"taxHistory": [
{
"year": 2025,
"taxPaid": 9840,
"value": 498000,
"taxIncreaseRate": null,
"valueIncreaseRate": null
}
],
"schools": [],
"virtualTourUrl": null,
"scrapedAt": "2026-10-19T14:02:11.000Z",
"calculated": {
"price_per_sqft": 285.33,
"zestimate_per_sqft": 278.26,
"rent_to_price_ratio": 0.0606,
"rent_to_price_basis": "price",
"gross_yield_pct": 6.06,
"price_vs_zestimate_pct": 2.54,
"last_sale_price": null,
"last_sale_date": null,
"change_since_last_sale_pct": null,
"change_since_last_sale_basis": null,
"days_on_market": 12,
"price_drops_count": 0,
"last_price_change": null
}
},
"meta": {
"credits": 0,
"cached": true,
"cache_key": "zpid:15073305",
"fetched_at": "2026-10-19T14:02:11.000Z",
"source": {
"note": "Read from the public Zillow page. Field availability varies by listing. PropertiesAPI is not affiliated with Zillow."
},
"release": "v1",
"took_ms": 2,
"completeness": {
"fields": {
"lotSize": {
"availability": "supplied"
},
"propertyTaxRate": {
"availability": "supplied"
},
"pageViewCount": {
"availability": "not_returned"
},
"favoriteCount": {
"availability": "not_returned"
},
"photos": {
"availability": "supplied",
"count": 2
},
"priceHistory": {
"availability": "supplied",
"count": 1
},
"taxHistory": {
"availability": "supplied",
"count": 1
},
"schools": {
"availability": "empty_array",
"count": 0
},
"virtualTourUrl": {
"availability": "not_returned"
},
"dateSold": {
"availability": "not_returned"
}
},
"required": [],
"missing": [],
"requirements_satisfied": true
}
}
},
{
"index": 1,
"ok": false,
"error": {
"code": "not_found",
"message": "No Zillow property matches this input"
}
}
],
"meta": {
"count": 2,
"succeeded": 1,
"failed": 1,
"cache_hits": 1,
"credits": 0,
"release": "v1",
"took_ms": 9120
}
}Example values are illustrative, not a real record. Fields Zillow doesn't show for a property come back as null. Data is provided as-is.
Notes
- More than 50 items returns 400 too_many_items. An empty or missing items array, or a body that isn't JSON, returns 400 bad_body; a body over 64 KB returns 413 bad_body, and one that doesn't arrive in time returns 408 request_timeout. Split larger lists into several requests.
- The request itself can fail with status 400, 401, 408, 413, 429, 500 or 503 (see Errors). Once the request is accepted, each item has its own result.
- data has one result per item, in the same order, with its index. Check each result's ok: one failed item doesn't fail the batch. A failed item has error { code, message, details } with the same codes as GET /v1/zillow/property (such as credits_exhausted, not_found, zpid_mismatch, address_ambiguous, rate_limited, upstream_busy and upstream_timeout), plus batch_deadline and batch_response_too_large. It carries no HTTP status of its own: the error table gives each code's status.
- When the account runs out of credits or of its per-minute limit part-way, meta.credits_exhausted or meta.rate_limited lists the indexes of the items that weren't looked up (they cost nothing). meta.credits_remaining is the included credits left, for account keys.
- Items run concurrently within an overall time limit of about 280 seconds. Items that couldn't start in time come back with error code batch_deadline; retry those.
- meta.credits is the number of credits charged. Only successful live lookups count; cache hits and failed items are free.
- Each successful item's data has the same fields as GET /v1/zillow/property, data.calculated included.
Errors
Errors are { error: { code, message, details? }, meta: { took_ms } } with status 400, 401, 500, 503 (per-item errors are inside data). Errors aren't billed. See errors.
Zillow is a trademark of Zillow, Inc. PropertiesAPI is an independent service and is not affiliated with, endorsed by or sponsored by Zillow.
Zillow batch lookup questions
How many properties can I send at once?+
Up to 50 items per request. Split longer lists into several requests.
What happens if one item fails?+
The rest still come back. Each result has its own ok flag, and failed items aren't billed.
Is this Zillow's official API?+
No. PropertiesAPI is an independent service and is not affiliated with, endorsed by or sponsored by Zillow. The data is provided as-is.
Do failed lookups cost anything?+
No. Only successful live lookups are billed. Errors are free, and repeat lookups of the same home within 24 hours come from cache for free.
Related guides
- Zillow API batch lookups: handle partial success
Process multiple Zillow properties with the batch API, preserve row identity, and retry individual failures without losing successful results.
- Calculate Estimated Gross Rental Yield for a Property Shortlist
A Python gross rental yield calculator for a property shortlist that labels every input: your assumed price and rent, or the source's asking price and rent Zestimate, with expenses excluded.
- Triage a Real Estate Lead List with Claude and the Zillow MCP Server
Sort inbound real estate leads by current Zillow listing status in one Claude session: strip the CRM export, set the rules, run one MCP batch and review unclear rows.