Coming soonZillow API for Google Sheets

Zillow API for Google Sheets

Coming soon: Zillow data in your spreadsheet with one formula. Paste a column of Zillow links or addresses, type =ZILLOW_PRICE(A2) or =ZILLOW_ZESTIMATE(A2), and fill down. A short Apps Script does the work.

The formulas

Added to your sheet by the script below. Each one takes a Zillow link or an address.

Google Sheets formulas for Zillow data
FormulaReturns
=ZILLOW_PRICE(A2)Listing price for the Zillow link or address in A2
=ZILLOW_ZESTIMATE(A2)Zestimate, when Zillow shows one
=ZILLOW_RENT(A2)Rent Zestimate (rentZestimate)
=ZILLOW_STATUS(A2)Listing status (homeStatus), e.g. FOR_SALE or RECENTLY_SOLD
=ZILLOW_FIELD(A2, "beds")Any top-level field of data: beds, baths, livingArea, lotSize, yearBuilt, homeType, daysOnZillow, zpid, detailUrl
What your sheet looks like
      A                                                  B                    C                       D
1  Zillow link or address                             Price                Zestimate               Beds
2  https://www.zillow.com/homedetails/…_zpid/         =ZILLOW_PRICE(A2)    =ZILLOW_ZESTIMATE(A2)   =ZILLOW_FIELD(A2, "beds")
3  1600 Main St, Austin, TX 78701                     =ZILLOW_PRICE(A3)    =ZILLOW_ZESTIMATE(A3)   =ZILLOW_FIELD(A3, "beds")
4  …fill down

Set it up

Open your sheet, go to Extensions → Apps Script, paste this, and add your key as a script property.

Apps Script: custom functions
// Extensions → Apps Script. Paste this, then save.
// Project Settings → Script properties → add PROPERTIESAPI_KEY = your key.
const BASE = "https://api.propertiesapi.com/v1";

function zillowLookup_(input) {
  input = String(input || "").trim();
  if (!input) return null;

  // Cache for 6 hours so recalculating the sheet doesn't repeat lookups.
  const cache = CacheService.getScriptCache();
  const cacheKey = Utilities.base64EncodeWebSafe(input).slice(0, 240);
  const hit = cache.get(cacheKey);
  if (hit) return JSON.parse(hit);

  const param = /^https?:\/\//i.test(input) ? "url" : "address";
  const res = UrlFetchApp.fetch(BASE + "/zillow/property?" + param + "=" + encodeURIComponent(input), {
    headers: { "x-api-key": PropertiesService.getScriptProperties().getProperty("PROPERTIESAPI_KEY") },
    muteHttpExceptions: true,
  });
  const code = res.getResponseCode();
  if (code === 404) return null;                       // no matching Zillow property (not billed)
  if (code !== 200) throw new Error("PropertiesAPI HTTP " + code);

  const data = JSON.parse(res.getContentText()).data;   // body is { data, meta }
  const text = JSON.stringify(data);
  if (text.length < 90000) cache.put(cacheKey, text, 21600);
  return data;
}

/** Listing price from a Zillow link or address. @customfunction */
function ZILLOW_PRICE(input) { const h = zillowLookup_(input); return h ? h.price : "not found"; }

/** Zestimate from a Zillow link or address. @customfunction */
function ZILLOW_ZESTIMATE(input) { const h = zillowLookup_(input); return h ? h.zestimate : "not found"; }

/** Rent Zestimate from a Zillow link or address. @customfunction */
function ZILLOW_RENT(input) { const h = zillowLookup_(input); return h ? h.rentZestimate : "not found"; }

/** Listing status from a Zillow link or address. @customfunction */
function ZILLOW_STATUS(input) { const h = zillowLookup_(input); return h ? h.homeStatus : "not found"; }

/** Any top-level field, e.g. =ZILLOW_FIELD(A2, "beds"). @customfunction */
function ZILLOW_FIELD(input, field) { const h = zillowLookup_(input); return h ? h[field] : "not found"; }
  • Lookups run live, so each new cell takes typically 8 seconds, up to about 20. Repeat lookups of the same home within 24 hours come from our cache, fast and free.
  • A blank cell means Zillow doesn't show that field for the home, for example no price on an off-market home.
  • "not found" means we couldn't match a Zillow property. You aren't billed for it.

Batch a whole column

Hundreds of formulas each make their own call. For long lists, one menu click is faster and stays under Google's time limits.

