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.
| Endpoint | What it does | Main parameters | Token cost |
|---|---|---|---|
| /v1/zipcodes/country | All postal codes of a country, grouped by state | country, limitToken | 1 per postal code returned |
| /v1/zipcodes/state | All postal codes of one state or province | state, limitToken | 1 per postal code returned |
| /v1/zipcodes/region | Postal codes of every country in Africa, Americas, Asia, Europe or Oceania | region, limitToken | 1 per postal code returned |
| /v1/zipcodes/all | The full worldwide list, for bulk imports | limitToken | 1 per postal code returned |
| /v1/states/zipcode | Which state(s) contain a given postal code | zipcode, fields | 1 per state (basic fields) |
| /v1/places/validate | Validate and normalise country, state, city and postcode (GET or POST) | country, state, city, zipcode | 1 per request |
| /v1/places/postal-format | Postcode format, regex and example for one country or all of them | country (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
correctionsfor 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.