The /v1/zipcodes/country endpoint returns all postal codes for a specific country, organized by state/province. This is perfect for applications that need complete postal code coverage for a specific country.
GET https://api.countrydataapi.com/v1/zipcodes/country
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 |
country |
string | Yes | Country ID, ISO code (e.g., "US", "DE"), or name |
lang |
string | No | Language code for response (default: en) |
limitToken |
number | No | Maximum tokens to spend on this request (default: 1000) |
en - English (default)es - Spanishpt - Portuguesefr - Frenchde - Germanit - ItalianEach returned postal code will cost 1 token.
Note: Large countries like the United States or Germany have thousands of postal codes. Use
limitTokento control costs.
[
{
"id": "8dd25479-067a-43b0-ac4a-8e7faf2bcaf",
"country_name": "United States",
"state_names": [
{
"id": "8dd25479-067a-43b0-ac4a-8e7faf2bcad",
"name": "California",
"postal_code": [
"90001",
"90002",
"90003",
"90004"
]
},
{
"id": "9ae35480-178b-54c1-bd5b-9f8gbf3cdeh",
"name": "Texas",
"postal_code": [
"73301",
"73344",
"75001"
]
}
]
}
]
| 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 'country' is missing"
}
}
See the Error Codes documentation for all possible error codes.
# Search by country name
curl -X GET "https://api.countrydataapi.com/v1/zipcodes/country?apikey=your-api-key&country=Germany&lang=en"
# Search by ISO code
curl -X GET "https://api.countrydataapi.com/v1/zipcodes/country?apikey=your-api-key&country=US&lang=en&limitToken=500"
# Search by country ID
curl -X GET "https://api.countrydataapi.com/v1/zipcodes/country?apikey=your-api-key&country=66c7a6c9e4bda21f4ab10fd5&lang=en"
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.countrydataapi.com/v1';
async function getZipcodesByCountry(country, limitToken = 1000) {
try {
const params = new URLSearchParams({
apikey: API_KEY,
country: country,
lang: 'en',
limitToken: limitToken.toString()
});
const response = await fetch(`${BASE_URL}/zipcodes/country?${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 country:', error);
throw error;
}
}
// Usage examples
// By country name
const germanyZipcodes = await getZipcodesByCountry('Germany');
console.log(germanyZipcodes);
// By ISO code
const usZipcodes = await getZipcodesByCountry('US', 500);
console.log(usZipcodes);
// By country ID
const mexicoZipcodes = await getZipcodesByCountry('66c7a6c9e4bda21f4ab10fa8');
console.log(mexicoZipcodes);
import axios from 'axios';
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.countrydataapi.com/v1';
async function getZipcodesByCountry(country, limitToken = 1000) {
try {
const response = await axios.get(`${BASE_URL}/zipcodes/country`, {
params: {
apikey: API_KEY,
country: country,
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 data = await getZipcodesByCountry('France', 500);
console.log(`Found postal codes for ${data[0]?.state_names?.length || 0} states`);
import { useState, useEffect } from 'react';
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.countrydataapi.com/v1';
function useCountryZipcodes(country, limitToken = 1000) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
if (!country) {
setData(null);
return;
}
async function fetchZipcodes() {
try {
setLoading(true);
setError(null);
const params = new URLSearchParams({
apikey: API_KEY,
country: country,
lang: 'en',
limitToken: limitToken.toString()
});
const response = await fetch(`${BASE_URL}/zipcodes/country?${params}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
setData(result[0] || null);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
fetchZipcodes();
}, [country, limitToken]);
return { data, loading, error };
}
// Component Example
function CountryZipcodeExplorer() {
const [selectedCountry, setSelectedCountry] = useState('');
const { data, loading, error } = useCountryZipcodes(selectedCountry, 500);
const countries = [
{ code: 'US', name: 'United States' },
{ code: 'DE', name: 'Germany' },
{ code: 'FR', name: 'France' },
{ code: 'ES', name: 'Spain' },
{ code: 'MX', name: 'Mexico' }
];
const totalZipcodes = data?.state_names?.reduce(
(sum, state) => sum + state.postal_code.length,
0
) || 0;
return (
<div>
<h2>Explore Postal Codes by Country</h2>
<select
value={selectedCountry}
onChange={(e) => setSelectedCountry(e.target.value)}
>
<option value="">Select a country...</option>
{countries.map(c => (
<option key={c.code} value={c.code}>{c.name}</option>
))}
</select>
{loading && <p>Loading postal codes...</p>}
{error && <p style={{ color: 'red' }}>Error: {error}</p>}
{data && (
<div>
<h3>{data.country_name}</h3>
<p>Total states: {data.state_names.length}</p>
<p>Total postal codes loaded: {totalZipcodes}</p>
<div style={{ maxHeight: '400px', overflow: 'auto' }}>
{data.state_names.map(state => (
<details key={state.id}>
<summary>
{state.name} ({state.postal_code.length} codes)
</summary>
<p style={{ fontSize: '0.9em', color: '#666' }}>
{state.postal_code.slice(0, 20).join(', ')}
{state.postal_code.length > 20 && '...'}
</p>
</details>
))}
</div>
</div>
)}
</div>
);
}
export default CountryZipcodeExplorer;
<script setup>
import { ref, watch, computed } from 'vue';
const API_KEY = 'your-api-key';
const BASE_URL = 'https://api.countrydataapi.com/v1';
const selectedCountry = ref('');
const countryData = ref(null);
const loading = ref(false);
const error = ref(null);
const countries = [
{ code: 'US', name: 'United States' },
{ code: 'DE', name: 'Germany' },
{ code: 'FR', name: 'France' },
{ code: 'ES', name: 'Spain' },
{ code: 'MX', name: 'Mexico' }
];
const totalZipcodes = computed(() => {
if (!countryData.value?.state_names) return 0;
return countryData.value.state_names.reduce(
(sum, state) => sum + state.postal_code.length,
0
);
});
watch(selectedCountry, async (newCountry) => {
if (!newCountry) {
countryData.value = null;
return;
}
try {
loading.value = true;
error.value = null;
const params = new URLSearchParams({
apikey: API_KEY,
country: newCountry,
lang: 'en',
limitToken: '500'
});
const response = await fetch(`${BASE_URL}/zipcodes/country?${params}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
countryData.value = data[0] || null;
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
});
</script>
<template>
<div>
<h2>Explore Postal Codes by Country</h2>
<select v-model="selectedCountry">
<option value="">Select a country...</option>
<option v-for="c in countries" :key="c.code" :value="c.code">
{{ c.name }}
</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="countryData">
<h3>{{ countryData.country_name }}</h3>
<p>Total states: {{ countryData.state_names.length }}</p>
<p>Total postal codes loaded: {{ totalZipcodes }}</p>
<div style="max-height: 400px; overflow: auto;">
<details v-for="state in countryData.state_names" :key="state.id">
<summary>
{{ state.name }} ({{ state.postal_code.length }} codes)
</summary>
<p style="font-size: 0.9em; color: #666;">
{{ state.postal_code.slice(0, 20).join(', ') }}
<span v-if="state.postal_code.length > 20">...</span>
</p>
</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) {}
getZipcodesByCountry(
country: string,
limitToken: number = 1000
): Observable<CountryZipcode[]> {
const params = new HttpParams()
.set('apikey', this.API_KEY)
.set('country', country)
.set('lang', 'en')
.set('limitToken', limitToken.toString());
return this.http.get<CountryZipcode[]>(
`${this.BASE_URL}/zipcodes/country`,
{ params }
);
}
}
// country-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 Country {
code: string;
name: string;
}
@Component({
selector: 'app-country-zipcode-explorer',
standalone: true,
imports: [CommonModule, FormsModule],
template: `
<div>
<h2>Explore Postal Codes by Country</h2>
<select [(ngModel)]="selectedCountry" (ngModelChange)="onCountryChange()">
<option value="">Select a country...</option>
<option *ngFor="let c of countries" [value]="c.code">
{{ c.name }}
</option>
</select>
<div *ngIf="loading">Loading postal codes...</div>
<div *ngIf="error" style="color: red;">Error: {{ error }}</div>
<div *ngIf="countryData && !loading">
<h3>{{ countryData.country_name }}</h3>
<p>Total states: {{ countryData.state_names.length }}</p>
<p>Total postal codes loaded: {{ getTotalZipcodes() }}</p>
<div style="max-height: 400px; overflow: auto;">
<details *ngFor="let state of countryData.state_names">
<summary>
{{ state.name }} ({{ state.postal_code.length }} codes)
</summary>
<p style="font-size: 0.9em; color: #666;">
{{ state.postal_code.slice(0, 20).join(', ') }}
<span *ngIf="state.postal_code.length > 20">...</span>
</p>
</details>
</div>
</div>
</div>
`
})
export class CountryZipcodeExplorerComponent {
countries: Country[] = [
{ code: 'US', name: 'United States' },
{ code: 'DE', name: 'Germany' },
{ code: 'FR', name: 'France' },
{ code: 'ES', name: 'Spain' },
{ code: 'MX', name: 'Mexico' }
];
selectedCountry = '';
countryData: any = null;
loading = false;
error: string | null = null;
constructor(private zipcodeService: ZipcodeService) {}
onCountryChange() {
if (!this.selectedCountry) {
this.countryData = null;
return;
}
this.loading = true;
this.error = null;
this.zipcodeService.getZipcodesByCountry(this.selectedCountry, 500).subscribe({
next: (data) => {
this.countryData = data[0] || null;
this.loading = false;
},
error: (err) => {
this.error = err.message;
this.loading = false;
}
});
}
getTotalZipcodes(): number {
if (!this.countryData?.state_names) return 0;
return this.countryData.state_names.reduce(
(sum: number, state: any) => sum + state.postal_code.length,
0
);
}
}
<?php
$apiKey = 'your-api-key';
$country = 'Germany'; // Can be country name, ISO code, or ID
$limitToken = 500;
$url = "https://api.countrydataapi.com/v1/zipcodes/country?" . http_build_query([
'apikey' => $apiKey,
'country' => $country,
'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);
if (!empty($data)) {
$countryData = $data[0];
echo "Country: " . $countryData['country_name'] . "\n";
echo "Total States: " . count($countryData['state_names']) . "\n";
$totalZipcodes = 0;
foreach ($countryData['state_names'] as $state) {
$totalZipcodes += count($state['postal_code']);
echo "\n State: " . $state['name'] . "\n";
echo " Postal Codes: " . count($state['postal_code']) . "\n";
echo " Sample: " . implode(', ', array_slice($state['postal_code'], 0, 5)) . "...\n";
}
echo "\nTotal Postal Codes: {$totalZipcodes}\n";
} else {
echo "No postal codes found for country: {$country}\n";
}
} else {
echo "Error: HTTP {$httpCode}\n";
$error = json_decode($response, true);
echo "Message: " . ($error['error']['message'] ?? 'Unknown error') . "\n";
}
// Reusable function
function getZipcodesByCountry($apiKey, $country, $lang = 'en', $limitToken = 1000) {
$url = "https://api.countrydataapi.com/v1/zipcodes/country?" . http_build_query([
'apikey' => $apiKey,
'country' => $country,
'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 {
// By ISO code
$usData = getZipcodesByCountry($apiKey, 'US', 'en', 100);
print_r($usData);
// By country name in Spanish
$spainData = getZipcodesByCountry($apiKey, 'Spain', 'es', 200);
print_r($spainData);
} catch (Exception $e) {
echo $e->getMessage();
}
?>
import requests
from typing import List, Dict, Any, Optional
API_KEY = 'your-api-key'
BASE_URL = 'https://api.countrydataapi.com/v1'
def get_zipcodes_by_country(
country: str,
lang: str = 'en',
limit_token: int = 1000
) -> List[Dict[str, Any]]:
"""
Fetch postal codes for a specific country.
Args:
country: Country name, ISO code, or ID
lang: Language code for response
limit_token: Maximum tokens to spend on this request
Returns:
List containing country data with states and postal codes
"""
try:
response = requests.get(
f'{BASE_URL}/zipcodes/country',
params={
'apikey': API_KEY,
'country': country,
'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 count_total_zipcodes(country_data: Dict[str, Any]) -> int:
"""Count total postal codes in country data"""
return sum(
len(state['postal_code'])
for state in country_data.get('state_names', [])
)
# Usage examples
if __name__ == '__main__':
# Search by country name
germany_data = get_zipcodes_by_country('Germany', limit_token=500)
if germany_data:
country = germany_data[0]
print(f"Country: {country['country_name']}")
print(f"Total states: {len(country['state_names'])}")
print(f"Total postal codes: {count_total_zipcodes(country)}")
for state in country['state_names'][:3]:
print(f"\n State: {state['name']}")
print(f" Codes: {', '.join(state['postal_code'][:5])}...")
# Search by ISO code
print("\n--- France (by ISO code) ---")
france_data = get_zipcodes_by_country('FR', limit_token=300)
if france_data:
print(f"Total postal codes: {count_total_zipcodes(france_data[0])}")
# Search in Spanish
print("\n--- Mexico (in Spanish) ---")
mexico_data = get_zipcodes_by_country('Mexico', lang='es', limit_token=200)
if mexico_data:
for state in mexico_data[0]['state_names'][:3]:
print(f" Estado: {state['name']}")
# Async version using aiohttp
import aiohttp
import asyncio
async def get_zipcodes_by_country_async(
country: 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/country',
params={
'apikey': API_KEY,
'country': country,
'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 multiple countries in parallel
async def get_multiple_countries(countries: List[str]) -> Dict[str, Any]:
"""Fetch zipcodes for multiple countries in parallel"""
tasks = [
get_zipcodes_by_country_async(country, limit_token=100)
for country in countries
]
results = await asyncio.gather(*tasks, return_exceptions=True)
return dict(zip(countries, results))
# Run async
# data = asyncio.run(get_multiple_countries(['US', 'DE', 'FR']))
Always implement proper error handling:
async function getZipcodesWithErrorHandling(country) {
try {
const response = await fetch(
`https://api.countrydataapi.com/v1/zipcodes/country?apikey=your-api-key&country=${encodeURIComponent(country)}`
);
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(`Country "${country}" 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) || data.length === 0) {
console.warn(`No postal codes found for country: ${country}`);
return null;
}
return data[0];
} catch (error) {
console.error('Failed to fetch country 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 |
country parameter missing |
Include country name, ISO code, or ID |
COUNTRY_NOT_FOUND |
Country does not exist | Verify country name or use valid ISO code |
QUOTA_EXCEEDED |
Daily token limit reached | Upgrade plan or wait for reset |
async function populateAddressForm(countryCode) {
const data = await getZipcodesByCountry(countryCode);
if (!data) return;
const stateSelect = document.getElementById('state');
stateSelect.innerHTML = '<option value="">Select state...</option>';
data.state_names.forEach(state => {
const option = new Option(state.name, state.id);
option.dataset.zipcodes = JSON.stringify(state.postal_code);
stateSelect.add(option);
});
}
async function validatePostalCode(countryCode, postalCode) {
const data = await getZipcodesByCountry(countryCode);
if (!data) {
return { valid: false, message: 'Country not found' };
}
for (const state of data.state_names) {
if (state.postal_code.includes(postalCode)) {
return {
valid: true,
state: state.name,
message: `Valid postal code for ${state.name}`
};
}
}
return { valid: false, message: 'Invalid postal code for this country' };
}
// Usage
const result = await validatePostalCode('DE', '10115');
console.log(result); // { valid: true, state: 'Berlin', message: '...' }
limitToken: Control data size for countries with many postal codesCheck our pricing page for more details.