Zillow API with curl
Look up Zillow property and listing data from a terminal: one curl command per home, jq to pick fields, and a short shell function that retries the right errors.
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 curl fits
curl is the fastest way to see what the API returns before you write any application code. Every example on this page is a plain HTTPS request with one header, so you can paste it into a terminal, a CI job, a cron script or a support ticket and get the same JSON your app will get.
The pattern is always the same: GET /v1/zillow/property with exactly one of url, zpid or address, and the x-api-key header. Use -G with --data-urlencode so curl encodes the Zillow link or the address for you; a raw address with spaces and commas in a query string is the most common reason a first request fails.
A live lookup takes typically 8 seconds, up to about 20 seconds, so give curl a --max-time well above that. Repeat lookups of the same home within 24 hours come from our cache and are free.
Keep the key in an environment variable
Every command below reads the key from PROPERTIESAPI_KEY, so it never lands in your shell history or a script you commit.
export PROPERTIESAPI_KEY="your_key_here"
BASE="https://api.propertiesapi.com/v1"Look up one home by its Zillow link
Paste any zillow.com/homedetails link. The body is { data, meta }: data is the property, meta says whether it was a cache hit and how many credits it used.
curl -sG "$BASE/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/" \
--max-time 120Look up by address and keep only the fields you need
Send address instead of url and we find the matching Zillow property first. jq trims the response to a readable summary; calculated figures such as gross yield live under data.calculated.
curl -sG "$BASE/zillow/property" \
-H "x-api-key: $PROPERTIESAPI_KEY" \
--data-urlencode "address=2640 Steiner St, San Francisco, CA 94115" \
--max-time 120 \
| jq '.data | {address, homeStatus, price, zestimate, rentZestimate, beds, baths, livingArea,
gross_yield_pct: .calculated.gross_yield_pct}'Read the cache and credit headers
-D writes the response headers to a file. x-cache says HIT for a free cache hit and MISS for a live lookup; x-credits-remaining is what your account has left.
curl -sG "$BASE/zillow/property" \
-H "x-api-key: $PROPERTIESAPI_KEY" \
--data-urlencode "address=2640 Steiner St, San Francisco, CA 94115" \
--max-time 120 -D headers.txt -o home.json
grep -iE '^(x-cache|x-credits-remaining|x-ratelimit-remaining):' headers.txt
jq '.meta | {credits, cached, fetched_at}' home.jsonA lookup function that retries the right errors
Errors come back as { error: { code, message, details } }. Retry rate limits and busy answers after the retry-after header; don't retry not_found or a bad input, because the answer won't change. Failed lookups aren't billed.
lookup() { # usage: lookup "address=..." or lookup "url=https://www.zillow.com/homedetails/..."
local h b status wait
h=$(mktemp); b=$(mktemp)
for attempt in 1 2 3 4; do
status=$(curl -sG "$BASE/zillow/property" -H "x-api-key: $PROPERTIESAPI_KEY" \
--data-urlencode "$1" --max-time 120 -D "$h" -o "$b" -w '%{http_code}') || { sleep 2; continue; }
case "$status" in
200) jq '.data' "$b"; rm -f "$h" "$b"; return 0 ;;
404) echo "no Zillow property matches (not billed)" >&2; break ;;
409) jq -r '"closest match is a different home: " + (.error.details.candidate.detailUrl // "none")' "$b" >&2; break ;;
429|502|503|504)
wait=$(grep -i '^retry-after:' "$h" | tr -dc '0-9')
sleep "${wait:-$((2 ** attempt))}" ;;
*) jq -r '.error.code + ": " + .error.message' "$b" >&2; break ;;
esac
done
rm -f "$h" "$b"; return 1
}
lookup "address=2640 Steiner St, San Francisco, CA 94115" | jq '{address, price, zestimate}'Batch a text file of addresses or links
POST /v1/zillow/batch takes up to 50 items per request. jq turns a file with one address or Zillow link per line into the request body, and splits the answer into found and failed rows. A full batch can take a few minutes, so raise --max-time.
# homes.txt: one address or zillow.com link per line
jq -R -s -c 'split("\n") | map(select(length > 0)) | .[:50] | {items: .}' homes.txt \
| curl -s "$BASE/zillow/batch" \
-H "x-api-key: $PROPERTIESAPI_KEY" \
-H "content-type: application/json" \
--max-time 320 -d @- > batch.json
jq -r '.data[] | select(.ok) | [.index, .data.address, .data.homeStatus, .data.price, .data.zestimate] | @tsv' batch.json
jq -r '.data[] | select(.ok | not) | "item \(.index): \(.error.code)"' batch.json
jq '.meta | {count, succeeded, failed, cache_hits, credits}' batch.jsoncurl gotchas
- Without -G, curl sends --data-urlencode as a POST body and the property endpoint answers with missing_param. Keep -G on every property call.
- Quote the whole url=... argument. An unquoted Zillow link or address breaks at the first space or ampersand.
- jq prints null for missing fields. That is the API telling you Zillow doesn't show the value, not that it is zero.
- Set a client timeout of at least 120 seconds: an occasional lookup takes longer.
Zillow API and curl: questions
Do I need an SDK to use the Zillow API from the command line?+
No. The API is plain HTTPS and JSON. curl sends the request and jq reads the answer; nothing else is required.
Can I pass the API key as a query parameter?+
No. The REST API reads the key from the x-api-key header only, which also keeps it out of server logs and shell history when you use an environment variable.
How do I tell a cache hit from a live lookup in curl?+
Read the x-cache response header (HIT or MISS) or meta.cached in the body. Repeat lookups of the same home within 24 hours come from our cache and are free.
What does a lookup cost?+
Zillow links and addresses cost the same: 1 credit per successful lookup. Failed lookups and cache hits cost nothing. You start with 50 free lookups.
Make your first call from curl
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.