Zillow API for Airtable

Zillow data in Airtable

Enrich an Airtable base of properties with Zillow listing data: one script reads the Zillow link or address from each record, looks them up in batches and writes the fields back.

Base URL https://api.propertiesapi.com/v1 · auth header x-api-key. PropertiesAPI is an independent service that returns Zillow property and listing data as JSON, provided as-is.

How Airtable fits

Airtable is where many small investment teams and agents keep their deal pipeline. The scripting extension can call any HTTPS API with fetch, so you can keep Zillow fields on each record current without exporting and re-importing.

The script below sends records to the batch endpoint, up to 50 items per request, so a large table takes a handful of requests instead of one per record. Records that fail keep their old values and get the error code in a Status field, so you can see what to fix.

Run it from the scripting extension rather than from an automation when the table is large: automations limit how long a script may run, and a live lookup takes typically 8 seconds, up to about 20 seconds. Repeat lookups of the same home within 24 hours come from our cache and are free.

Add the fields

In your Homes table, keep one field with the Zillow link or address and add the output fields the script writes. Field names must match the script, or change the script.

Fields in the Homes table
Input            single line text  (Zillow link or full address)
Price            currency
Zestimate        currency
Rent Zestimate   currency
Status           single line text
Zillow URL       URL
Lookup error     single line text

Paste the script

Add the Scripting extension, paste this, and set your key at the top. It reads every record that has an Input, looks them up in batches and writes the results back.

Airtable script
const KEY = "YOUR_KEY";
const table = base.getTable("Homes");
const query = await table.selectRecordsAsync({ fields: ["Input"] });
const records = query.records.filter((r) => r.getCellValueAsString("Input").trim());

for (let i = 0; i < records.length; i += 50) {
  const chunk = records.slice(i, i + 50);
  const res = await fetch("https://api.propertiesapi.com/v1/zillow/batch", {
    method: "POST",
    headers: { "x-api-key": KEY, "content-type": "application/json" },
    body: JSON.stringify({ items: chunk.map((r) => r.getCellValueAsString("Input").trim()) }),
  });
  const body = await res.json();
  if (!res.ok) throw new Error(`${res.status} ${body.error?.code}: ${body.error?.message}`);

  const updates = body.data.map((item) => {
    const id = chunk[item.index].id;
    if (!item.ok) return { id, fields: { "Lookup error": item.error.code } };
    const d = item.data;
    return {
      id,
      fields: {
        "Price": d.price, "Zestimate": d.zestimate, "Rent Zestimate": d.rentZestimate,
        "Status": d.homeStatus, "Zillow URL": d.detailUrl, "Lookup error": null,
      },
    };
  });
  while (updates.length) await table.updateRecordsAsync(updates.splice(0, 50));
  output.text(`${i + chunk.length} of ${records.length} done, ${body.meta.credits} credits used`);
}

Review what needs a person

Filter the view on Lookup error. address_ambiguous means Zillow's closest match is a different home: paste the right Zillow link into Input and run again. not_found means no Zillow property matched.

Common values in Lookup error
not_found            no matching Zillow property: check the address or paste the Zillow link
address_ambiguous    closest match is a different home: add the unit, city or ZIP, or paste the link
bad_param            the Input isn't a Zillow link or a full US address with a house number
rate_limited         too many requests a minute: run the script again shortly
upstream_busy        lookups are busy: run the script again shortly

Airtable gotchas

  • Store the Zillow URL the script writes back and switch Input to it for future runs. Links are the most precise input and skip the address match.
  • A blank Zestimate cell means Zillow doesn't show one for that home. Airtable rollups treat blanks differently from zero, which is what you want.
  • Anyone who can see the script can see the key. Use a key for this base only, and revoke it from your dashboard if the base is shared more widely.
  • Airtable's own update call takes a limited number of records at a time, which is why the script writes results back in slices.

Zillow API and Airtable: questions

Can this run automatically when a record is added?+

Yes, with an automation that runs a script for the new record and calls GET /v1/zillow/property for it. Keep the batch script above for refreshing the whole table.

Is there an Airtable app or sync for Zillow data?+

Not from us. The script uses Airtable's built-in scripting, so there is nothing else to install.

Does rerunning the script cost credits again?+

Repeat lookups of the same home within 24 hours come from our cache and are free. After that, each successful live lookup is billed again. Zillow links and addresses cost the same: 1 credit per successful lookup.

Can I get owner names or contact details?+

No. PropertiesAPI returns what the public Zillow page shows, such as the listing agent and broker, not owner or skip-trace data.

Make your first call from Airtable

50 free lookups, no card, no approval.

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