Guide · Node.js · SDK · REST API

Postal Code Validation in Node.js — Multi-Country Formats & Geolocation

Every country has its own postal code format. Some share the same codes. A five-digit number could be a US ZIP, a German PLZ, or an Italian CAP. Here's how to validate them properly and get geolocation data in the process.

1. Why postal code validation is harder than it looks

Unlike email or phone numbers, postal codes have no single international standard. Each country defines its own format, length, and character set. What looks like a valid code in one country may be valid in another — or meaningless in both.

1

60+ distinct formats

The US uses 5 digits, the UK uses an alphanumeric pattern like "SW1A 1AA", Poland uses "NN-NNN", Japan uses "NNN-NNNN", and Canada alternates letters and digits as "A9A 9A9".

2

Wildly different lengths

From 3 digits (Iceland) to 10 characters (Iran). Some include spaces or hyphens as mandatory separators.

3

Cross-country ambiguity

The code "10115" is valid in both the United States (a New York ZIP) and Germany (Berlin). Without a country hint, you cannot know which one the user means.

A simple regex can tell you whether a string is five digits — but it cannot tell you whether that string is a real postal code, which country it belongs to, or where in the world it points.


2. Postal code formats around the world

Here is a sampling of how different countries structure their postal codes. The "N" stands for a digit and "A" for a letter.

CountryCodeFormatExampleLength
United StatesUSNNNNN902105
United KingdomGBA9 9AA / A9A 9AA / A99 9AASW1A 1AA6–8
GermanyDENNNNN101155
PolandPLNN-NNN00-0016
JapanJPNNN-NNNN100-00018
CanadaCAA9A 9A9K1A 0B17
FranceFRNNNNN750085
BrazilBRNNNNN-NNN01001-0009
IndiaINNNNNNN1100016
NetherlandsNLNNNN AA1011 AB7
ℹ️Some countries like Ireland and Hong Kong do not use nationwide postal codes at all. Others, like the UK, have a format so complex that a single regex is not enough to cover all valid outward and inward codes.

3. Why regex per country is a maintenance nightmare

The natural instinct is to build a map of country codes to regex patterns. It works at first — then reality sets in.

// Seems manageable at first...
const POSTAL_REGEX = {
  US: /^\d{5}(-\d{4})?$/,
  GB: /^[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}$/i,
  PL: /^\d{2}-\d{3}$/,
  DE: /^\d{5}$/,
  JP: /^\d{3}-\d{4}$/,
  CA: /^[A-Z]\d[A-Z] ?\d[A-Z]\d$/i,
  // ... 54 more countries ...
};

// Problems:
// 1. You need 60+ regex patterns, each hand-crafted and tested
// 2. You need country detection logic when no country is provided
// 3. Regex only checks format — "00000" passes US regex but is not a real ZIP
// 4. No geolocation — you still don't know the city or region
// 5. Formats change: Royal Mail updates UK postcodes regularly
!

Maintenance burden

Every time a country reforms its postal system, you need to update your regex table and redeploy.

!

No existence check

A regex confirms format but cannot tell you whether "99999" is an actual US ZIP code or a placeholder.

!

No country detection

When the user enters "10115" without specifying a country, your code has no way to determine if it is Berlin, Germany or New York, US.

!

No geolocation

Even with a valid code and country, regex gives you zero information about the city, region, or coordinates.


4. The right solution

The IsValid Postal Code API handles format validation, country detection, and geolocation in a single request. Pass an optional country code for a definitive answer, or omit it to get all matching countries.

Multi-country format validation

Validates against official format rules for 60+ countries

Country detection

When no country is specified, returns all countries where the code is valid

Geolocation data

Returns city, region, sub-region, latitude, and longitude when a country is provided

60+ countries supported

From US ZIP codes to Japanese postal codes, all maintained and updated

<50ms
Response time
with country hint
60+
Countries
formats maintained
100/day
Free tier
no credit card

Full parameter reference and response schema: Postal Code Validation API docs →


5. Node.js code example

Using the IsValid SDK or the native fetch API.

import { createClient } from '@isvalid-dev/sdk';

const iv = createClient({ apiKey: process.env.ISVALID_API_KEY });

// ── With country hint ────────────────────────────────────────────────────────
// Get definitive validation + geolocation for a Polish postal code
const plResult = await iv.postalCode('00-001', { countryCode: 'PL' });
console.log(plResult.valid);              // true
console.log(plResult.country);            // 'PL'
console.log(plResult.format);             // 'NN-NNN'
console.log(plResult.location.city);      // 'Warszawa'
console.log(plResult.location.lat);       // 52.23
console.log(plResult.location.lon);       // 21.01

// ── Without country hint ─────────────────────────────────────────────────────
// Detect which countries match the code
const ambiguous = await iv.postalCode('90210');
console.log(ambiguous.valid);                       // true
console.log(ambiguous.matchingCountries.length);    // may match US, etc.
console.log(ambiguous.matchingCountries[0].country);     // 'US'
console.log(ambiguous.matchingCountries[0].format);      // 'NNNNN'

