Zillow API migration: map the old calls to JSON
The calls from the retired Zillow API, mapped to a working JSON endpoint. Swap the URL and the key, rename a few fields, and get Zestimates and listing data back. Where there's no replacement, we say so.
Old call → new endpoint
Base URL https://api.propertiesapi.com/v1, header x-api-key. Every lookup takes a Zillow link (?url=), or an address (?address=). The JSON body is { data, meta }.
| Old Zillow API call | PropertiesAPI endpoint | Notes |
|---|---|---|
| GetSearchResults | GET /v1/zillow/property?address= | Send one address string instead of address + citystatezip. Returns the ZPID, the Zillow link and the Zestimate, plus much more. |
| GetDeepSearchResults | GET /v1/zillow/property?address= | Same call. Beds, baths, square feet, lot, year built, price history and tax history come back in one response. |
| GetZestimate | GET /v1/zillow/property?url= or ?address= | Takes a Zillow link or an address. Lookups by ZPID alone aren't supported yet. Returns zestimate and rentZestimate when Zillow shows them. No valuation range. |
| GetUpdatedPropertyDetails | GET /v1/zillow/property?url= | Photo URLs, home facts, listing price and status, days on Zillow, the listing broker and agent, as shown on the Zillow page. |
| GetComps / GetDeepComps | No equivalent | We don't return comparable sales. Look up the comps you choose one by one, or with the batch endpoint. |
| GetChart | No equivalent | No chart images. priceHistory gives you the listing and sale events to chart yourself. |
| GetRegionChildren | No equivalent | No region or neighbourhood data. Lookups are per property. |
| (no old call) | POST /v1/zillow/batch | Up to 50 Zillow links or addresses in one request. The old API had no bulk call. |
Field names
What the old XML fields are called in our JSON.
| Old field | PropertiesAPI field |
|---|---|
| zpid | zpid |
| links.homedetails | detailUrl |
| address.street / city / state / zipcode | streetAddress / city / state / zipcode (plus address, one string) |
| address.latitude / longitude | latitude / longitude |
| zestimate.amount | zestimate |
| zestimate.valuationRange.low / high | No equivalent |
| rentzestimate.amount | rentZestimate |
| bedrooms / bathrooms | beds / baths |
| finishedSqFt | livingArea |
| lotSizeSqFt | lotSize |
| yearBuilt | yearBuilt |
| useCode | homeType |
| lastSoldDate / lastSoldPrice | dateSold / lastSoldPrice |
| taxAssessmentYear / taxAssessment | taxHistory[].year / taxHistory[].value (or taxAssessedValue) |
| images.image.url (GetUpdatedPropertyDetails) | photos |
| (none) | price, homeStatus, daysOnZillow, priceHistory, taxHistory[].taxPaid, brokerName, agentName, schools |
Code: before and after
// Before: Zillow Web Services (retired 2021)
const url = "http://www.zillow.com/webservice/GetDeepSearchResults.htm"
+ "?zws-id=" + ZWSID
+ "&address=" + encodeURIComponent("1600 Main St")
+ "&citystatezip=" + encodeURIComponent("Austin, TX 78701")
+ "&rentzestimate=true";
// -> XML, now 410 Gone// After: PropertiesAPI (JSON)
const u = new URL("https://api.propertiesapi.com/v1/zillow/property");
u.searchParams.set("address", "1600 Main St, Austin, TX 78701");
const res = await fetch(u, {
headers: { "x-api-key": process.env.PROPERTIESAPI_KEY },
signal: AbortSignal.timeout(120_000), // live lookup: typically 8 seconds, up to about 20
});
if (res.status === 404) throw new Error("no matching Zillow property");
const { data: p } = await res.json();
// Shape it like your old code expects
const result = {
zpid: p.zpid,
links: { homedetails: p.detailUrl },
zestimate: { amount: p.zestimate },
rentzestimate: { amount: p.rentZestimate },
bedrooms: p.beds, bathrooms: p.baths, finishedSqFt: p.livingArea,
lotSizeSqFt: p.lotSize, yearBuilt: p.yearBuilt,
};import os, requests
KEY = {"x-api-key": os.environ["PROPERTIESAPI_KEY"]}
BASE = "https://api.propertiesapi.com/v1"
# GetZestimate (you stored ZPIDs): send the address or Zillow link you stored with it
p = requests.get(
f"{BASE}/zillow/property",
params={"address": "1600 Main St, Austin, TX 78701"},
headers=KEY,
timeout=120,
).json()["data"]
print(p["zestimate"], p["rentZestimate"])
# Many old GetSearchResults calls at once: POST /v1/zillow/batch (up to 50 per request)
addresses = ["1600 Main St, Austin, TX 78701", "350 5th Ave, New York, NY 10118"]
r = requests.post(
f"{BASE}/zillow/batch",
json={"items": addresses},
headers=KEY,
timeout=320,
)
for item in r.json()["data"]: # same order as items
print(addresses[item["index"]], item["data"]["zestimate"] if item["ok"] else "not found")What doesn't carry over
- No comps: GetComps and GetDeepComps have no equivalent.
- No Zestimate range: you get the Zestimate itself, when Zillow shows one, but not the low and high values.
- No charts or region data: GetChart and GetRegionChildren have no equivalent. priceHistory gives you the events to chart.
- Slower calls: a live lookup fetches the Zillow page and takes typically 8 seconds, up to about 20. Repeat lookups of the same home within 24 hours come from cache, fast and free. Use the batch endpoint for many homes.
- Not official: PropertiesAPI is independent of Zillow. The data is what the public Zillow page shows, provided as-is.
Migration questions
Is the Zillow API deprecated?+
Yes. The legacy Zillow Web Services API (ZWSID keys, GetSearchResults, GetZestimate and the rest) started returning errors in February 2021 and was retired on 30 September 2021. Zillow's current APIs run through Bridge Interactive, by application.
What's the alternative to GetSearchResults?+
GET /v1/zillow/property?address= with the full address as one string. It returns the ZPID, the Zillow link, the Zestimate and the rest of the property in JSON.
Do you return Zestimates?+
Yes, when the Zillow page for that property shows one, along with the rent Zestimate. There is no valuation range. PropertiesAPI is an independent service, not affiliated with Zillow, and the data is provided as-is.
Is there a replacement for GetComps?+
No. We don't pick comparable sales. If you already know which homes you want to compare, look each one up, or send them together to the batch endpoint.
Do I need a ZPID?+
No. Send a plain address or a Zillow link. Lookups by ZPID alone aren't supported yet, so if your database only holds ZPIDs, send the address you stored with each one.
Is the response XML like the old API?+
No, it's JSON. Map the fields once with the table above, then adapt your parsing to the JSON.
Bring your old app back
50 free lookups, no card. Join the list; keys go out as we open accounts.
Zillow is a trademark of Zillow, Inc. PropertiesAPI is an independent service and is not affiliated with, endorsed by or sponsored by Zillow.