Every ZIP code in the United States, with weather, radar, trivia and the numbers behind it. Five digits since 1963!

ZIP stands for Zone Improvement Plan. The codes went live on July 1, 1963.The lowest ZIP code is 00501 — the IRS in Holtsville, New York.The highest ZIP code is 99950, in Ketchikan, Alaska.Type 07734 into a calculator and turn it upside down: hELLO. It is Keansburg, New Jersey.12345 belongs to one company: General Electric in Schenectady, New York.The first digit is a region: 0 is New England and New Jersey, 9 is the West Coast, Alaska and Hawaii.Mr. ZIP, the cartoon mailman, was the mascot that sold the idea to America.ZIP+4 arrived in 1983 and can narrow a ZIP down to one side of one block.A ZIP code is a mail route, not a place: plenty of them cross county and even state lines.Play ZIP Hunt: guess the secret ZIP code of the day in six tries.
zipcodes.pro — API/DOCS

ZIP code API reference

A JSON REST API for 41,711 US ZIP codes. Base URL https://zipcodes.pro, every endpoint under /v1, a key in the Authorization header. The responses below are what the API returned when this page was generated, from data release 2026-10-22.

Contents

Quick start

  1. Get a free key below. It is shown once, on the next page.
  2. Send it as a bearer token: Authorization: Bearer zk_live_…
  3. Call any endpoint. Free keys include 1,000 requests a day.

Get a free API key

1,000 requests a day, free · no card · the key appears on the next page

Authentication

Every /v1 endpoint needs a key, sent as Authorization: Bearer YOUR_API_KEY. A ?key= query parameter is also accepted for cases where a header cannot be set, but it ends up in logs and browser history, so prefer the header. Keys start zk_live_. Only a hash of each key is stored: a lost key cannot be recovered, only replaced. CORS is open on the free plan, so a key works from browser code.

Look up a ZIP code

GET /v1/zip/{zip}

Everything about one ZIP code: USPS city, other place names, state, every county it touches with a weight, coordinates, time zone, metro area, census demographics, business counts, IRS figures and the nearest ZIP codes. ZIP+4 input is accepted and cut to five digits.

ParameterMeaning
zip
path, required
Five digit ZIP code, or ZIP+4 (95014-2083).
curl "https://zipcodes.pro/v1/zip/95014" \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://zipcodes.pro/v1/zip/95014", {
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
if (!res.ok) throw new Error((await res.json()).message);
const data = await res.json();
import requests

