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.
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.
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.
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 outputUnderstand 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.
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.
| Columns | How to use them |
|---|---|
| input_id, input_address, address, unit | Join back to the source row and inspect property identity. |
| home_status, currency, price | Interpret price using listing status. A rental price is monthly asking rent. |
| zestimate, rent_zestimate | Zillow's estimates when available; neither is a completed transaction. |
| fetched_at, cached | When the source was collected and whether this request reused a cached result. |
| status, error_code, review_required | Separate usable responses, review cases, failures, and unrequested rows. |
| credits | The 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.
- Property endpoint and response contract
- Python CSV library
- Requests timeouts
- Spreadsheet formula injection
Written by PropertiesAPI, an independent property data service. We are not affiliated with Zillow. Source data may be incomplete or change over time.