The /v1/zipcodes/region endpoint returns all postal codes for countries within a specific geographic region (e.g., Europe, Africa, Americas). This is ideal for applications that need to work with postal codes across multiple countries in a geographic area.
GET https://api.countrydataapi.com/v1/zipcodes/region
Include your API key as a query parameter:
?apikey=your-api-key
Your API key is like a password, keep it secure. Get your key from the account dashboard.
| Parameter | Type | Required | Description |
|---|---|---|---|
apikey |
string | Yes | Your API authentication key |
region |
string | Yes | Name of the region being searched (e.g., "Africa", "Europe") |
lang |
string | No | Language code for response (default: en) |
limitToken |
number | No | Maximum tokens to spend on this request (default: 1000) |
AfricaAmericasAsiaEuropeOceaniaen - English (default)es - Spanishpt - Portuguesefr - Frenchde - Germanit - ItalianEach returned postal code will cost 1 token.
Important: Regions contain many countries with thousands of postal codes. Use
limitTokento control costs effectively.
[
{
"id": "8dd25479-067a-43b0-ac4a-8e7faf2bcaf",
"country_name": "Algeria",
"state_names": [
{
"id": "8dd25479-067a-43b0-ac4a-8e7faf2bcad",
"name": "Oran",
"postal_code": [
"31004",
"31016",
"31019",
"31020"
]
}
]
},
{
"id": "9ae35480-178b-54c1-bd5b-9f8gbf3cdeg",
"country_name": "Morocco",
"state_names": [
{
"id": "9ae35480-178b-54c1-bd5b-9f8gbf3cdeh",
"name": "Casablanca-Settat",
"postal_code": [
"20000",
"20100",
"20200"
]
}
]
}
]
| Field | Type | Description |
|---|---|---|
id |
string | Unique country identifier |
country_name |
string | Country name in the requested language |
state_names |
array | Array of state objects containing postal codes |
state_names[].id |
string | Unique state identifier |
state_names[].name |
string | State/province name |
state_names[].postal_code |
array | Array of postal codes for this state |
{
"success": false,
"error": {
"code": "MISSING_PARAMETER",
"message": "Required parameter 'region' is missing"
}
}
See the Error Codes documentation for all possible error codes.
# Get postal codes for Africa
curl -X GET "https://api.countrydataapi.com/v1/zipcodes/region?apikey=your-api-key®ion=Africa&lang=en&limitToken=500"
# Get postal codes for Europe
curl -X GET "https://api.countrydataapi.com/v1/zipcodes/region?apikey=your-api-key®ion=Europe&lang=en&limitToken=1000"
# Get postal codes for Americas in Spanish
curl -X GET "https://api.countrydataapi.com/v1/zipcodes/region?apikey=your-api-key®ion=Americas&lang=es&limitToken=500"
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.countrydataapi.com/v1';
async function getZipcodesByRegion(region, limitToken = 1000) {
try {
const params = new URLSearchParams({
apikey: API_KEY,
region: region,
lang: 'en',
limitToken: limitToken.toString()
});
const response = await fetch(`${BASE_URL}/zipcodes/region?${params}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching zipcodes by region:', error);
throw error;
}
}
// Usage examples
const africaZipcodes = await getZipcodesByRegion('Africa', 500);
console.log(`Found ${africaZipcodes.length} countries in Africa`);
const europeZipcodes = await getZipcodesByRegion('Europe', 1000);
console.log(`Found ${europeZipcodes.length} countries in Europe`);
import axios from 'axios';
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.countrydataapi.com/v1';
async function getZipcodesByRegion(region, limitToken = 1000) {
try {
const response = await axios.get(`${BASE_URL}/zipcodes/region`, {
params: {
apikey: API_KEY,
region: region,
lang: 'en',
limitToken: limitToken
}
});
return response.data;
} catch (error) {
if (error.response) {
console.error('API Error:', error.response.data);
throw new Error(error.response.data.error?.message || 'API Error');
} else {
console.error('Network Error:', error.message);
throw error;
}
}
}
// Usage
const asiaData = await getZipcodesByRegion('Asia', 500);
const totalCountries = asiaData.length;
const totalStates = asiaData.reduce((sum, c) => sum + c.state_names.length, 0);
console.log(`Asia: ${totalCountries} countries, ${totalStates} states/provinces`);
import { useState, useEffect } from 'react';
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.countrydataapi.com/v1';
const REGIONS = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'];
function useRegionZipcodes(region, limitToken = 1000) {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
if (!region) {
setData([]);
return;
}
async function fetchZipcodes() {
try {
setLoading(true);
setError(null);
const params = new URLSearchParams({
apikey: API_KEY,
region: region,
lang: 'en',
limitToken: limitToken.toString()
});
const response = await fetch(`${BASE_URL}/zipcodes/region?${params}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
setData(result);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
fetchZipcodes();
}, [region, limitToken]);
return { data, loading, error };
}
// Component Example
function RegionZipcodeExplorer() {
const [selectedRegion, setSelectedRegion] = useState('');
const { data, loading, error } = useRegionZipcodes(selectedRegion, 500);
const stats = {
countries: data.length,
states: data.reduce((sum, c) => sum + c.state_names.length, 0),
zipcodes: data.reduce((sum, c) =>
sum + c.state_names.reduce((s, st) => s + st.postal_code.length, 0),
0
)
};
return (
<div>
<h2>Explore Postal Codes by Region</h2>
<select
value={selectedRegion}
onChange={(e) => setSelectedRegion(e.target.value)}
>
<option value="">Select a region...</option>
{REGIONS.map(region => (
<option key={region} value={region}>{region}</option>
))}
</select>
{loading && <p>Loading postal codes...</p>}
{error && <p style={{ color: 'red' }}>Error: {error}</p>}
{data.length > 0 && (
<div>
<h3>{selectedRegion}</h3>
<p>
Countries: {stats.countries} |
States: {stats.states} |
Postal Codes: {stats.zipcodes}
</p>
<div style={{ maxHeight: '400px', overflow: 'auto' }}>
{data.map(country => (
<details key={country.id}>
<summary>
<strong>{country.country_name}</strong>
({country.state_names.length} states)
</summary>
<div style={{ paddingLeft: '20px' }}>
{country.state_names.map(state => (
<div key={state.id} style={{ margin: '5px 0' }}>
<strong>{state.name}:</strong>
<span style={{ fontSize: '0.9em', color: '#666' }}>
{' '}{state.postal_code.slice(0, 5).join(', ')}
{state.postal_code.length > 5 && '...'}
</span>
</div>
))}
</div>
</details>
))}
</div>
</div>
)}
</div>
);
}
export default RegionZipcodeExplorer;
<script setup>
import { ref, watch, computed } from 'vue';
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.countrydataapi.com/v1';
const REGIONS = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'];
const selectedRegion = ref('');
const regionData = ref([]);
const loading = ref(false);
const error = ref(null);
const stats = computed(() => ({
countries: regionData.value.length,
states: regionData.value.reduce((sum, c) => sum + c.state_names.length, 0),
zipcodes: regionData.value.reduce((sum, c) =>
sum + c.state_names.reduce((s, st) => s + st.postal_code.length, 0),
0
)
}));
watch(selectedRegion, async (newRegion) => {
if (!newRegion) {
regionData.value = [];
return;
}
try {
loading.value = true;
error.value = null;
const params = new URLSearchParams({
apikey: API_KEY,
region: newRegion,
lang: 'en',
limitToken: '500'
});
const response = await fetch(`${BASE_URL}/zipcodes/region?${params}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
regionData.value = await response.json();
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
});
</script>
<template>
<div>
<h2>Explore Postal Codes by Region</h2>
<select v-model="selectedRegion">
<option value="">Select a region...</option>
<option v-for="region in REGIONS" :key="region" :value="region">
{{ region }}
</option>
</select>
<div v-if="loading">Loading postal codes...</div>
<div v-else-if="error" style="color: red;">Error: {{ error }}</div>
<div v-else-if="regionData.length > 0">
<h3>{{ selectedRegion }}</h3>
<p>
Countries: {{ stats.countries }} |
States: {{ stats.states }} |
Postal Codes: {{ stats.zipcodes }}
</p>
<div style="max-height: 400px; overflow: auto;">
<details v-for="country in regionData" :key="country.id">
<summary>
<strong>{{ country.country_name }}</strong>
({{ country.state_names.length }} states)
</summary>
<div style="padding-left: 20px;">
<div
v-for="state in country.state_names"
:key="state.id"
style="margin: 5px 0;"
>
<strong>{{ state.name }}:</strong>
<span style="font-size: 0.9em; color: #666;">
{{ state.postal_code.slice(0, 5).join(', ') }}
<span v-if="state.postal_code.length > 5">...</span>
</span>
</div>
</div>
</details>
</div>
</div>
</div>
</template>
// zipcode.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
interface State {
id: string;
name: string;
postal_code: string[];
}
interface CountryZipcode {
id: string;
country_name: string;
state_names: State[];
}
@Injectable({
providedIn: 'root'
})
export class ZipcodeService {
private readonly API_KEY = 'your-api-key';
private readonly BASE_URL = 'https://api.countrydataapi.com/v1';
constructor(private http: HttpClient) {}
getZipcodesByRegion(
region: string,
limitToken: number = 1000
): Observable<CountryZipcode[]> {
const params = new HttpParams()
.set('apikey', this.API_KEY)
.set('region', region)
.set('lang', 'en')
.set('limitToken', limitToken.toString());
return this.http.get<CountryZipcode[]>(
`${this.BASE_URL}/zipcodes/region`,
{ params }
);
}
}
// region-zipcode-explorer.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ZipcodeService } from './zipcode.service';
interface Stats {
countries: number;
states: number;
zipcodes: number;
}
@Component({
selector: 'app-region-zipcode-explorer',
standalone: true,
imports: [CommonModule, FormsModule],
template: `
<div>
<h2>Explore Postal Codes by Region</h2>
<select [(ngModel)]="selectedRegion" (ngModelChange)="onRegionChange()">
<option value="">Select a region...</option>
<option *ngFor="let region of regions" [value]="region">
{{ region }}
</option>
</select>
<div *ngIf="loading">Loading postal codes...</div>
<div *ngIf="error" style="color: red;">Error: {{ error }}</div>
<div *ngIf="regionData.length > 0 && !loading">
<h3>{{ selectedRegion }}</h3>
<p>
Countries: {{ stats.countries }} |
States: {{ stats.states }} |
Postal Codes: {{ stats.zipcodes }}
</p>
<div style="max-height: 400px; overflow: auto;">
<details *ngFor="let country of regionData">
<summary>
<strong>{{ country.country_name }}</strong>
({{ country.state_names.length }} states)
</summary>
<div style="padding-left: 20px;">
<div
*ngFor="let state of country.state_names"
style="margin: 5px 0;"
>
<strong>{{ state.name }}:</strong>
<span style="font-size: 0.9em; color: #666;">
{{ state.postal_code.slice(0, 5).join(', ') }}
<span *ngIf="state.postal_code.length > 5">...</span>
</span>
</div>
</div>
</details>
</div>
</div>
</div>
`
})
export class RegionZipcodeExplorerComponent {
regions = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'];
selectedRegion = '';
regionData: any[] = [];
loading = false;
error: string | null = null;
get stats(): Stats {
return {
countries: this.regionData.length,
states: this.regionData.reduce((sum, c) => sum + c.state_names.length, 0),
zipcodes: this.regionData.reduce((sum, c) =>
sum + c.state_names.reduce((s: number, st: any) => s + st.postal_code.length, 0),
0
)
};
}
constructor(private zipcodeService: ZipcodeService) {}
onRegionChange() {
if (!this.selectedRegion) {
this.regionData = [];
return;
}
this.loading = true;
this.error = null;
this.zipcodeService.getZipcodesByRegion(this.selectedRegion, 500).subscribe({
next: (data) => {
this.regionData = data;
this.loading = false;
},
error: (err) => {
this.error = err.message;
this.loading = false;
}
});
}
}
<?php
$apiKey = 'your-api-key';
$region = 'Europe';
$limitToken = 500;
$url = "https://api.countrydataapi.com/v1/zipcodes/region?" . http_build_query([
'apikey' => $apiKey,
'region' => $region,
'lang' => 'en',
'limitToken' => $limitToken
]);
// Using cURL
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Accept: application/json'
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
if ($curlError) {
die("cURL Error: {$curlError}");
}
if ($httpCode === 200) {
$data = json_decode($response, true);
echo "Region: {$region}\n";
echo "Countries found: " . count($data) . "\n\n";
$totalStates = 0;
$totalZipcodes = 0;
foreach ($data as $country) {
$countryStates = count($country['state_names']);
$countryZipcodes = 0;
foreach ($country['state_names'] as $state) {
$countryZipcodes += count($state['postal_code']);
}
$totalStates += $countryStates;
$totalZipcodes += $countryZipcodes;
echo " {$country['country_name']}: {$countryStates} states, {$countryZipcodes} postal codes\n";
}
echo "\nTotal: {$totalStates} states, {$totalZipcodes} postal codes\n";
} else {
echo "Error: HTTP {$httpCode}\n";
$error = json_decode($response, true);
echo "Message: " . ($error['error']['message'] ?? 'Unknown error') . "\n";
}
// Reusable function
function getZipcodesByRegion($apiKey, $region, $lang = 'en', $limitToken = 1000) {
$url = "https://api.countrydataapi.com/v1/zipcodes/region?" . http_build_query([
'apikey' => $apiKey,
'region' => $region,
'lang' => $lang,
'limitToken' => $limitToken
]);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception("API Error: HTTP {$httpCode}");
}
return json_decode($response, true);
}
// Usage
try {
$africaData = getZipcodesByRegion($apiKey, 'Africa', 'en', 300);
echo "\nAfrica has " . count($africaData) . " countries\n";
$americasData = getZipcodesByRegion($apiKey, 'Americas', 'es', 400);
echo "Americas has " . count($americasData) . " countries\n";
} catch (Exception $e) {
echo $e->getMessage();
}
?>
import requests
from typing import List, Dict, Any
API_KEY = 'your-api-key'
BASE_URL = 'https://api.countrydataapi.com/v1'
REGIONS = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania']
def get_zipcodes_by_region(
region: str,
lang: str = 'en',
limit_token: int = 1000
) -> List[Dict[str, Any]]:
"""
Fetch postal codes for all countries in a specific region.
Args:
region: Geographic region name (Africa, Americas, Asia, Europe, Oceania)
lang: Language code for response
limit_token: Maximum tokens to spend on this request
Returns:
List of countries with their states and postal codes
"""
if region not in REGIONS:
raise ValueError(f"Invalid region. Must be one of: {', '.join(REGIONS)}")
try:
response = requests.get(
f'{BASE_URL}/zipcodes/region',
params={
'apikey': API_KEY,
'region': region,
'lang': lang,
'limitToken': limit_token
},
timeout=30
)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
print(f'HTTP Error: {e.response.status_code}')
print(f'Response: {e.response.text}')
raise
except requests.exceptions.RequestException as e:
print(f'Request Error: {e}')
raise
def calculate_region_stats(data: List[Dict[str, Any]]) -> Dict[str, int]:
"""Calculate statistics for region data"""
countries = len(data)
states = sum(len(c['state_names']) for c in data)
zipcodes = sum(
len(state['postal_code'])
for c in data
for state in c['state_names']
)
return {
'countries': countries,
'states': states,
'zipcodes': zipcodes
}
# Usage examples
if __name__ == '__main__':
# Get Africa data
print("=== Africa ===")
africa_data = get_zipcodes_by_region('Africa', limit_token=500)
africa_stats = calculate_region_stats(africa_data)
print(f"Countries: {africa_stats['countries']}")
print(f"States: {africa_stats['states']}")
print(f"Postal Codes: {africa_stats['zipcodes']}")
# List countries
for country in africa_data[:5]:
print(f" - {country['country_name']}: {len(country['state_names'])} states")
# Get Europe data
print("\n=== Europe ===")
europe_data = get_zipcodes_by_region('Europe', limit_token=1000)
europe_stats = calculate_region_stats(europe_data)
print(f"Countries: {europe_stats['countries']}")
print(f"States: {europe_stats['states']}")
print(f"Postal Codes: {europe_stats['zipcodes']}")
# Get Americas data in Spanish
print("\n=== Americas (Spanish) ===")
americas_data = get_zipcodes_by_region('Americas', lang='es', limit_token=500)
for country in americas_data[:3]:
print(f" - {country['country_name']}")
# Async version using aiohttp
import aiohttp
import asyncio
async def get_zipcodes_by_region_async(
region: str,
lang: str = 'en',
limit_token: int = 1000
) -> List[Dict[str, Any]]:
"""Async version using aiohttp"""
async with aiohttp.ClientSession() as session:
async with session.get(
f'{BASE_URL}/zipcodes/region',
params={
'apikey': API_KEY,
'region': region,
'lang': lang,
'limitToken': limit_token
}
) as response:
if response.status != 200:
text = await response.text()
raise Exception(f'API Error: {response.status} - {text}')
return await response.json()
# Fetch all regions in parallel
async def get_all_regions() -> Dict[str, List[Dict[str, Any]]]:
"""Fetch zipcodes for all regions in parallel"""
tasks = [
get_zipcodes_by_region_async(region, limit_token=200)
for region in REGIONS
]
results = await asyncio.gather(*tasks, return_exceptions=True)
return {
region: result
for region, result in zip(REGIONS, results)
if not isinstance(result, Exception)
}
# Run async
# all_regions = asyncio.run(get_all_regions())
# for region, data in all_regions.items():
# print(f"{region}: {len(data)} countries")
Always implement proper error handling:
async function getZipcodesWithErrorHandling(region) {
const validRegions = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'];
if (!validRegions.includes(region)) {
throw new Error(`Invalid region. Must be one of: ${validRegions.join(', ')}`);
}
try {
const response = await fetch(
`https://api.countrydataapi.com/v1/zipcodes/region?apikey=your-api-key®ion=${encodeURIComponent(region)}`
);
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
switch (response.status) {
case 400:
throw new Error(errorData.error?.message || 'Invalid request parameters');
case 401:
throw new Error('Invalid API key');
case 402:
throw new Error('Insufficient tokens. Please upgrade your plan.');
case 404:
throw new Error(`Region "${region}" not found`);
case 429:
throw new Error('Rate limit exceeded. Please try again later.');
default:
throw new Error(`HTTP error! status: ${response.status}`);
}
}
const data = await response.json();
if (!Array.isArray(data)) {
throw new Error('Invalid response format');
}
return data;
} catch (error) {
console.error('Failed to fetch region zipcodes:', error.message);
throw error;
}
}
| Error Code | Description | Solution |
|---|---|---|
INVALID_API_KEY |
API key is invalid | Check your API key in account dashboard |
MISSING_PARAMETER |
region parameter missing |
Include valid region name in request |
REGION_NOT_FOUND |
Region does not exist | Use valid region: Africa, Americas, Asia, Europe, Oceania |
QUOTA_EXCEEDED |
Daily token limit reached | Upgrade plan or wait for reset |
async function getRegionalStats() {
const regions = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'];
const stats = {};
for (const region of regions) {
const data = await getZipcodesByRegion(region, 100);
stats[region] = {
countries: data.length,
states: data.reduce((sum, c) => sum + c.state_names.length, 0),
zipcodes: data.reduce((sum, c) =>
sum + c.state_names.reduce((s, st) => s + st.postal_code.length, 0), 0
)
};
}
return stats;
}
async function getCountriesInRegion(region) {
const data = await getZipcodesByRegion(region);
return data.map(country => ({
id: country.id,
name: country.country_name,
stateCount: country.state_names.length
}));
}
// Usage
const europeanCountries = await getCountriesInRegion('Europe');
console.log(europeanCountries);
async function findPostalCodeInRegion(region, postalCode) {
const data = await getZipcodesByRegion(region);
for (const country of data) {
for (const state of country.state_names) {
if (state.postal_code.includes(postalCode)) {
return {
found: true,
country: country.country_name,
state: state.name,
postalCode: postalCode
};
}
}
}
return { found: false };
}
// Usage
const result = await findPostalCodeInRegion('Europe', '75001');
console.log(result); // { found: true, country: 'France', state: 'Ile-de-France', ... }
limitToken: Regions contain many countries; control data sizeCheck our pricing page for more details.