r = requests.get(
    "https://zipcodes.pro/v1/zip/95014",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Response 200

{
  "zip": "95014",
  "type": "standard",
  "type_source": "inferred",
  "city": "Cupertino",
  "other_place_names": [
    "San Jose",
    "Sunnyvale"
  ],
  "state": "CA",
  "state_name": "California",
  "county": {
    "fips": "06085",
    "name": "Santa Clara County",
    "short_name": "Santa Clara"
  },
  "counties": [
    {
      "county_fips": "06085",
      "name": "Santa Clara County",
      "short_name": "Santa Clara",
      "weight": 1,
      "basis": "land_area"
    }
  ],
  "location": {
    "lat": 37.308354,
    "lng": -122.081882,
    "source": "gazetteer_internal_point",
    "timezone": "America/Los_Angeles"
  },
  "is_zcta": true,
  "parent_zcta": null,
  "metro": {
    "cbsa_code": "41940",
    "name": "San Jose-Sunnyvale-Santa Clara, CA",
    "type": "metro",
    "csa_code": "488",
    "csa_name": "San Jose-San Francisco-Oakland, CA"
  },
  "demographics": {
    "population": 60932,
    "households": 21868,
    "housing_units": 23104,
    "median_age": 41,
    "median_household_income": 230913,
    "median_home_value": 2000001,
    "median_rent": 3501,
    "pct_bachelors_plus": 81.9,
    "mean_commute_min": 23.7,
    "density_per_sqmi": 2451
  },
  "business": {
    "establishments": 1615,
    "employees": 59243,
    "annual_payroll_thousands": 22133258
  },
  "tax": {
    "irs_returns": 27000,
    "irs_agi_thousands": 8673961
  },
  "area": {
    "land_sqmi": 24.86,
    "water_sqmi": 0.131
  },
  "nearest_zips": [
    {
      "zip": "95015",
      "miles": 1.9,
      "city": "Cupertino",
      "state": "CA"
    },
    {
      "zip": "94024",
      "miles": 3,
      "city": "Los Altos",
      "state": "CA"
    },
    {
      "zip": "94087",
      "miles": 3.9,
      "city": "Sunnyvale",
      "state": "CA"
    },
    "… 7 more"
  ],
  "release": "2026-10-22"
}

ZIP codes for a city

GET /v1/zips

Every ZIP code whose USPS city or other place names match, in one state.

ParameterMeaning
city
query, required
City name, any case: Cupertino.
state
query, required
Two letter state code: CA.
curl "https://zipcodes.pro/v1/zips?city=Cupertino&state=CA" \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://zipcodes.pro/v1/zips?city=Cupertino&state=CA", {
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
if (!res.ok) throw new Error((await res.json()).message);
const data = await res.json();
import requests

r = requests.get(
    "https://zipcodes.pro/v1/zips",
    params={"city": "Cupertino", "state": "CA"},
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Response 200

{
  "city": "Cupertino",
  "state": "CA",
  "count": 2,
  "zips": [
    {
      "zip": "95014",
      "type": "standard",
      "usps_city": "Cupertino",
      "state": "CA",
      "county_fips": "06085",
      "timezone": "America/Los_Angeles",
      "lat": 37.308354,
      "lng": -122.081882,
      "population": 60932,
      "median_household_income": 230913,
      "median_home_value": 2000001,
      "land_sqmi": 24.86,
      "density_per_sqmi": 2451
    },
    {
      "zip": "95015",
      "type": "unknown",
      "usps_city": "Cupertino",
      "state": "CA",
      "county_fips": "06085",
      "timezone": "America/Los_Angeles",
      "lat": 37.323,
      "lng": -122.0527,
      "population": null,
      "median_household_income": null,
      "median_home_value": null,
      "land_sqmi": null,
      "density_per_sqmi": null
    }
  ]
}

ZIP codes within a radius

GET /v1/radius

Every ZIP code whose centre point is within the radius, nearest first, each with its distance in miles. Measure from a ZIP code or from any coordinate.

ParameterMeaning
zip
query, optional
Centre ZIP code. Either this, or lat and lng.
lat
query, optional
Centre latitude, −90 to 90.
lng
query, optional
Centre longitude, −180 to 180.
miles
query, optional
Radius in miles, above 0 and up to 500. Default 10.
curl "https://zipcodes.pro/v1/radius?zip=95014&miles=5" \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://zipcodes.pro/v1/radius?zip=95014&miles=5", {
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
if (!res.ok) throw new Error((await res.json()).message);
const data = await res.json();
import requests

r = requests.get(
    "https://zipcodes.pro/v1/radius",
    params={"zip": "95014", "miles": "5"},
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Response 200

{
  "origin": {
    "zip": "95014",
    "lat": 37.308354,
    "lng": -122.081882
  },
  "miles": 5,
  "count": 11,
  "zips": [
    {
      "zip": "95014",
      "type": "standard",
      "usps_city": "Cupertino",
      "state": "CA",
      "county_fips": "06085",
      "timezone": "America/Los_Angeles",
      "lat": 37.308354,
      "lng": -122.081882,
      "population": 60932,
      "median_household_income": 230913,
      "median_home_value": 2000001,
      "land_sqmi": 24.86,
      "density_per_sqmi": 2451,
      "miles": 0
    },
    {
      "zip": "95015",
      "type": "unknown",
      "usps_city": "Cupertino",
      "state": "CA",
      "county_fips": "06085",
      "timezone": "America/Los_Angeles",
      "lat": 37.323,
      "lng": -122.0527,
      "population": null,
      "median_household_income": null,
      "median_home_value": null,
      "land_sqmi": null,
      "density_per_sqmi": null,
      "miles": 1.896
    },
    {
      "zip": "94024",
      "type": "standard",
      "usps_city": "Los Altos",
      "state": "CA",
      "county_fips": "06085",
      "timezone": "America/Los_Angeles",
      "lat": 37.350388,
      "lng": -122.098686,
      "population": 23051,
      "median_household_income": 250001,
      "median_home_value": 2000001,
      "land_sqmi": 8.273,
      "density_per_sqmi": 2786.3,
      "miles": 3.047
    },
    "… 8 more"
  ]
}

Distance between two ZIP codes

GET /v1/distance

Great-circle distance in miles and kilometres between the two ZIP codes' published centre points, with each end's city, state and coordinates.

ParameterMeaning
from
query, required
Five digit ZIP code.
to
query, required
Five digit ZIP code.
curl "https://zipcodes.pro/v1/distance?from=95014&to=10001" \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://zipcodes.pro/v1/distance?from=95014&to=10001", {
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
if (!res.ok) throw new Error((await res.json()).message);
const data = await res.json();
import requests

r = requests.get(
    "https://zipcodes.pro/v1/distance",
    params={"from": "95014", "to": "10001"},
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Response 200

{
  "from": {
    "zip": "95014",
    "city": "Cupertino",
    "state": "CA",
    "lat": 37.308354,
    "lng": -122.081882
  },
  "to": {
    "zip": "10001",
    "city": "New York",
    "state": "NY",
    "lat": 40.750649,
    "lng": -73.997298
  },
  "miles": 2559.524,
  "kilometers": 4119.155,
  "method": "great-circle distance between the ZIP codes' published centre points"
}

ZIP codes in a county

GET /v1/county/{fips}/zips

Every ZIP code in a county, by five digit county FIPS code (state FIPS + county FIPS).

ParameterMeaning
fips
path, required
Five digit county FIPS code: 06085 is Santa Clara County, CA.
curl "https://zipcodes.pro/v1/county/06085/zips" \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://zipcodes.pro/v1/county/06085/zips", {
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
if (!res.ok) throw new Error((await res.json()).message);
const data = await res.json();
import requests

r = requests.get(
    "https://zipcodes.pro/v1/county/06085/zips",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Response 200

{
  "county_fips": "06085",
  "count": 109,
  "zips": [
    {
      "zip": "94022",
      "type": "standard",
      "usps_city": "Los Altos",
      "state": "CA",
      "county_fips": "06085",
      "timezone": "America/Los_Angeles",
      "lat": 37.35536,
      "lng": -122.144935,
      "population": 20027,
      "median_household_income": 250001,
      "median_home_value": 2000001,
      "land_sqmi": 17.689,
      "density_per_sqmi": 1132.2
    },
    {
      "zip": "94023",
      "type": "unknown",
      "usps_city": "Los Altos",
      "state": "CA",
      "county_fips": "06085",
      "timezone": "America/Los_Angeles",
      "lat": 37.3852,
      "lng": -122.1141,
      "population": null,
      "median_household_income": null,
      "median_home_value": null,
      "land_sqmi": null,
      "density_per_sqmi": null
    },
    {
      "zip": "94024",
      "type": "standard",
      "usps_city": "Los Altos",
      "state": "CA",
      "county_fips": "06085",
      "timezone": "America/Los_Angeles",
      "lat": 37.350388,
      "lng": -122.098686,
      "population": 23051,
      "median_household_income": 250001,
      "median_home_value": 2000001,
      "land_sqmi": 8.273,
      "density_per_sqmi": 2786.3
    },
    "… 106 more"
  ]
}

Bulk lookup

POST /v1/bulk

Many ZIP codes in one request (100 on Free, 1,000 on paid plans). Results come back in the order you sent them, with null for a ZIP code that does not exist, and lists of what was not found or not valid.

ParameterMeaning
zips
body, required
JSON array of ZIP code strings: {"zips": ["95014", "10001"]}.
curl -X POST "https://zipcodes.pro/v1/bulk" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"zips":["95014","10001","99999"]}'
const res = await fetch("https://zipcodes.pro/v1/bulk", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"zips":["95014","10001","99999"]}),
});
const data = await res.json();
import requests

r = requests.post(
    "https://zipcodes.pro/v1/bulk",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={"zips":["95014","10001","99999"]},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Response 200

{
  "requested": 3,
  "found": 2,
  "not_found": [
    "99999"
  ],
  "invalid": [],
  "results": [
    {
      "zip": "95014",
      "type": "standard",
      "type_source": "inferred",
      "city": "Cupertino",
      "other_place_names": [
        "San Jose",
        "Sunnyvale"
      ],
      "state": "CA",
      "state_name": null,
      "county": null,
      "counties": [
        {
          "county_fips": "06085",
          "name": "Santa Clara County",
          "short_name": "Santa Clara",
          "weight": 1,
          "basis": "land_area"
        }
      ],
      "location": {
        "lat": 37.308354,
        "lng": -122.081882,
        "source": "gazetteer_internal_point",
        "timezone": "America/Los_Angeles"
      },
      "is_zcta": true,
      "parent_zcta": null,
      "metro": {
        "cbsa_code": "41940",
        "name": "San Jose-Sunnyvale-Santa Clara, CA",
        "type": "metro",
        "csa_code": "488",
        "csa_name": "San Jose-San Francisco-Oakland, CA"
      },
      "demographics": {
        "population": 60932,
        "households": 21868,
        "housing_units": 23104,
        "median_age": 41,
        "median_household_income": 230913,
        "median_home_value": 2000001,
        "median_rent": 3501,
        "pct_bachelors_plus": 81.9,
        "mean_commute_min": 23.7,
        "density_per_sqmi": 2451
      },
      "business": {
        "establishments": 1615,
        "employees": 59243,
        "annual_payroll_thousands": 22133258
      },
      "tax": {
        "irs_returns": 27000,
        "irs_agi_thousands": 8673961
      },
      "area": {
        "land_sqmi": 24.86,
        "water_sqmi": 0.131
      },
      "nearest_zips": [
        {
          "zip": "95015",
          "miles": 1.9,
          "city": "Cupertino",
          "state": "CA"
        },
        {
          "zip": "94024",
          "miles": 3,
          "city": "Los Altos",
          "state": "CA"
        },
        {
          "zip": "94087",
          "miles": 3.9,
          "city": "Sunnyvale",
          "state": "CA"
        },
        "… 7 more"
      ],
      "release": "2026-10-22"
    },
    {
      "zip": "10001",
      "type": "standard",
      "type_source": "inferred",
      "city": "New York",
      "other_place_names": [],
      "state": "NY",
      "state_name": null,
      "county": null,
      "counties": [
        {
          "county_fips": "36061",
          "name": "New York County",
          "short_name": "New York",
          "weight": 1,
          "basis": "land_area"
        }
      ],
      "location": {
        "lat": 40.750649,
        "lng": -73.997298,
        "source": "gazetteer_internal_point",
        "timezone": "America/New_York"
      },
      "is_zcta": true,
      "parent_zcta": null,
      "metro": {
        "cbsa_code": "35620",
        "name": "New York-Newark-Jersey City, NY-NJ",
        "type": "metro",
        "csa_code": "408",
        "csa_name": "New York-Newark, NY-NJ-CT-PA"
      },
      "demographics": {
        "population": 30511,
        "households": 15737,
        "housing_units": 18356,
        "median_age": 35.8,
        "median_household_income": 129852,
        "median_home_value": 561100,
        "median_rent": 3361,
        "pct_bachelors_plus": 72.6,
        "mean_commute_min": 26,
        "density_per_sqmi": 48895.8
      },
      "business": {
        "establishments": 6325,
        "employees": 173194,
        "annual_payroll_thousands": 21557555
      },
      "tax": {
        "irs_returns": 16960,
        "irs_agi_thousands": 4479865
      },
      "area": {
        "land_sqmi": 0.624,
        "water_sqmi": 0
      },
      "nearest_zips": [
        {
          "zip": "10199",
          "miles": 0.1,
          "city": "New York",
          "state": "NY"
        },
        {
          "zip": "10119",
          "miles": 0.2,
          "city": "New York",
          "state": "NY"
        },
        {
          "zip": "10122",
          "miles": 0.3,
          "city": "New York",
          "state": "NY"
        },
        "… 7 more"
      ],
      "release": "2026-10-22"
    },
    null
  ]
}

Release and sources

GET /v1/meta

The data release the API is serving, every source with its vintage and licence, and field coverage.

curl "https://zipcodes.pro/v1/meta" \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://zipcodes.pro/v1/meta", {
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
if (!res.ok) throw new Error((await res.json()).message);
const data = await res.json();
import requests

r = requests.get(
    "https://zipcodes.pro/v1/meta",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Response 200

{
  "release": {
    "release": "2026-10-22",
    "built_at": "2026-10-22T16:19:31+00:00",
    "zip_count": 41711,
    "zcta_count": 33791,
    "added": 0,
    "retired": 0,
    "modified": 0,
    "notes": null
  },
  "sources": [
    {
      "key": "gazetteer_county_2020",
      "name": "Census 2020 Gazetteer county file",
      "url": "https://www2.census.gov/geo/docs/maps-data/data/gazetteer/2020_Gazetteer/2020_Gaz_counties_national.zip",
      "license": "Public domain (U.S. Census Bureau)",
      "attribution": "U.S. Census Bureau, Gazetteer Files",
      "vintage": "2020 Gazetteer",
      "retrieved_at": "2026-10-22"
    },
    {
      "key": "zcta_county_rel",
      "name": "Census 2020 ZCTA-to-County relationship file",
      "url": "https://www2.census.gov/geo/docs/maps-data/data/rel2020/zcta520/tab20_zcta520_county20_natl.txt",
      "license": "Public domain (U.S. Census Bureau)",
      "attribution": "U.S. Census Bureau, 2020 ZCTA to County Relationship File",
      "vintage": "2020 relationship file",
      "retrieved_at": "2026-10-22"
    },
    {
      "key": "zcta_place_rel",
      "name": "Census 2020 ZCTA-to-Place relationship file",
      "url": "https://www2.census.gov/geo/docs/maps-data/data/rel2020/zcta520/tab20_zcta520_place20_natl.txt",
      "license": "Public domain (U.S. Census Bureau)",
      "attribution": "U.S. Census Bureau, 2020 ZCTA to Place Relationship File",
      "vintage": "2020 relationship file",
      "retrieved_at": "2026-10-22"
    },
    "… 22 more"
  ],
  "coverage": [
    {
      "field": "cbsa_code",
      "populated": 31568,
      "total": 41711,
      "gap_reason": "A ZIP outside any metro or micro area has none, which is normal."
    },
    {
      "field": "county_fips",
      "populated": 41171,
      "total": 41711,
      "gap_reason": "Military and some territory ZIPs have no county."
    },
    {
      "field": "employees",
      "populated": 34944,
      "total": 41711,
      "gap_reason": "CBP withholds employment where it would disclose a single firm."
    },
    "… 8 more"
  ],
  "note": "A null value means the source did not publish that figure. It never means zero."
}

Your usage

GET /v1/usage

Your plan, requests used and refused in the current quota window, and requests per day this month. Counts as a request.

curl "https://zipcodes.pro/v1/usage" \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://zipcodes.pro/v1/usage", {
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
if (!res.ok) throw new Error((await res.json()).message);
const data = await res.json();
import requests

r = requests.get(
    "https://zipcodes.pro/v1/usage",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Limits and plans

PlanRequestsWindowPer minutePrice
Free 1,000 per day, reset 00:00 UTC 60 Free
Starter 100,000 per calendar month 120 $19/mo, not on sale yet
Pro 500,000 per calendar month 600 $49/mo, not on sale yet
Business 3,000,000 per calendar month 2,000 $149/mo, not on sale yet

Bulk lookup takes up to 100 ZIP codes a request on Free and 1,000 on paid plans. The quota is a hard stop, not a meter: over it, requests are refused with a 429 until the reset, and nothing is ever billed for them. The per-minute limit is separate, keeps one client from crowding out the rest, and does not use quota.

Response headerMeaning
X-RateLimit-LimitRequests your plan includes in the current window (1,000 a day on Free).
X-RateLimit-RemainingRequests left in the window, after this one.
X-RateLimit-ResetWhen the window resets, ISO 8601 in UTC. Free resets at 00:00 UTC.
Retry-AfterSeconds to wait, on a 429 for the per-minute limit only.

Errors

Every error has the same shape: a stable error code to branch on, a message a person can act on, and a docs link. For example, a four digit ZIP code:

GET /v1/zip/9501 → 400

{
  "error": "not_a_zip",
  "message": "\"9501\" is not a five digit US ZIP code.",
  "docs": "https://zipcodes.pro/api/docs"
}
StatuserrorWhen
400not_a_zip / bad_parameter / too_many_zipsThe request is malformed. The message says which parameter and why.
401missing_key / invalid_keyNo key, a key that does not exist, or a revoked one.
404not_foundNo such ZIP code or county in the current release.
422no_coordinateThe ZIP code exists but has no published centre point to measure from.
429rate_limitedToo many requests this minute. Wait Retry-After seconds; it does not use quota.
429quota_exceededThe plan's allowance is used up until reset_at. Nothing is billed; requests are refused instead.

A field the source never published is null. It never means zero.

OpenAPI spec

The machine-readable spec is at https://zipcodes.pro/v1/openapi.json (OpenAPI 3.1, no key needed), for code generators and API clients.

Guides