Skip to main content

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

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/

Release files for zip-codes-api 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zip-codes-api 0.1.0
File Size Uploaded
zip_codes_api-0.1.0.tar.gz 10.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for zip-codes-api 0.1.0
File Interpreter ABI Platform
zip_codes_api-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 20.1 kB

Release files / zip_codes_api-0.1.0.tar.gz

Download URL zip_codes_api-0.1.0.tar.gz
Size 10.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1176d357b988a2c3a431c918cafb9f2aa50c47882577efaaf6e69d3b54eb2c5d
BLAKE2b-256 checksum
How to use checksums
c82ebfbfd7e9a04101a26649bd8e9e9b8c015fd6eb3092b8df0ec2251bc135fb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release files / zip_codes_api-0.1.0-py3-none-any.whl

Download URL zip_codes_api-0.1.0-py3-none-any.whl
Size 10.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5cedff75d699ab0db532963e796258092fc68f964000c064bf08dc1e9c45c9fa
BLAKE2b-256 checksum
How to use checksums
e6fa0fca6ca7df7972039f5e64820c4b2c3211980981074cd95c70726d47978d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page