Build a project

Enrich a Property Address List with Python and Export to CSV

Turn an address spreadsheet into property data with a downloadable Python script. Keep prices, Zillow estimates, collection times, and every failed row.

By PropertiesAPI5 min read

From an address list to a useful research file

Start with the properties you already want to research: a saved list, an internal spreadsheet, or addresses supplied by your customers. This guide turns that list into a CSV with returned addresses, listing status, prices, Zillow estimates, and collection times. It also saves a JSON snapshot that the dashboard and rent-comparison guides can reuse.

The API supplies JSON. The Python program below creates the files on your machine. It looks up known properties; it does not search a neighborhood for new listings, identify owners, or select comparable homes. Keep your input list so you can check which property each response actually describes.

Prepare the address spreadsheet

Save your spreadsheet as addresses.csv with id and address headers. Give each row a unique local ID and include the full street address, unit when applicable, city, state, and ZIP. The ID joins the returned data back to your original records even when a lookup fails.

The sample below is an input-format illustration, not a verified property. Replace it with an address you intend to look up. The script validates missing IDs, duplicate IDs, and empty addresses before making any requests. It keeps ZIP codes inside text fields so leading zeros survive the export.

addresses.csv, replace the illustrative address
id,address
property-a,"1600 Main St, Austin, TX 78701"

Install the client and run the export

Download enrich_properties.py into your working directory. Use a supported Python release and install requests in a virtual environment. Get an API key through the quickstart, then set PROPERTIESAPI_KEY in your environment. The hidden prompt below keeps your key out of shell history; do not paste it into the script.

The program sends sequential property requests with explicit timeouts. It does not retry automatically. Start with a small list and check your account allowance before processing more addresses. The output directory is overwritten when you reuse its name, so choose a new directory when you want to retain an earlier snapshot.

Bash terminal on macOS or Linux
python3 -m venv .venv
source .venv/bin/activate
python -m pip install requests
read -rsp "PropertiesAPI key: " PROPERTIESAPI_KEY; echo
export PROPERTIESAPI_KEY
python enrich_properties.py addresses.csv --output-dir output

Understand the request before running a larger file

The request below is the core of the downloadable program. requests encodes the address as a query parameter, and the key travels in a header. Redirects are disabled so the client will not forward that header to an unexpected destination. The complete file adds input validation, response checks, row accounting, and exports.

An API success is not the same as a verified investment input. The script preserves the requested and returned addresses separately and raises review_required when the response contains an identity warning or lacks a returned identifier or address. Review units and listing status before using the file.

Core request; download the complete program above
response = session.get(
    "https://api.propertiesapi.com/v1/zillow/property",
    params={"address": source["address"]},
    timeout=(10, 140),
    allow_redirects=False,
)
body = response.json()
data, meta = body["data"], body["meta"]
# data contains property fields; meta contains collection and credit information.

Read the output without confusing missing values and prices

properties.csv has a row for every submitted address. properties.json contains the same results with native nulls, booleans, and an export timestamp. Empty numeric cells in the CSV mean unavailable, not zero. The JSON snapshot preserves the distinction for later calculations.

The script guards text cells that spreadsheet software could interpret as formulas. Numeric cells stay numeric. When opening the CSV, import identifiers and ZIP-related fields as text. Use the JSON version if you need the original text without the spreadsheet safety prefix.

ColumnsHow to use them
input_id, input_address, address, unitJoin back to the source row and inspect property identity.
home_status, currency, priceInterpret price using listing status. A rental price is monthly asking rent.
zestimate, rent_zestimateZillow's estimates when available; neither is a completed transaction.
fetched_at, cachedWhen the source was collected and whether this request reused a cached result.
status, error_code, review_requiredSeparate usable responses, review cases, failures, and unrequested rows.
creditsThe credits reported for that successful response, not an inferred charge from row count.

Keep failed and unrequested rows visible

An unmatched or ambiguous address stays in the file with its error code. Authentication failures, exhausted credits, rate limits, and server failures stop further calls in this simple client. Remaining rows are marked not_requested. Correct the cause or wait as instructed by the API, then make a smaller input file containing only the rows you want to try again.

A network failure is marked uncertain because the client cannot establish whether the server completed a lookup. The script stops further calls and does not assume that replaying the request is free. Reconcile account usage before retrying uncertain rows. A nonzero process exit status tells an automated job that the export contains failures or review flags; the files are still saved.

This program is a small sequential workflow, not a resumable job runner. An interrupted process may not save its in-memory progress. Use small inputs first. For larger imports, add durable checkpoints and use the batch guide to preserve item-level outcomes.

Use the snapshot in a dashboard or rental worksheet

Once you have checked the returned properties, use properties.json as the input to the local dashboard or rent-comparison report. Those programs read the saved data and make no additional API requests. Export time is separate from fetched_at, so generating a new spreadsheet does not imply that each property was collected again.

Validation scope: the downloadable client is tested against a local HTTP fixture for successful responses, missing fields, identity warnings, ambiguous addresses, account failures, and transport errors. Its request and field names were checked against the published API contract. These checks are not a live coverage or accuracy benchmark.

Sources and documentation

Product details checked against the linked documentation on October 21, 2026. Code and sample inputs are illustrative unless stated otherwise.

Written by PropertiesAPI, an independent property data service. We are not affiliated with Zillow. Source data may be incomplete or change over time.