In a shipping form handler — validate the postal code against the selected country:

// routes/checkout.js (Express)
app.post('/checkout', async (req, res) => {
  const { postalCode, country, address } = req.body;

  let check;
  try {
    check = await validatePostalCode(postalCode, { countryCode: country });
  } catch {
    return res.status(502).json({ error: 'Postal code validation service unavailable' });
  }

  if (!check.valid) {
    return res.status(400).json({
      error: `Invalid postal code for ${country}. Expected format: ${check.format ?? 'unknown'}.`,
    });
  }

  // Use geolocation to auto-fill city and region
  if (check.location) {
    req.body.city = req.body.city || check.location.city;
    req.body.region = req.body.region || check.location.region;
  }

  // Proceed with order
  await createOrder(req.body);
  res.json({ success: true });
});
When the user selects a country first, pass the countryCode parameter for a definitive answer and geolocation data. If you only need a quick format check (e.g., in an international search bar), omit the country to see all matches.

6. cURL example

With a country hint (returns geolocation):

curl -G -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "value=00-001" \
  --data-urlencode "countryCode=PL" \
  "https://api.isvalid.dev/v0/postal-code"

Without a country hint (returns matching countries):

curl -G -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "value=90210" \
  "https://api.isvalid.dev/v0/postal-code"

Invalid postal code:

curl -G -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "value=INVALID" \
  --data-urlencode "countryCode=US" \
  "https://api.isvalid.dev/v0/postal-code"

7. Understanding the response

With country code — validated against a specific country, includes geolocation:

{
  "valid": true,
  "country": "PL",
  "countryName": "Poland",
  "format": "NN-NNN",
  "location": {
    "city": "Warszawa",
    "region": "Masovian Voivodeship",
    "subregion": "Warsaw",
    "lat": 52.23,
    "lon": 21.01
  }
}

Without country code — returns all countries where the format matches:

{
  "valid": true,
  "matchingCountries": [
    {
      "country": "DE",
      "countryName": "Germany",
      "format": "NNNNN"
    },
    {
      "country": "US",
      "countryName": "United States",
      "format": "NNNNN"
    }
  ]
}

Invalid code:

{
  "valid": false
}
FieldTypeDescription
validbooleanWhether the postal code matches a known format
countrystringISO 3166-1 alpha-2 code (present when countryCode was provided)
countryNamestringFull country name in English
formatstringFormat pattern for the country (e.g., "NN-NNN", "NNNNN")
locationobjectGeolocation data (present when countryCode was provided and the code is valid)
location.citystringCity or primary locality name
location.regionstringState, province, voivodeship, or equivalent
location.subregionstringCounty, district, or sub-division
location.latnumberLatitude of the postal code area centroid
location.lonnumberLongitude of the postal code area centroid
matchingCountriesarrayList of countries where the code is format-valid (present when countryCode was omitted)

8. Edge cases

Ambiguous codes matching multiple countries

Five-digit postal codes are used by at least a dozen countries. The code "10115" is valid in both the US and Germany. When you call the API without a countryCode, the response lists all matching countries in the matchingCountries array.

const result = await iv.postalCode('10115');
// result.matchingCountries might include DE, US, IT, FR...
// Let the user pick their country, then re-validate with countryCode
// to get definitive geolocation data.

UK outward vs full postcode

A UK postcode has two parts: the outward code (e.g., "SW1A") identifies the postal district, and the inward code (e.g., "1AA") narrows it to a delivery point. Some systems accept just the outward code, but the API validates the full postcode. Always collect the complete code from users (e.g., "SW1A 1AA") for accurate validation and geolocation.

US ZIP+4 codes

The US Postal Service uses an extended format called ZIP+4 (e.g., "90210-1234") for more precise delivery. The API accepts both the standard 5-digit ZIP and the extended ZIP+4 format. If your application collects shipping addresses, accept both but do not require the +4 extension — most users do not know it.

Countries without postal codes

Not every country uses postal codes. Notable examples include Ireland (which uses Eircode, a unique system), Hong Kong, Panama, and several island nations. If your application supports these countries, make the postal code field optional in your forms rather than forcing users to enter a value.


Summary

Do not maintain a regex table for 60+ countries — it is brittle and gives you no geolocation
Do not assume all postal codes are numeric — many countries use letters, spaces, and hyphens
Pass a country code when you have one — you get definitive validation plus city, region, and coordinates
Omit the country code for auto-detection when you need to identify where a code belongs
Use geolocation data to auto-fill city and region fields in shipping forms
Make the postal code field optional for countries that do not use them

See also

Validate postal codes instantly

Free tier includes 100 API calls per day. No credit card required. Format validation, country detection, and geolocation for 60+ countries.