Postal code lookup & validation

Zip Code API
for Lookup & Validation

List the postal codes of any country, state or region, find which state a zip code belongs to, and check that a country + city + postcode combination really exists before you store it. One REST API, clean JSON, 500,000+ postal codes across 200+ countries.

What the Postal Code API Gives You

Four jobs that every checkout, shipping calculator and CRM import eventually needs.

Postal code lists

Every postal code of a country, a state or a whole region, grouped by state so you can build shipping zones or seed your own tables.

Reverse lookup

Send a zip code and get back the state or province it belongs to, so the user does not have to pick it by hand.

Address validation

Check country, state, city and postcode together. You get a verdict per component, the canonical spelling and suggested corrections.

Format & regex

The postcode template, official regular expression and a sample value per country, to validate the field in the browser.

Zip Code Endpoints at a Glance

All requests are GET calls to https://api.countrydataapi.com with your key in the apikey query parameter.

Postal code endpoints, their main parameters and token cost
EndpointWhat it doesMain parametersToken cost
/v1/zipcodes/countryAll postal codes of a country, grouped by statecountry, limitToken1 per postal code returned
/v1/zipcodes/stateAll postal codes of one state or provincestate, limitToken1 per postal code returned
/v1/zipcodes/regionPostal codes of every country in Africa, Americas, Asia, Europe or Oceaniaregion, limitToken1 per postal code returned
/v1/zipcodes/allThe full worldwide list, for bulk importslimitToken1 per postal code returned
/v1/states/zipcodeWhich state(s) contain a given postal codezipcode, fields1 per state (basic fields)
/v1/places/validateValidate and normalise country, state, city and postcode (GET or POST)country, state, city, zipcode1 per request
/v1/places/postal-formatPostcode format, regex and example for one country or all of themcountry (optional)1 per request

Bulk endpoints accept limitToken (default 1000) so a large country such as the United States or Germany never spends more than you allow in a single call.

Validate a Postal Code in One Request

Send what the user typed. Get back a verdict per field and the canonical address.

Request (cURL)

curl "https://api.countrydataapi.com/v1/places/validate?apikey=YOUR_API_KEY&country=ES&city=Madrid&zipcode=28001"

Reverse lookup (cURL)

curl "https://api.countrydataapi.com/v1/states/zipcode?apikey=YOUR_API_KEY&zipcode=90001"

Bulk list (cURL)

curl "https://api.countrydataapi.com/v1/zipcodes/country?apikey=YOUR_API_KEY&country=Germany&limitToken=500"

Validation response (abridged)

{
  "success": true,
  "result": {
    "valid": true,
    "has_corrections": false,
    "verdict": {
      "country": "confirmed",
      "state": "not_provided",
      "city": "confirmed",
      "zipcode": "confirmed"
    },
    "normalized": {
      "country": { "name": "Spain", "iso2": "ES" },
      "state": { "name": "Comunidad de Madrid" },
      "city": { "name": "Madrid" },
      "zipcode": "28001"
    },
    "corrections": [],
    "postal": {
      "format": "#####",
      "regex": "^\\d{5}$",
      "example": "12345",
      "matches_format": true
    }
  },
  "tokens_used": 1
}

Client-side check with fetch

// Fetch every country's postcode format once and cache it
const res = await fetch(
  'https://api.countrydataapi.com/v1/places/postal-format?apikey=YOUR_API_KEY'
);
const { data } = await res.json();

const formats = Object.fromEntries(
  data.map(({ country, postal }) => [country.iso2, postal])
);

function looksValid(value, iso2) {
  const postal = formats[iso2];
  if (!postal?.regex) return true; // no pattern on record
  return new RegExp(postal.regex).test(value.trim());
}

input.placeholder = formats['GB']?.example ?? '';

How Postal Code Validation Works

/v1/places/validate requires a country and accepts any mix of state, city and postcode. Each component comes back with one of four verdicts, and valid is true only when every component you sent is confirmed.

  • confirmed

    The value exists and matches exactly what was sent.

  • corrected

    Resolved, but not from what was sent. Check corrections for a "did you mean" prompt.

  • unconfirmed

    The value could not be verified.

  • not_provided

    You did not send this field. Omitted fields never make an address invalid.

Send only a country and a postcode and the response fills in the state for you, so a checkout can pre-populate the province field. If a code is not in the dataset but matches the country's official format, the verdict is corrected and postal.matches_format is true: plausible, and usually safe to accept.

Where Teams Use a Zip Code API

Checkout and shipping forms

Catch a mistyped postcode before the order is placed, and fill in the state automatically from the zip code to remove a field from the form.

Delivery zones and rates

Pull every postal code of a state or country once, store it, and map codes to your own zones or carriers. You can keep the data for as long as you need it.

CRM and data imports

Run addresses typed by hand or imported from spreadsheets through validation to normalise spelling and flag records that need a second look.

International sign-up forms

Show the right placeholder and validate the field per country: five digits in Spain, SW1A 1AA in the UK, K1A 0B1 in Canada.

Coverage and Limits

The dataset covers 200+ countries, 5,000+ states, 150,000+ cities and 500,000+ postal codes. It is administrative data, so be clear about what it does not do:

  • No street-level data. There are no streets, house numbers or delivery points, so it cannot confirm a full street address.
  • No points of interest. No businesses, opening hours or reviews.
  • No geocoding. Postal codes and cities do not carry coordinates; only countries return a centroid.
  • Coverage varies by country. Postal code lists are not complete everywhere, which is why validation also checks the official format.
  • Codes repeat across countries. A reverse lookup can return states from several countries, so pass the country whenever you know it.
  • Well-formed is not the same as real. A regex check in the browser improves UX; confirm with the validation endpoint before shipping anything.

Frequently Asked Questions

What is a zip code API?

It is a web service that returns postal code data over HTTP. CountryDataAPI lets you list the postal codes of a country, state or region, find the state a code belongs to, and validate a postcode together with its country, state and city.

How do I validate a postal code?

Call /v1/places/validate with country and zipcode (plus state and city if you have them). It returns a verdict per field, the canonical address and whether the code matches the country's official format. For instant feedback while typing, cache /v1/places/postal-format and test the regex in the browser. See the validation docs.

Does it validate street addresses?

No. Coverage stops at country, state, city and postal code. There is no street-level or point-of-interest data, so the API cannot confirm a street name or house number.

Is every country's postal code list complete?

Not for every country. The dataset holds 500,000+ postal codes, but coverage varies. When a code is missing but matches the official format, validation marks it as corrected with matches_format: true so you can decide whether to accept it.

How much does the zip code API cost?

Paid plans start at €5/month with 200,000 monthly tokens. Validation and postal-format calls cost 1 token each; bulk lists cost 1 token per postal code returned, capped by limitToken. See the pricing page for every plan.

Stop shipping to postcodes that don't exist

Postal code lookup, reverse lookup and validation in one API, from €5/month. Create an account, grab your key and make your first call in minutes.

Building an address form? See the city autocomplete API.