API Documentation - Endpoints & Examples

Search states by country

Overview

This endpoint allows you to retrieve all states belonging to a specific country. It is perfect for building country-state dropdowns, filtering geographical data, or when you need to display all administrative divisions of a particular country.

Country Data API provides detailed information about +200 different countries

Authentication

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.


Request

HTTP GET

https://api.countrydataapi.com/v1/states/country

Returns the states that belong to that country.

Some examples of the structure

Country: USA, State: Colorado, City: Denver

Country: Spain, State: Comunidad Valenciana, City: Valencia

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

Query Params


Parameter Type Description
apikey required, token Account authentication key
country required, string Name of the country from which you want the states
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

Response

Sample 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"
    ]
  }
]

Code Examples

JavaScript (Fetch)

const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/country';

async function getStatesByCountry(countryName) {
  try {
    const params = new URLSearchParams({
      apikey: API_KEY,
      country: countryName,
      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 in ${countryName}:`, states);
    return states;
  } catch (error) {
    console.error('Error fetching states:', error);
    throw error;
  }
}

// Usage
getStatesByCountry('United States');
getStatesByCountry('Spain');

JavaScript (Axios)

import axios from 'axios';

const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/country';

async function getStatesByCountry(countryName) {
  try {
    const response = await axios.get(BASE_URL, {
      params: {
        apikey: API_KEY,
        country: countryName,
        lang: 'en',
        fields: 'id,state_name,lang'
      }
    });

    console.log(`States in ${countryName}:`, response.data);
    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      console.error('API Error:', error.response?.data || error.message);
    }
    throw error;
  }
}

// Usage
getStatesByCountry('Germany');

React

import { useState, useEffect } from 'react';

const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/country';

function StatesByCountry({ country }) {
  const [states, setStates] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchStates = async () => {
      if (!country) return;

      try {
        setLoading(true);
        setError(null);

        const params = new URLSearchParams({
          apikey: API_KEY,
          country: country,
          lang: 'en',
          fields: 'id,state_name,lang'
        });

        const response = await fetch(`${BASE_URL}?${params}`);

        if (!response.ok) {
          throw new Error('Failed to fetch states');
        }

        const data = await response.json();
        setStates(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchStates();
  }, [country]);

  if (loading) return <div>Loading states...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      <h2>States in {country}</h2>
      <p>Total: {states.length} states</p>
      <ul>
        {states.map((state) => (
          <li key={state.id}>{state.state_name}</li>
        ))}
      </ul>
    </div>
  );
}

// Country selector with states dropdown
function CountryStateSelector() {
  const [selectedCountry, setSelectedCountry] = useState('');
  const [states, setStates] = useState([]);
  const [selectedState, setSelectedState] = useState('');
  const [loading, setLoading] = useState(false);

  const countries = ['United States', 'Spain', 'Germany', 'France', 'Mexico'];

  useEffect(() => {
    if (!selectedCountry) {
      setStates([]);
      return;
    }

    const fetchStates = async () => {
      setLoading(true);
      const params = new URLSearchParams({
        apikey: API_KEY,
        country: selectedCountry,
        lang: 'en',
        fields: 'id,state_name'
      });

      try {
        const response = await fetch(`${BASE_URL}?${params}`);
        const data = await response.json();
        setStates(data);
        setSelectedState('');
      } catch (err) {
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    fetchStates();
  }, [selectedCountry]);

  return (
    <div>
      <select
        value={selectedCountry}
        onChange={(e) => setSelectedCountry(e.target.value)}
      >
        <option value="">Select Country</option>
        {countries.map((c) => (
          <option key={c} value={c}>{c}</option>
        ))}
      </select>

      <select
        value={selectedState}
        onChange={(e) => setSelectedState(e.target.value)}
        disabled={loading || !states.length}
      >
        <option value="">
          {loading ? 'Loading...' : 'Select State'}
        </option>
        {states.map((s) => (
          <option key={s.id} value={s.id}>{s.state_name}</option>
        ))}
      </select>
    </div>
  );
}

export default StatesByCountry;

Vue 3

<template>
  <div>
    <div v-if="loading">Loading states...</div>
    <div v-else-if="error">Error: {{ error }}</div>
    <div v-else>
      <h2>States in {{ country }}</h2>
      <p>Total: {{ states.length }} states</p>
      <ul>
        <li v-for="state in states" :key="state.id">
          {{ state.state_name }}
        </li>
      </ul>
    </div>
  </div>
</template>

<script setup>
import { ref, watch, onMounted } from 'vue';

const props = defineProps({
  country: {
    type: String,
    required: true
  }
});

const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/country';

const states = ref([]);
const loading = ref(true);
const error = ref(null);

const fetchStates = async () => {
  if (!props.country) return;

  try {
    loading.value = true;
    error.value = null;

    const params = new URLSearchParams({
      apikey: API_KEY,
      country: props.country,
      lang: 'en',
      fields: 'id,state_name,lang'
    });

    const response = await fetch(`${BASE_URL}?${params}`);

    if (!response.ok) {
      throw new Error('Failed to fetch states');
    }

    states.value = await response.json();
  } catch (err) {
    error.value = err.message;
  } finally {
    loading.value = false;
  }
};

watch(() => props.country, fetchStates);
onMounted(fetchStates);
</script>

Angular

import { Component, Input, OnInit, OnChanges } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { CommonModule } from '@angular/common';

interface State {
  id: string;
  state_name: string;
  lang: string;
  state_cities?: Array<{ id: string; city_name: string }>;
  state_zip_codes?: string[];
}

@Component({
  selector: 'app-states-by-country',
  standalone: true,
  imports: [CommonModule],
  template: `
    <div>
      <div *ngIf="loading">Loading states...</div>
      <div *ngIf="error">Error: {{ error }}</div>
      <div *ngIf="!loading && !error">
        <h2>States in {{ country }}</h2>
        <p>Total: {{ states.length }} states</p>
        <ul>
          <li *ngFor="let state of states">{{ state.state_name }}</li>
        </ul>
      </div>
    </div>
  `
})
export class StatesByCountryComponent implements OnInit, OnChanges {
  @Input() country!: string;

  private readonly API_KEY = 'YOUR_API_KEY';
  private readonly BASE_URL = 'https://api.countrydataapi.com/v1/states/country';

  states: State[] = [];
  loading = true;
  error: string | null = null;

  constructor(private http: HttpClient) {}

  ngOnInit(): void {
    this.fetchStates();
  }

  ngOnChanges(): void {
    this.fetchStates();
  }

  private fetchStates(): void {
    if (!this.country) return;

    this.loading = true;
    this.error = null;

    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('country', this.country)
      .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;
      }
    });
  }
}

PHP

<?php

$apiKey = 'YOUR_API_KEY';
$baseUrl = 'https://api.countrydataapi.com/v1/states/country';

function getStatesByCountry($countryName, $apiKey) {
    $baseUrl = 'https://api.countrydataapi.com/v1/states/country';

    $params = http_build_query([
        'apikey' => $apiKey,
        'country' => $countryName,
        '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 {
    $states = getStatesByCountry('United States', $apiKey);

    echo "States in United States:\n";
    echo "Total: " . count($states) . " states\n\n";

    foreach ($states as $state) {
        echo "- " . $state['state_name'] . " (ID: " . $state['id'] . ")\n";
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

// Alternative using file_get_contents
function getStatesByCountrySimple($countryName, $apiKey) {
    $baseUrl = 'https://api.countrydataapi.com/v1/states/country';

    $params = http_build_query([
        'apikey' => $apiKey,
        'country' => $countryName,
        'lang' => 'en',
        'fields' => 'id,state_name,lang'
    ]);

    $response = file_get_contents($baseUrl . '?' . $params);

    if ($response === false) {
        throw new Exception('Failed to fetch states');
    }

    return json_decode($response, true);
}
?>

Python

import requests

API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://api.countrydataapi.com/v1/states/country'

def get_states_by_country(country_name):
    """Fetch all states for a specific country."""
    params = {
        'apikey': API_KEY,
        'country': country_name,
        '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 states: {e}')
        raise

# Usage
if __name__ == '__main__':
    country = 'United States'
    states = get_states_by_country(country)

    print(f"States in {country}:")
    print(f"Total: {len(states)} states\n")

    for state in states[:10]:  # First 10 states
        print(f"  - {state['state_name']}")


# Async version with aiohttp
import aiohttp
import asyncio

async def get_states_by_country_async(country_name):
    """Fetch states for a country asynchronously."""
    params = {
        'apikey': API_KEY,
        'country': country_name,
        '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}')

# Fetch states for multiple countries in parallel
async def get_states_for_multiple_countries(countries):
    """Fetch states for multiple countries concurrently."""
    tasks = [get_states_by_country_async(country) for country in countries]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(countries, results))

# Usage
# countries = ['United States', 'Spain', 'Germany']
# results = asyncio.run(get_states_for_multiple_countries(countries))

cURL

# Get states for United States
curl -X GET "https://api.countrydataapi.com/v1/states/country?apikey=YOUR_API_KEY&country=United%20States&lang=en&fields=id,state_name,lang"

# Get states for Spain
curl -X GET "https://api.countrydataapi.com/v1/states/country?apikey=YOUR_API_KEY&country=Spain&lang=en"

# With pretty-printed JSON output
curl -X GET "https://api.countrydataapi.com/v1/states/country?apikey=YOUR_API_KEY&country=Germany&lang=en" | json_pp

# Get states with city information (NORMAL request)
curl -X GET "https://api.countrydataapi.com/v1/states/country?apikey=YOUR_API_KEY&country=France&fields=id,state_name,state_cities"

# Limit token usage
curl -X GET "https://api.countrydataapi.com/v1/states/country?apikey=YOUR_API_KEY&country=Mexico&limitToken=500"

# Save response to file
curl -X GET "https://api.countrydataapi.com/v1/states/country?apikey=YOUR_API_KEY&country=Canada&lang=en" -o canada_states.json

Error Handling

The API may return the following error responses:

Status Code Description
400 Bad Request - Invalid parameters or missing country
401 Unauthorized - Invalid or missing API key
403 Forbidden - Insufficient permissions or token balance
404 Not Found - Country not found
429 Too Many Requests - Rate limit exceeded
500 Internal Server Error

Error Response Example

{
  "statusCode": 404,
  "message": "Country not found",
  "error": "Not Found"
}