Zillow property lookup
GEThttps://api.propertiesapi.com/v1/zillow/property
One property by Zillow URL or address: listing price and status, Zestimate, rent Zestimate, beds, baths, living area, lot, year built, home type, photo URLs, days on Zillow, price history, tax history, schools, broker and agent.
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.
- Replaces: the old GetSearchResults, GetDeepSearchResults, GetZestimate and GetUpdatedPropertyDetails calls from the retired Zillow API.
Parameters
Send exactly one of url or address.
| Name | In | Type | Description |
|---|---|---|---|
| zpid | query | string | A Zillow property ID, 1–12 digits. Give exactly one of url, zpid or address. |
| url | query | string | A zillow.com property link: a home (zillow.com/homedetails/..._zpid/, zillow.com/homes/..._zpid/ or a new-construction zillow.com/community/.../..._zpid/ link) or a building (zillow.com/b/... or zillow.com/apartments/...). Photo and other sub-pages after the property part are ignored. Other zillow.com pages, such as search results, return 400 bad_param, free. URL-encode it. Max 500 characters. Short links (zil.lw) and m.zillow.com links aren't accepted (400 bad_param, free): send the full www.zillow.com link. |
| address | query | string | A one-line US address with a house number, 5-200 characters. We find the matching Zillow property first. Include the unit number for condos and apartments. |
Other parameters
| Name | In | Type | Description |
|---|---|---|---|
| status | query | string: for_sale | sold | for_rent | Optional hint for which listing to read, for a home listed for sale and for rent at once. It is a hint, not a filter: a home served from the 24-hour cache, or found first by our primary source, comes back with whatever listing it has, so check homeStatus. When the home returned doesn't have the status you asked for, meta.warning says so. If omitted, the status is detected automatically. |
| raw | query | boolean | Also return the unmapped source record as data.raw. Unstable: it is the record of whichever source served the lookup, so its keys and casing differ between lookups (even of the same home) and change without notice. Don't parse it; use the documented fields. Default false. |
Response fields
The body is { data, meta }. Fields of data (any can be null; lists can be empty):
| Field | Type | Description |
|---|---|---|
zpid | string | Zillow property ID. null for an apartment building (a zillow.com/apartments/ link): a building has no zpid of its own, so use its detailUrl as its id. |
detailUrl | string | The Zillow property page. |
address | string | One-line address. |
streetAddress | string | Street line. |
unit | string | Unit number, e.g. 1905 for 600 N Fairbanks Ct APT 1905. For an apartment building, the unit that price describes (see price). |
city | string | City. |
state | string | Two-letter state code. |
zipcode | string | ZIP code. |
county | string | County. |
neighborhood | string | Neighborhood name. |
latitude | number | Latitude. |
longitude | number | Longitude. |
price | number | List price. For rentals, the monthly rent. For an apartment building (a zillow.com/apartments/ link), the rent of its lowest-priced unit available now (no move-in date, or one on or before the lookup date; if none is available yet, its lowest-priced unit); beds, baths, livingArea and unit describe that same unit. For sold homes, the sale price, or null when the sale price isn't disclosed. Never 0. |
currency | string | Currency of price, e.g. USD. |
homeStatus | string | Zillow's status code: FOR_SALE, FOR_RENT, RECENTLY_SOLD, PENDING, COMING_SOON, FORECLOSURE, OFF_MARKET or OTHER. Homes that aren't listed usually come back as OTHER. |
statusText | string | A short readable status built from Zillow's status and listing flags: For sale, Pending, Coming soon, New construction, For sale by owner, Foreclosure, Auction, For rent, Sold or Off market. Null when the status is unclear. |
homeType | string | SINGLE_FAMILY, CONDO, TOWNHOUSE, MULTI_FAMILY, APARTMENT, LOT, MANUFACTURED, ... |
beds | number | Bedrooms. |
baths | number | Bathrooms. |
livingArea | number | Living area in square feet. |
lotSize | number | Lot size in square feet (acres converted). |
yearBuilt | integer | Year built. |
pricePerSquareFoot | number | Price per square foot. |
zestimate | number | Zillow's Zestimate, when shown. |
rentZestimate | number | Zillow's rent Zestimate (a month), when shown. |
daysOnZillow | integer | Zillow's day count for the home. For a listed home, the days the current listing has been on Zillow. Sold and off-market homes usually still have a count (counted from an earlier listing or event), which isn't days on market: use calculated.days_on_market, which is null unless the home is listed. |
datePosted | string | Date the current listing went on the market (the day daysOnZillow counts from), YYYY-MM-DD. Null when the home isn't listed (sold or off market). |
dateSold | string | Date of the last sale, YYYY-MM-DD. |
lastSoldPrice | number | Last sale price. |
monthlyHoaFee | number | HOA fee a month. |
taxAnnualAmount | number | Annual property tax. |
taxAssessedValue | number | Assessed value. |
propertyTaxRate | number | Property tax rate, percent. |
pageViewCount | integer | Cumulative views supplied by the source. Zero is meaningful; null when not returned. |
favoriteCount | integer | Favorites supplied by the source. Zero is meaningful; null when not returned. |
parcelId | string | Parcel (APN) number. |
description | string | Listing description. |
imgSrc | string | Main photo URL. |
photos | string[] | Photo URLs as published on the listing. Never re-hosted. Can be empty. |
photoCount | integer | Number of photos. |
brokerName | string | Listing brokerage. |
brokerPhone | string | Brokerage phone. |
agentName | string | Listing agent. |
agentPhone | string | Agent phone. |
agentLicenseNumber | string | Agent license number. |
mlsId | string | MLS listing number. |
mlsName | string | MLS name. |
priceHistory | ZillowPriceEvent[] | Past events, newest first: date, event, price, pricePerSquareFoot, priceChangeRate, source. priceChangeRate is the change from the previous priced event of the same kind (sale or rent), as a fraction (−0.05 = 5% lower), and 0 when there is none; null when it can't be determined. Can be empty. |
taxHistory | ZillowTaxEvent[] | Tax years: year, taxPaid, value (assessed), taxIncreaseRate, valueIncreaseRate. Can be empty. |
schools | ZillowSchool[] | Nearby schools: name, rating, distance (miles), level, type, grades, link. Can be empty. |
virtualTourUrl | string | Virtual tour link. |
scrapedAt | string | When the data was collected (ISO 8601). |
calculated | CalculatedFields | Figures calculated by PropertiesAPI from the returned fields; not Zillow estimates. Each is null when an input it needs is missing. See Calculated fields for every formula. |
Calculated fields
Calculated by PropertiesAPI from the returned fields; not Zillow estimates. They are plain arithmetic on the fields in the same response, never other data. Any figure whose inputs are missing, zero or don't apply to the home's status is null. Money is in USD rounded to cents, percentages to 2 decimals and ratios to 4 decimals. Fields of data.calculated:
| Field | Type | Formula |
|---|---|---|
price_per_sqft | number | price ÷ livingArea. Only when price is a sale or asking price: null for rentals (price is a monthly rent) and when the status is unknown. |
zestimate_per_sqft | number | zestimate ÷ livingArea. |
rent_to_price_ratio | number | rentZestimate × 12 ÷ price, or ÷ zestimate when there is no price (and always for rentals, whose price is a rent). rent_to_price_basis says which was used. |
rent_to_price_basis | string | price or zestimate: the denominator of rent_to_price_ratio. Null when the ratio is null. |
gross_yield_pct | number | rent_to_price_ratio × 100: the rent Zestimate for a year as a percent of the price (or Zestimate). Before vacancy, taxes, insurance and other costs. |
price_vs_zestimate_pct | number | (price − zestimate) ÷ zestimate × 100. Negative means the price is below the Zestimate. Only when price is a sale or asking price. |
last_sale_price | number | The price of the most recent Sold event in priceHistory. Null when that sale's price isn't disclosed (an older sale's price is never used instead). |
last_sale_date | string | The date of the most recent Sold event in priceHistory, YYYY-MM-DD. |
change_since_last_sale_pct | number | (value now − last_sale_price) ÷ last_sale_price × 100, where value now is the asking price for a home listed for sale (for sale, pending, coming soon, foreclosure), otherwise the zestimate. change_since_last_sale_basis says which was used. |
change_since_last_sale_basis | string | price or zestimate: the value now used by change_since_last_sale_pct. Null when that figure is null. |
days_on_market | integer | daysOnZillow, only while the home is listed (for sale, pending, coming soon, foreclosure or for rent). Null otherwise: for a sold or off-market home Zillow's day count isn't days on market. Zillow's count can run across a relist, so it can cover a longer stretch than price_drops_count, which counts only the most recent listing. |
price_drops_count | integer | In the most recent listing of the home's kind (from the last Listed for rent event for a rental, otherwise the last Listed for sale event, in priceHistory), the number of Price change events whose price is lower than the event before it in that listing. Events named for the other kind (a Listed for rent inside a sale listing) are skipped. Null when priceHistory has no such listing event. |
last_price_change | object | The latest Price change event in that same listing: { date, price, previous_price, change, change_pct }, where previous_price is the price of the event before it in that listing (never one from before the listing started, never one of the other kind), change = price − previous_price and change_pct = change ÷ previous_price × 100. Null when there is none. |
Example
curl -G "https://api.propertiesapi.com/v1/zillow/property" \
-H "x-api-key: $PROPERTIESAPI_KEY" \
--data-urlencode "url=https://www.zillow.com/homedetails/2640-Steiner-St-San-Francisco-CA-94115/15073305_zpid/"{
"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": 1,
"cached": false,
"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": 14230,
"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
}
}
}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
- Send exactly one of url, zpid or address. Sending none returns 400 missing_param; sending several returns 400 bad_param.
- The body is { data, meta }. data is the property; meta has credits, cached, cache_key, fetched_at, source, release, took_ms, completeness and, when there is something to check, warning. For some answers meta.source_age is "approximate": the source served a copy it may have collected earlier, so fetched_at (when we received it) can be a few hours later than when the data was collected; those answers stay in our cache for a shorter time.
- meta.source.note says where the data comes from: the property's public Zillow page. You're billed once per successful live lookup.
- The x-cache response header is HIT when the result came from the 24-hour cache (free, no live lookup) and MISS when it was fetched live.
- A live lookup typically takes 6 seconds, up to about 20. Set a client timeout of at least 120 seconds: an occasional lookup takes longer.
- Fields Zillow doesn't show for a property come back as null. Don't treat null as zero.
- A page with no listing data at all (no price, beds, baths, size, available units or Zestimate; for example a building with no units listed) returns 404 not_found, not billed.
- Which fields are filled can depend on how the home was first looked up (by link, zpid or address), and the 24-hour cache keeps that first answer: for example the tax amounts, the tax rate and the view and favorite counts. When PropertiesAPI has collected the same home both ways within 24 hours, the result carries both sets (each value for at most a day after it was collected). meta.completeness says, for this response, which of the commonly missing fields were supplied, came back null or came back as an empty list.
- daysOnZillow is Zillow's own day count and is usually set for sold and off-market homes too. For days on market use calculated.days_on_market, which is null unless the home is listed.
- With raw=true, data.raw is the unmapped source record, untouched: values PropertiesAPI corrects in data (for example priceHistory[].priceChangeRate from some sources) are left as the source sent them there. It is unstable: its keys and casing depend on which source served the lookup, so they differ between lookups of the same home and change without notice. Don't parse it.
- Every response carries x-api-version and cache-control; authenticated requests also get the rate-limit headers, and account keys the credit headers (see Headers). Errors carry the same headers, plus retry-after when there is a wait to honor.
- price is the listing price (monthly rent for rentals). zestimate and rentZestimate are Zillow's own estimates, returned only when Zillow shows them. PropertiesAPI doesn't make estimates of its own.
- data.calculated has figures calculated by PropertiesAPI from the returned fields; not Zillow estimates: price and Zestimate per square foot, the rent-to-price ratio and gross yield, price vs Zestimate, the last sale and the change since it, days on market, and price drops. Each is null when its inputs are missing. The formulas are under Calculated fields.
- A building link (zillow.com/apartments/... or zillow.com/b/...) returns the building: address, photos and schools are the building listing's, zpid is null (use detailUrl as the building's id), and price, beds, baths, livingArea and unit come from its lowest-priced unit available now (no move-in date, or one on or before the lookup date; if none is available yet, its lowest-priced unit). The other units aren't returned yet.
- photos is a list of image URLs. priceHistory, taxHistory and schools are lists and can be empty.
- Data is provided as-is, as shown on the public Zillow page at the time of the lookup. It isn't official and isn't guaranteed to be accurate or complete.
Errors
Errors are { error: { code, message, details? }, meta: { took_ms } } with status 400, 401, 404, 422, 500, 502, 503 or 504. 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 property lookup questions
Can I look up a property by address instead of a Zillow link?+
Yes. Send address instead of url and we find the matching Zillow property first. An address lookup costs 1 credit, the same as a link.
How long does a lookup take?+
A live lookup takes typically 6 seconds, up to about 20. Set a client timeout of at least 120 seconds: an occasional lookup takes longer. A cache hit (x-cache: HIT) skips the live lookup and is free.
What do I get for an apartment building link?+
The building. zpid, address and photos are the building listing's, and price, beds, baths, livingArea and unit describe its lowest-priced unit available now (no move-in date, or one on or before the lookup date; if none is available yet, its lowest-priced unit). The other units aren't returned yet.
Why is zestimate null?+
Zillow doesn't show a Zestimate for every home. When the page doesn't show one, the field is null.
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
- Missing Zestimate data: handle null values correctly
Why is a Zestimate not available? What a missing Zestimate means, and how to keep null distinct from zero, asking price, and rent Zestimate.
- Asking Rent vs. Rent Zestimate: Build a Rental Comparison Spreadsheet
What the rent Zestimate means, how it differs from the asking rent, and a Python report that compares the two for a list of rental properties.
- Use Zillow Property Data in Claude with MCP
A worked research session with the PropertiesAPI MCP server: connect Claude, compare a shortlist of Zillow homes, handle an ambiguous address and check your remaining credits.