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/FREE

Free ZIP code API

Type an email and get a key on the next page: 1,000 requests a day, free, with no card and no trial that runs out. Every endpoint is included: ZIP lookup, radius search, distance, ZIP to county, ZIP codes by city and bulk lookup.

Get a free API key

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

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.

curl "https://zipcodes.pro/v1/zip/10001" \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch("https://zipcodes.pro/v1/zip/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/zip/10001",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Response 200

{
  "zip": "10001",
  "type": "standard",
  "type_source": "inferred",
  "city": "New York",
  "other_place_names": [],
  "state": "NY",
  "state_name": "New York",
  "county": {
    "fips": "36061",
    "name": "New York County",
    "short_name": "New York"
  },
  "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"
}
ParameterMeaning
zip
path, required
Five digit ZIP code, or ZIP+4 (95014-2083).

What you get

  • 1,000 requests a day, reset at 00:00 UTC, and 60 a minute.
  • Every endpoint and every field, the same data the paid plans get.
  • CORS is open, so you can call it from a browser page.
  • Bulk lookup of up to 100 ZIP codes in one request.
  • Going over the limit returns 429 with the reset time. There is nothing to be billed for.

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.

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.

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"
}

Limits

The free plan includes 1,000 requests a day, reset at 00:00 UTC, and 60 a minute. Every response says where you stand:

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.

Over the limit, the API answers 429 with the reset time; nothing is billed. Paid plans for higher volume (Starter 100,000 a month, Pro 500,000 a month, Business 3,000,000 a month) are listed on the pricing page and are not on sale yet.

Questions

Is the ZIP code API really free?

Yes. The free plan includes 1,000 requests a day with no card on file, and it does not expire. Paid plans are for higher volume.

How do I get a free API key?

Enter your email in the form on this page. The key is shown on the next page; copy it then, because only a hash of it is stored.

What happens when I reach the daily limit?

Requests return HTTP 429 with error quota_exceeded and the time the quota resets (00:00 UTC). Nothing is charged, and the key works again after the reset.

Can I use it from JavaScript in the browser?

Yes. CORS is open on the free plan. A key in page code is visible to anyone who opens the page, so use it for low-stakes lookups such as filling in a city from a ZIP code.

Where does the data come from?

US Census Bureau files (Gazetteer, ZCTA relationship files, American Community Survey, ZIP Code Business Patterns), IRS statistics, the OMB metro area delineations and GeoNames. Each source and its vintage is listed by the /v1/meta endpoint and on the sources page.

I need every ZIP code at once, not one at a time.

Download the free ZIP code database instead: every ZIP code as CSV, JSON and SQLite under CC BY 4.0, from the same data release the API serves.

More