Apps Script: batch menu
// For long lists: one menu click fills a whole column block using the batch endpoint.
// Column A = Zillow links or addresses (row 1 is a header). Writes columns B to H.
function onOpen() {
  SpreadsheetApp.getUi().createMenu("Zillow").addItem("Fill sheet", "fillSheet").addToUi();
}

function fillSheet() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const inputs = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues().map((r) => String(r[0]).trim());
  const key = PropertiesService.getScriptProperties().getProperty("PROPERTIESAPI_KEY");
  const out = [];

  for (let i = 0; i < inputs.length; i += 50) {
    const chunk = inputs.slice(i, i + 50);
    const items = chunk.filter(Boolean);                 // links or addresses
    const res = UrlFetchApp.fetch("https://api.propertiesapi.com/v1/zillow/batch", {
      method: "post",
      contentType: "application/json",
      headers: { "x-api-key": key },
      payload: JSON.stringify({ items }),
      muteHttpExceptions: true,
    });
    if (res.getResponseCode() !== 200) throw new Error("PropertiesAPI HTTP " + res.getResponseCode());
    const results = JSON.parse(res.getContentText()).data;   // same order as items, each { index, ok, data }
    let j = 0;
    chunk.forEach((x) => {
      const r = x ? results[j++] : null;
      const h = r && r.ok ? r.data : null;
      out.push(h ? [h.homeStatus, h.price, h.zestimate, h.rentZestimate, h.beds, h.baths, h.livingArea] : ["not found", "", "", "", "", "", ""]);
    });
  }
  sheet.getRange(1, 2, 1, 7).setValues([["Status", "Price", "Zestimate", "Rent Zestimate", "Beds", "Baths", "Sqft"]]);
  sheet.getRange(2, 2, out.length, 7).setValues(out);
}
Step 1

Paste your list

Zillow links, addresses or a mix, in column A with a header in row 1.

Step 2

Click Zillow → Fill sheet

The script sends 50 rows per request to POST /v1/zillow/batch. Rows we can't match say "not found".

Step 3

Read the results

Status, price, Zestimate, rent Zestimate, beds, baths and square feet fill in next to each row.

Same data as CSV (example row, illustrative values)
input,homeStatus,price,zestimate,rentZestimate,beds,baths,livingArea,yearBuilt,daysOnZillow
"1600 Main St, Austin, TX 78701",FOR_SALE,525000,512000,2650,3,2,1840,1998,12

Prefer code? The Python tutorial batches a CSV into pandas in a dozen lines.

Try it on your own list

50 free lookups, no card. Join the list; keys go out as we open accounts. The script is coming soon.

Get a free key →

Google Sheets questions

Is there a Zillow API for Google Sheets?+

Zillow doesn't offer one. This page shows a short Apps Script that adds =ZILLOW_PRICE() and similar formulas by calling PropertiesAPI, an independent service that is not affiliated with Zillow. The data is what the public Zillow page shows, provided as-is.

Can I use an address instead of a Zillow link?+

Yes. Put either one in the cell. Anything starting with http is sent as ?url=; anything else is sent as ?address= and we find the matching Zillow property.

Why do cells show Loading?+

A live lookup fetches the Zillow page, so it takes typically 8 seconds, up to about 20. Google stops a custom function after about 30 seconds, so a slow lookup can show an error: recalculate later (repeat lookups within 24 hours come from our cache, fast and free), or use the batch menu script for long lists instead of hundreds of formulas.

Will recalculating the sheet use up my lookups?+

The script caches each result for 6 hours, so a recalculation within that window doesn't call the API again. On our side, repeat lookups of the same home within 24 hours are free anyway. Failed lookups, such as a link we can't find, aren't billed.

Does it work in Excel?+

Not with this script. Excel can call the same API with Power Query or Office Scripts, or you can call the batch endpoint and convert its JSON to rows.

How many rows can I run?+

50 free lookups, with no card. Paid plans (lookups a month): Starter $29/mo (2,500); Pro $79/mo (7,500); Business $199/mo (20,000); Scale $499/mo (65,000). Overage is your plan's own per-lookup rate ($11.60 per 1,000 on Starter, down to $7.68 on Scale). The batch endpoint takes up to 50 links or addresses per request.

Your spreadsheet, filled in

50 free lookups, no card. The Sheets script is coming soon.

Zillow is a trademark of Zillow, Inc. PropertiesAPI is an independent service and is not affiliated with, endorsed by or sponsored by Zillow.