Search, validate, and look up postal codes worldwide. Covers 124 countries with 4.25 million records including place names, administrative divisions, and geographic coordinates. Spatial queries let you find codes near a point or within a polygon.
Comprehensive postal code coverage from regularly updated sources. Place names, admin divisions, and coordinates for every record.
Validate postal codes by regex format or check actual existence in the database. Batch validate up to 100 codes across multiple countries in one request.
Find postal codes within a GeoJSON polygon or near a GPS coordinate with distance calculations. Powered by PostGIS for accurate haversine distances.
Each record includes up to three levels of administrative divisions (state, county, municipality) for detailed geographic context.
# Look up a US ZIP code
$ curl "https://api.apicrate.io/api/v1/postal/US/90210" \
-H "X-API-Key: YOUR_API_KEY"
# Response
{
"status": "ok",
"data": [
{
"postal_code": "90210",
"place_name": "Beverly Hills",
"admin_name1": "California",
"admin_code1": "CA",
"admin_name2": "Los Angeles",
"admin_code2": "037",
"admin_name3": null,
"admin_code3": null,
"latitude": 34.0901,
"longitude": -118.4065,
"accuracy": 4
}
]
}
import requests
# Look up a German postal code
response = requests.get(
"https://api.apicrate.io/api/v1/postal/DE/10115",
headers={"X-API-Key": "YOUR_API_KEY"},
)
for place in response.json()["data"]:
print(f"{place['postal_code']}: {place['place_name']}, {place['admin_name1']}")
# 10115: Mitte, Berlin
// Look up a UK postcode
const res = await fetch("https://api.apicrate.io/api/v1/postal/GB/SW1A 1AA", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
const { data } = await res.json();
console.log(data[0].place_name); // "London"
console.log(data[0].admin_name1); // "England"
# Search UK postal codes by place name
$ curl "https://api.apicrate.io/api/v1/postal/GB/search?q=Westminster&limit=3" \
-H "X-API-Key: YOUR_API_KEY"
# Response
{
"status": "ok",
"data": [
{
"postal_code": "SW1A 0AA",
"place_name": "Westminster",
"admin_name1": "England",
"admin_code1": "ENG",
"latitude": 51.4995,
"longitude": -0.1248,
"accuracy": 6
}
],
"total": 42
}
import requests
# Search by postal code prefix and admin code
response = requests.get(
"https://api.apicrate.io/api/v1/postal/US/search",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"prefix": "902", "admin_code": "CA", "limit": 5},
)
data = response.json()
print(f"Found {data['total']} codes starting with 902 in California")
for place in data["data"]:
print(f" {place['postal_code']}: {place['place_name']}")
// Search Polish postal codes by place name
const res = await fetch(
"https://api.apicrate.io/api/v1/postal/PL/search?q=Kraków&limit=5",
{ headers: { "X-API-Key": "YOUR_API_KEY" } },
);
const { data, total } = await res.json();
console.log(`Found ${total} results`);
data.forEach((p) => console.log(`${p.postal_code}: ${p.place_name}`));
# Validate multiple codes across countries in one request
$ curl -X POST "https://api.apicrate.io/api/v1/postal/validate" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"codes": [
{"country_code": "US", "postal_code": "90210"},
{"country_code": "GB", "postal_code": "SW1A 1AA"},
{"country_code": "DE", "postal_code": "XXXXX"}
]
}'
# Response
{
"status": "ok",
"data": [
{"postal_code": "90210", "country_code": "US", "format_valid": true, "exists": true},
{"postal_code": "SW1A 1AA", "country_code": "GB", "format_valid": true, "exists": true},
{"postal_code": "XXXXX", "country_code": "DE", "format_valid": false, "exists": false}
]
}
import requests
# Batch validate with format + existence checks
response = requests.post(
"https://api.apicrate.io/api/v1/postal/validate",
headers={"X-API-Key": "YOUR_API_KEY"},
json={
"codes": [
{"country_code": "US", "postal_code": "90210"},
{"country_code": "PL", "postal_code": "00-001"},
{"country_code": "US", "postal_code": "00000"},
]
},
)
for result in response.json()["data"]:
status = "valid" if result["format_valid"] and result["exists"] else "invalid"
print(f"{result['country_code']} {result['postal_code']}: {status}")
// Validate a list of postal codes from a form submission
const codes = [
{ country_code: "FR", postal_code: "75001" },
{ country_code: "JP", postal_code: "100-0001" },
{ country_code: "AU", postal_code: "2000" },
];
const res = await fetch("https://api.apicrate.io/api/v1/postal/validate", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ codes }),
});
const { data } = await res.json();
const invalid = data.filter((r) => !r.format_valid || !r.exists);
console.log(`${invalid.length} invalid codes found`);
# Find postal codes within 5 km of central London
$ curl -X POST "https://api.apicrate.io/api/v1/postal/GB/nearby" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"lat": 51.5074, "lng": -0.1278, "radius_km": 5, "limit": 3}'
# Response — ordered by distance
{
"status": "ok",
"data": [
{
"postal_code": "WC2N 5DU",
"place_name": "London",
"admin_name1": "England",
"latitude": 51.5074,
"longitude": -0.1278,
"distance_km": 0.012
},
{
"postal_code": "WC2E 8HD",
"place_name": "London",
"latitude": 51.5112,
"longitude": -0.1215,
"distance_km": 0.593
}
],
"total_count": 847,
"limit": 3,
"offset": 0
}
import requests
# Find US ZIP codes within 10 km of a store location
response = requests.post(
"https://api.apicrate.io/api/v1/postal/US/nearby",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"lat": 40.7128, "lng": -74.0060, "radius_km": 10},
)
data = response.json()
print(f"{data['total_count']} postal codes within 10 km")
for place in data["data"][:5]:
print(f" {place['postal_code']} — {place['place_name']} ({place['distance_km']} km)")
// Find nearby postal codes for a store locator
const res = await fetch("https://api.apicrate.io/api/v1/postal/DE/nearby", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ lat: 52.52, lng: 13.405, radius_km: 3 }),
});
const { data, total_count } = await res.json();
console.log(`${total_count} codes near Berlin center`);
data.forEach((p) => console.log(`${p.postal_code}: ${p.distance_km} km`));
# Find US postal codes inside a GeoJSON polygon (Manhattan bounding box)
$ curl -X POST "https://api.apicrate.io/api/v1/postal/US/within" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"geometry": {
"type": "Polygon",
"coordinates": [[
[-74.02, 40.70], [-73.97, 40.70], [-73.93, 40.78],
[-73.94, 40.82], [-74.02, 40.78], [-74.02, 40.70]
]]
},
"limit": 5
}'
# Response
{
"status": "ok",
"data": [
{
"postal_code": "10001",
"place_name": "New York City",
"admin_name1": "New York",
"admin_code1": "NY",
"latitude": 40.7484,
"longitude": -73.9967
}
],
"total_count": 87,
"limit": 5,
"offset": 0
}
import requests
# Find all postal codes within a delivery zone
delivery_zone = {
"type": "Polygon",
"coordinates": [[
[2.25, 48.81], [2.42, 48.81], [2.42, 48.90],
[2.25, 48.90], [2.25, 48.81],
]],
}
response = requests.post(
"https://api.apicrate.io/api/v1/postal/FR/within",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"geometry": delivery_zone, "limit": 1000},
)
data = response.json()
codes = [p["postal_code"] for p in data["data"]]
print(f"{data['total_count']} postal codes in delivery zone: {codes[:5]}...")
// Find postal codes within a sales territory polygon
const res = await fetch("https://api.apicrate.io/api/v1/postal/GB/within", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
geometry: {
type: "Polygon",
coordinates: [[
[-0.15, 51.49], [-0.07, 51.49], [-0.07, 51.53],
[-0.15, 51.53], [-0.15, 51.49],
]],
},
}),
});
const { data, total_count } = await res.json();
console.log(`${total_count} postal codes in territory`);
# Browse all supported postal systems
$ curl "https://api.apicrate.io/api/v1/postal?limit=3&fields=country,country_code,format,total_codes" \
-H "X-API-Key: YOUR_API_KEY"
# Response
{
"status": "ok",
"data": [
{"country": "Andorra", "country_code": "AD", "format": "AD###", "total_codes": 7},
{"country": "Argentina", "country_code": "AR", "format": "@####@@@", "total_codes": 20261},
{"country": "Austria", "country_code": "AT", "format": "####", "total_codes": 2213}
],
"total": 124
}
import requests
# Find countries using 5-digit postal codes
response = requests.get(
"https://api.apicrate.io/api/v1/postal",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"format_like": "#####", "fields": "country,country_code,format"},
)
data = response.json()
print(f"{data['total']} countries use 5-digit codes:")
for system in data["data"]:
print(f" {system['country_code']}: {system['country']} ({system['format']})")
// List all postal systems with their regex patterns
const res = await fetch(
"https://api.apicrate.io/api/v1/postal?limit=500&fields=country_code,regex,total_records",
{ headers: { "X-API-Key": "YOUR_API_KEY" } },
);
const { data } = await res.json();
const bySize = data.sort((a, b) => b.total_records - a.total_records);
console.log("Top 5 by record count:");
bySize.slice(0, 5).forEach((s) =>
console.log(` ${s.country_code}: ${s.total_records.toLocaleString()} records`),
);
/api/v1/postal
List postal systems
/api/v1/postal/validate
Validate postal codes (batch)
/api/v1/postal/{country_code}
Get postal system for a country
/api/v1/postal/{country_code}/codes
List all postal codes for a country
/api/v1/postal/{country_code}/search
Search postal codes
/api/v1/postal/{country_code}/within
Find postal codes within a polygon
/api/v1/postal/{country_code}/nearby
Find postal codes near a point
/api/v1/postal/{country_code}/validate/{postal_code}
Quick-validate a postal code
/api/v1/postal/{country_code}/{postal_code}
Look up a postal code
The API covers 124 countries with 4.25 million postal code records from regularly updated sources.
Format validation (GET /postal/{country}/validate/{code}) checks if a postal
code matches the country's regex pattern — it's a fast, lightweight check.
Batch validation (POST /postal/validate) also checks if the code actually
exists in the database, giving you both format_valid and exists fields.
Yes. All endpoints accept both alpha-2 (US) and alpha-3 (USA)
country codes interchangeably.
The nearby endpoint (POST /postal/{country}/nearby) finds postal codes
within a radius of a GPS point, returning results ordered by distance.
The within endpoint (POST /postal/{country}/within) finds postal codes
inside a GeoJSON polygon or multi-polygon. Both use PostGIS for accurate
geographic calculations.
Accuracy varies by country and is indicated by the accuracy field:
0 = address-level sourced, 1 = estimated, 4 = place ID, 6 = centroid
of the postal code area.
Yes. A single postal code can map to multiple places (e.g., a ZIP code covering several neighborhoods). The lookup endpoint returns all matching records as a list.
Create a free account and start making requests in under a minute.