Python client for the ZIP Codes API: US ZIP and Canadian postal data with 14 years of US Census ACS demographics, radius search, address validation, and distance.
Project description
zip-codes-api
Python client for the ZIP Codes API — US ZIP and Canadian postal data with 14 years of US Census ACS demographics (2011–2024), radius search (centroid + spatial coverage-weighting), address validation with ZIP+4, distance, and typo-tolerant autocomplete.
pip install zip-codes-api # core
pip install 'zip-codes-api[pandas]' # + DataFrame helpers for research
Quickstart
from zip_codes_api import ZipCodesClient
# Public demo key works for demo ZIPs (90210, 10001, ...). Any ZIP: get a free
# key at https://www.zip-codes.com/api/signup (2,500 credits/day, no card).
client = ZipCodesClient("zc_test_DEMOAPIKEY000000000000")
bh = client.zip("90210", include=["acs_demographic", "timezone"])
print(bh["city"]) # Beverly Hills
print(client.last_meta["credits"]["used"]) # credits this call cost
Single-target methods (zip, quick_zip, radius, distance, address, suggest)
return the first result object. Batch methods return the list of per-item results.
Pass raw=True for the full response envelope. client.last_meta always holds the
most recent response's meta (including credits).
14 years of demographics as a DataFrame
The reason most researchers reach for this API — a longitudinal ZIP-level series in one
call, with the year-to-year Census variable drift and the 2020 GEO_ID change already
normalized:
df = client.acs_timeseries("90210", profile="demographic", years=range(2011, 2025))
print(df[["sex_and_age.total_population", "sex_and_age.median_age"]])
# sex_and_age.total_population sex_and_age.median_age
# year
# 2011 21719 45.7
# ...
# 2024 19004 51.9
profile is one of demographic (DP05), social (DP02), economic (DP03),
housing (DP04).
Coverage-weighted radius aggregation (no GIS)
/radius in spatial mode intersects your radius with actual ZIP/FSA boundary polygons
and weights the ACS aggregate by each ZIP's pct_inside — a ZIP 30% inside contributes
30% of its population, not all-or-nothing:
r = client.radius("90210", max_radius=10, mode="spatial", include="acs_demographic")
pop = r["stats"]["acs"]["current"]["demographic"]["sex_and_age"]["total_population"]["est"]
print(f"{pop:,} people within 10 miles (coverage-weighted)")
matches = client.radius_dataframe("90210", max_radius=10, mode="spatial") # pandas
print(matches[["code", "city", "pct_inside", "distance_miles"]].head())
Other endpoints
client.quick_zip("M5V") # Canadian FSA: city/province/coords
client.distance("90210", "10001") # great-circle distance + bearing
client.address("200 N Spring St, Los Angeles, CA 90012") # validate + ZIP+4
client.suggest("9021") # autocomplete -> result["matches"]
# Batch (up to 100; requires a paid subscription key)
client.zip_batch(["90210", "10001", "M5V"], include="timezone")
Errors
Failures raise typed exceptions carrying the API's code, status, and request_id:
from zip_codes_api import InsufficientCreditsError, RateLimitError, NotFoundError
try:
client.zip("90210", include=["acs_economic"])
except RateLimitError as e:
print("retry after", e.retry_after, "seconds")
except InsufficientCreditsError:
...
except NotFoundError:
...
ZipCodesClient retries 429 / 5xx automatically (honoring Retry-After), up to
max_retries (default 2).
Links
- API docs: https://www.zip-codes.com/api/docs
- Get a free key: https://www.zip-codes.com/api/signup
- Sample data + notebooks: https://github.com/ZIP-Codes-API/acs-by-zip
- Research/journalism/nonprofit credits: https://www.zip-codes.com/api/research-credits
License
MIT. Underlying demographic data is US Census Bureau ACS (public domain). Suggested acknowledgement:
Demographic data: US Census Bureau ACS 5-Year Estimates, accessed via ZIP Codes API (Zip-Codes.com), https://www.zip-codes.com/api/
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zip_codes_api-0.1.0.tar.gz.
File metadata
- Download URL: zip_codes_api-0.1.0.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1176d357b988a2c3a431c918cafb9f2aa50c47882577efaaf6e69d3b54eb2c5d
|
|
| MD5 |
c2927b27acdd037b5bab3a120fd43d37
|
|
| BLAKE2b-256 |
c82ebfbfd7e9a04101a26649bd8e9e9b8c015fd6eb3092b8df0ec2251bc135fb
|
File details
Details for the file zip_codes_api-0.1.0-py3-none-any.whl.
File metadata
- Download URL: zip_codes_api-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cedff75d699ab0db532963e796258092fc68f964000c064bf08dc1e9c45c9fa
|
|
| MD5 |
61dd4abf5caf82746d184e2158d21fb2
|
|
| BLAKE2b-256 |
e6fa0fca6ca7df7972039f5e64820c4b2c3211980981074cd95c70726d47978d
|