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.
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 textPaste 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.
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.
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 shortlyAirtable 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.