This endpoint allows you to find states based on a postal code (ZIP code). It is particularly useful for address validation, shipping calculations, and location-based services. Note that the same postal code may exist in different countries, so multiple results may be returned.
All API requests require authentication using an API key. Include your API key as a query parameter in each request:
?apikey=YOUR_API_KEY
You can obtain an API key by registering at CountryDataAPI.
https://api.countrydataapi.com/v1/states/zipCode
Returns a list of all states according to their postal code
Keep in mind that there are many states from different countries that have the same postal codes
According to the requested fields, there will be 3 types of requests:
BASIC: Returns the fields id, state_name, lang Each state will cost 1 token
NORMAL: Returns the field state_cities [All IDs and names of cities in the state] Each city will cost 1 token
ADVANCED: Returns the field state_zip_codes [All postal codes of the city] Each postal code costs 1 token
| Parameter | Type | Description |
|---|---|---|
| apikey | required, token | Account authentication key |
| zipcode | required, string | Postal code of the desired state |
| limitToken | optional, number | 1000 (default). Maximum number of tokens you want to spend on this request |
| fields | optional, string | id,lang,state_name (default). Expected fields in the response |
| lang | optional, lang | en (default). Expected language of the response |
[
{
"id": "8dd25479-067a-43b0-ac4a-8e7faf2bcafb",
"state_name": "Takhar",
"lang": "en",
"state_cities": [
{
"id": "8dd25476-067a-43b0-ac4b-8e7faf2bcbfb",
"city_name": "City"
}
],
"state_zip_codes": [
"00000",
"00001"
]
}
]
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';
async function getStateByZipCode(zipCode) {
try {
const params = new URLSearchParams({
apikey: API_KEY,
zipcode: zipCode,
lang: 'en',
fields: 'id,state_name,lang'
});
const response = await fetch(`${BASE_URL}?${params}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const states = await response.json();
console.log(`States with postal code "${zipCode}":`, states);
return states;
} catch (error) {
console.error('Error fetching state by zip code:', error);
throw error;
}
}
// Usage
getStateByZipCode('90210'); // Beverly Hills, California
getStateByZipCode('10001'); // New York
getStateByZipCode('28001'); // Madrid, Spain
import axios from 'axios';
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';
async function getStateByZipCode(zipCode) {
try {
const response = await axios.get(BASE_URL, {
params: {
apikey: API_KEY,
zipcode: zipCode,
lang: 'en',
fields: 'id,state_name,lang'
}
});
console.log(`States with postal code "${zipCode}":`, response.data);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
console.error('API Error:', error.response?.data || error.message);
}
throw error;
}
}
// Validate ZIP code and get state
async function validateZipCode(zipCode) {
const states = await getStateByZipCode(zipCode);
if (states.length === 0) {
return { valid: false, message: 'Invalid ZIP code' };
}
if (states.length === 1) {
return {
valid: true,
state: states[0].state_name,
message: `ZIP code belongs to ${states[0].state_name}`
};
}
return {
valid: true,
states: states.map(s => s.state_name),
message: `ZIP code exists in multiple locations`
};
}
// Usage
validateZipCode('33101'); // Miami, Florida
import { useState, useEffect, useCallback } from 'react';
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';
function StateByZipCode({ zipCode }) {
const [states, setStates] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const fetchStateByZipCode = async () => {
if (!zipCode) {
setStates([]);
return;
}
try {
setLoading(true);
setError(null);
const params = new URLSearchParams({
apikey: API_KEY,
zipcode: zipCode,
lang: 'en',
fields: 'id,state_name,lang'
});
const response = await fetch(`${BASE_URL}?${params}`);
if (!response.ok) {
throw new Error('Failed to fetch state');
}
const data = await response.json();
setStates(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchStateByZipCode();
}, [zipCode]);
if (loading) return <div>Looking up ZIP code...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
<h2>States with ZIP code "{zipCode}"</h2>
{states.length === 0 ? (
<p>No states found for this ZIP code</p>
) : (
<>
<p>Found {states.length} result(s)</p>
<ul>
{states.map((state) => (
<li key={state.id}>{state.state_name}</li>
))}
</ul>
</>
)}
</div>
);
}
// ZIP code lookup component with input and debounce
function ZipCodeLookup() {
const [zipInput, setZipInput] = useState('');
const [searchZip, setSearchZip] = useState('');
const [debouncedZip, setDebouncedZip] = useState('');
// Debounce the search
useEffect(() => {
const timer = setTimeout(() => {
if (zipInput.length >= 3) {
setDebouncedZip(zipInput);
}
}, 500);
return () => clearTimeout(timer);
}, [zipInput]);
const handleSearch = (e) => {
e.preventDefault();
setSearchZip(zipInput);
};
return (
<div>
<form onSubmit={handleSearch}>
<input
type="text"
value={zipInput}
onChange={(e) => setZipInput(e.target.value)}
placeholder="Enter ZIP code..."
pattern="[0-9]*"
/>
<button type="submit">Lookup</button>
</form>
{(searchZip || debouncedZip) && (
<StateByZipCode zipCode={searchZip || debouncedZip} />
)}
</div>
);
}
export default ZipCodeLookup;
<template>
<div>
<div v-if="loading">Looking up ZIP code...</div>
<div v-else-if="error">Error: {{ error }}</div>
<div v-else>
<h2>States with ZIP code "{{ zipCode }}"</h2>
<p v-if="states.length === 0">No states found for this ZIP code</p>
<div v-else>
<p>Found {{ states.length }} result(s)</p>
<ul>
<li v-for="state in states" :key="state.id">
{{ state.state_name }}
</li>
</ul>
</div>
</div>
</div>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue';
const props = defineProps({
zipCode: {
type: String,
required: true
}
});
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';
const states = ref([]);
const loading = ref(false);
const error = ref(null);
const fetchStateByZipCode = async () => {
if (!props.zipCode) {
states.value = [];
return;
}
try {
loading.value = true;
error.value = null;
const params = new URLSearchParams({
apikey: API_KEY,
zipcode: props.zipCode,
lang: 'en',
fields: 'id,state_name,lang'
});
const response = await fetch(`${BASE_URL}?${params}`);
if (!response.ok) {
throw new Error('Failed to fetch state');
}
states.value = await response.json();
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
};
watch(() => props.zipCode, fetchStateByZipCode);
onMounted(fetchStateByZipCode);
</script>
import { Component, Input, OnInit, OnChanges } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Subject, debounceTime, distinctUntilChanged } from 'rxjs';
interface State {
id: string;
state_name: string;
lang: string;
state_cities?: Array<{ id: string; city_name: string }>;
state_zip_codes?: string[];
}
@Component({
selector: 'app-state-by-zipcode',
standalone: true,
imports: [CommonModule],
template: `
<div>
<div *ngIf="loading">Looking up ZIP code...</div>
<div *ngIf="error">Error: {{ error }}</div>
<div *ngIf="!loading && !error">
<h2>States with ZIP code "{{ zipCode }}"</h2>
<p *ngIf="states.length === 0">No states found for this ZIP code</p>
<div *ngIf="states.length > 0">
<p>Found {{ states.length }} result(s)</p>
<ul>
<li *ngFor="let state of states">{{ state.state_name }}</li>
</ul>
</div>
</div>
</div>
`
})
export class StateByZipCodeComponent implements OnInit, OnChanges {
@Input() zipCode!: string;
private readonly API_KEY = 'YOUR_API_KEY';
private readonly BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';
states: State[] = [];
loading = false;
error: string | null = null;
constructor(private http: HttpClient) {}
ngOnInit(): void {
this.fetchStateByZipCode();
}
ngOnChanges(): void {
this.fetchStateByZipCode();
}
private fetchStateByZipCode(): void {
if (!this.zipCode) {
this.states = [];
return;
}
this.loading = true;
this.error = null;
const params = new HttpParams()
.set('apikey', this.API_KEY)
.set('zipcode', this.zipCode)
.set('lang', 'en')
.set('fields', 'id,state_name,lang');
this.http.get<State[]>(this.BASE_URL, { params }).subscribe({
next: (data) => {
this.states = data;
this.loading = false;
},
error: (err) => {
this.error = err.message;
this.loading = false;
}
});
}
}
// ZIP code lookup with debounce
@Component({
selector: 'app-zipcode-lookup',
standalone: true,
imports: [CommonModule, FormsModule, StateByZipCodeComponent],
template: `
<div>
<form (ngSubmit)="search()">
<input
type="text"
[(ngModel)]="zipInput"
name="zipcode"
(ngModelChange)="onZipChange($event)"
placeholder="Enter ZIP code..."
/>
<button type="submit">Lookup</button>
</form>
<app-state-by-zipcode
*ngIf="searchZip"
[zipCode]="searchZip"
></app-state-by-zipcode>
</div>
`
})
export class ZipCodeLookupComponent {
zipInput = '';
searchZip = '';
private zipSubject = new Subject<string>();
constructor() {
this.zipSubject.pipe(
debounceTime(500),
distinctUntilChanged()
).subscribe(zip => {
if (zip.length >= 3) {
this.searchZip = zip;
}
});
}
onZipChange(value: string): void {
this.zipSubject.next(value);
}
search(): void {
this.searchZip = this.zipInput;
}
}
<?php
$apiKey = 'YOUR_API_KEY';
$baseUrl = 'https://api.countrydataapi.com/v1/states/zipCode';
function getStateByZipCode($zipCode, $apiKey) {
$baseUrl = 'https://api.countrydataapi.com/v1/states/zipCode';
$params = http_build_query([
'apikey' => $apiKey,
'zipcode' => $zipCode,
'lang' => 'en',
'fields' => 'id,state_name,lang'
]);
$url = $baseUrl . '?' . $params;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new Exception("HTTP Error: $httpCode");
}
return json_decode($response, true);
}
// Usage
try {
$zipCode = '90210';
$states = getStateByZipCode($zipCode, $apiKey);
echo "States with ZIP code '$zipCode':\n";
echo "Found " . count($states) . " result(s)\n\n";
foreach ($states as $state) {
echo "- " . $state['state_name'] . " (ID: " . $state['id'] . ")\n";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
// Validate ZIP code function
function validateZipCode($zipCode, $apiKey) {
$states = getStateByZipCode($zipCode, $apiKey);
if (empty($states)) {
return [
'valid' => false,
'message' => "Invalid ZIP code: $zipCode"
];
}
if (count($states) === 1) {
return [
'valid' => true,
'state' => $states[0]['state_name'],
'message' => "ZIP code $zipCode is in " . $states[0]['state_name']
];
}
$stateNames = array_map(function($s) {
return $s['state_name'];
}, $states);
return [
'valid' => true,
'states' => $stateNames,
'message' => "ZIP code $zipCode exists in: " . implode(', ', $stateNames)
];
}
// Example
$result = validateZipCode('10001', $apiKey);
echo $result['message'] . "\n";
?>
import requests
API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode'
def get_state_by_zipcode(zip_code):
"""Find the state(s) for a given postal code."""
params = {
'apikey': API_KEY,
'zipcode': zip_code,
'lang': 'en',
'fields': 'id,state_name,lang'
}
try:
response = requests.get(BASE_URL, params=params)
response.raise_for_status()
states = response.json()
return states
except requests.exceptions.RequestException as e:
print(f'Error fetching state by ZIP code: {e}')
raise
def validate_zipcode(zip_code):
"""Validate a ZIP code and return state information."""
states = get_state_by_zipcode(zip_code)
if not states:
return {
'valid': False,
'message': f'Invalid ZIP code: {zip_code}'
}
if len(states) == 1:
return {
'valid': True,
'state': states[0]['state_name'],
'state_id': states[0]['id'],
'message': f"ZIP code {zip_code} is in {states[0]['state_name']}"
}
state_names = [s['state_name'] for s in states]
return {
'valid': True,
'states': state_names,
'message': f"ZIP code {zip_code} exists in multiple locations: {', '.join(state_names)}"
}
# Usage
if __name__ == '__main__':
# US ZIP codes
us_zips = ['90210', '10001', '33101', '60601']
for zip_code in us_zips:
result = validate_zipcode(zip_code)
print(f"{zip_code}: {result['message']}")
# Async version with aiohttp
import aiohttp
import asyncio
async def get_state_by_zipcode_async(zip_code):
"""Find state by ZIP code asynchronously."""
params = {
'apikey': API_KEY,
'zipcode': zip_code,
'lang': 'en',
'fields': 'id,state_name,lang'
}
async with aiohttp.ClientSession() as session:
async with session.get(BASE_URL, params=params) as response:
if response.status == 200:
return await response.json()
else:
raise Exception(f'HTTP Error: {response.status}')
# Batch ZIP code validation
async def validate_multiple_zipcodes(zip_codes):
"""Validate multiple ZIP codes concurrently."""
tasks = [get_state_by_zipcode_async(z) for z in zip_codes]
results = await asyncio.gather(*tasks, return_exceptions=True)
return dict(zip(zip_codes, results))
# Usage
# zip_codes = ['90210', '10001', '33101', '60601', '98101']
# results = asyncio.run(validate_multiple_zipcodes(zip_codes))
# for zip_code, states in results.items():
# if isinstance(states, list) and states:
# print(f"{zip_code}: {states[0]['state_name']}")
# Search state by ZIP code
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=YOUR_API_KEY&zipcode=90210&lang=en&fields=id,state_name,lang"
# New York ZIP code
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=YOUR_API_KEY&zipcode=10001&lang=en"
# With pretty-printed JSON output
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=YOUR_API_KEY&zipcode=33101&lang=en" | json_pp
# European postal code
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=YOUR_API_KEY&zipcode=28001&lang=en"
# Get detailed state info including cities
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=YOUR_API_KEY&zipcode=60601&fields=id,state_name,state_cities"
# Save response to file
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=YOUR_API_KEY&zipcode=98101&lang=en" -o seattle_state.json
# Check multiple ZIP codes in sequence
for zip in 90210 10001 33101 60601; do
echo "ZIP: $zip"
curl -s "https://api.countrydataapi.com/v1/states/zipCode?apikey=YOUR_API_KEY&zipcode=$zip&fields=state_name" | json_pp
echo ""
done
The API may return the following error responses:
| Status Code | Description |
|---|---|
| 400 | Bad Request - Invalid parameters or missing ZIP code |
| 401 | Unauthorized - Invalid or missing API key |
| 403 | Forbidden - Insufficient permissions or token balance |
| 404 | Not Found - ZIP code not found |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error |
{
"statusCode": 404,
"message": "ZIP code not found",
"error": "Not Found"
}