API Documentation - Endpoints & Examples

Search Country by State

Overview

The Search Country by State endpoint allows you to find countries that contain a specific state or administrative division. This is particularly useful for location-based applications, address validation systems, and geographic data analysis.

Country Data API provides detailed information about +200 different countries

Authentication

All API requests require authentication using an API key passed as a query parameter.

https://api.countrydataapi.com/v1/countries/state?apikey=YOUR_API_KEY&state=Colorado

Request

HTTP GET

https://api.countrydataapi.com/v1/countries/state

Return the country that has that state.

Some examples of the structure

Country: USA, State: Colorado, City: Denver

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

Relevant Information

Keep in mind that there are many cities with the same name.

There are 4 types of operations:

  • BASIC: Returns the fields id, lang, country_name, country_short_iso, country_phone_code, country_cca2, country_ccn3, country_cca3, country_cioc.

  • NORMAL: Returns the previous fields and adds country_independent, country_status, country_unMember, country_flag, country_map_googleMaps, country_map_openStreetMaps, country_fifa, country_flag_png, country_flag_svg, country_flag_alt, country_coatOfArms_png, country_coatOfArms_svg, country_startofWeek, country_continent_code, country_current_currency, country_GDP, country_location, country_land, country_terrain, country_climate, country_natural_hazards, country_note, country_history, country_GDP_per_capita_PPP, country_life_expectancy, country_median_age, country_birth_rate, country_death_rate, country_sex_ratio, country_literacy, country_roadways, country_airports, country_railways, country_waterways, country_heliports, country_airports_paved, country_wikipedia_url.

  • ADVANCED: Returns the previous fields and adds country_car_info, _country_idd_info.

  • ALL: Returns the previous fields and adds country_tld, country_capital, country_altSpellings, country_latLng, country_borders, country_timezones, country_continents, country_currencies, country_languages, country_translations, country_capital_info, country_demonyms, country_name.nativeName.

Each country returned with the BASIC method will cost 1 tokens.

Each country returned with the NORMAL method will cost 2 tokens.

Each country returned with the ADVANCED method will cost 3 tokens.

Each country returned with the ALL method will cost 4 tokens.

Query Params


Parameter Type Description
apikey required, token Authentication key of the account
state required, string State of the country you want to search for
limitToken optional, number 1000 (default). Maximum number of countries to be returned
lang optional, lang en (default). Expected language of the response
fields optional, string id,lang,country_name (default). Expected fields in the response

Response

Example Response

[
  {
    "id": "33be30c5-80fc-429d-bf10-bd11f2e3e84c",
    "lang": "en",
    "country_name": "United States",
    "country_short_iso": "US",
    "country_phone_code": "1",
    "country_cca2": "US",
    "country_ccn3": "840",
    "country_cca3": "USA",
    "country_cioc": "USA",
    "country_independent": true,
    "country_status": "officially-assigned",
    "country_unMember": true,
    "country_capital": ["Washington, D.C."],
    "country_region": "Americas",
    "country_subregion": "Northern America",
    "country_flag": "flag-emoji",
    "country_flag_png": "https://flagcdn.com/w320/us.png",
    "country_flag_svg": "https://flagcdn.com/us.svg"
  }
]

Code Examples

cURL

# Search country by state name
curl -X GET "https://api.countrydataapi.com/v1/countries/state?apikey=YOUR_API_KEY&state=Colorado"

# With specific fields (BASIC)
curl -X GET "https://api.countrydataapi.com/v1/countries/state?apikey=YOUR_API_KEY&state=California&fields=id,lang,country_name,country_cca2"

# With NORMAL fields
curl -X GET "https://api.countrydataapi.com/v1/countries/state?apikey=YOUR_API_KEY&state=Bavaria&fields=id,lang,country_name,country_flag_png,country_capital"

# Search with different language response
curl -X GET "https://api.countrydataapi.com/v1/countries/state?apikey=YOUR_API_KEY&state=Catalonia&lang=es"

JavaScript (Fetch)

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

// Search country by state
async function searchCountryByState(stateName, options = {}) {
  const params = new URLSearchParams({
    apikey: API_KEY,
    state: stateName,
    ...options
  });

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

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error searching country by state:', error);
    throw error;
  }
}

// Usage examples
searchCountryByState('Colorado')
  .then(countries => {
    console.log('Countries with Colorado state:', countries);
  });

// With specific fields
searchCountryByState('Texas', {
  fields: 'id,lang,country_name,country_flag_png,country_capital'
})
  .then(countries => {
    console.log('Texas state results:', countries);
  });

// Search European state
searchCountryByState('Bavaria', { lang: 'de' })
  .then(countries => {
    console.log('Bavaria results (German):', countries);
  });

JavaScript (Axios)

import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.countrydataapi.com/v1/countries',
  params: {
    apikey: 'YOUR_API_KEY'
  }
});

// Search country by state
async function searchCountryByState(stateName, options = {}) {
  try {
    const response = await apiClient.get('/state', {
      params: {
        state: stateName,
        ...options
      }
    });
    return response.data;
  } catch (error) {
    if (error.response) {
      console.error('API Error:', error.response.status, error.response.data);
    } else {
      console.error('Network Error:', error.message);
    }
    throw error;
  }
}

// State lookup service
const stateLookupService = {
  async findCountryByState(stateName) {
    return searchCountryByState(stateName);
  },

  async getStateCountryDetails(stateName) {
    return searchCountryByState(stateName, {
      fields: 'id,lang,country_name,country_flag_png,country_capital,country_region,country_subregion'
    });
  },

  async searchStateInLanguage(stateName, lang) {
    return searchCountryByState(stateName, { lang });
  }
};

// Usage
stateLookupService.findCountryByState('New York')
  .then(result => console.log('New York state country:', result));

React

import { useState, useCallback } from 'react';

const API_KEY = 'YOUR_API_KEY';

function useStateSearch() {
  const [countries, setCountries] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const searchByState = useCallback(async (stateName, options = {}) => {
    if (!stateName.trim()) {
      setCountries([]);
      return;
    }

    setLoading(true);
    setError(null);

    const params = new URLSearchParams({
      apikey: API_KEY,
      state: stateName,
      fields: 'id,lang,country_name,country_flag_png,country_capital,country_region',
      ...options
    });

    try {
      const response = await fetch(
        `https://api.countrydataapi.com/v1/countries/state?${params}`
      );

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const data = await response.json();
      setCountries(data);
    } catch (err) {
      setError(err.message);
      setCountries([]);
    } finally {
      setLoading(false);
    }
  }, []);

  return { countries, loading, error, searchByState };
}

function StateSearchComponent() {
  const [stateInput, setStateInput] = useState('');
  const { countries, loading, error, searchByState } = useStateSearch();

  const handleSearch = (e) => {
    e.preventDefault();
    searchByState(stateInput);
  };

  return (
    <div className="state-search-container">
      <h2>Find Country by State</h2>

      <form onSubmit={handleSearch} className="search-form">
        <input
          type="text"
          value={stateInput}
          onChange={(e) => setStateInput(e.target.value)}
          placeholder="Enter state name (e.g., California, Bavaria)"
          className="state-input"
        />
        <button type="submit" disabled={loading || !stateInput.trim()}>
          {loading ? 'Searching...' : 'Search'}
        </button>
      </form>

      {error && (
        <div className="error-message">
          Error: {error}
        </div>
      )}

      {countries.length > 0 && (
        <div className="results">
          <h3>Results for "{stateInput}"</h3>
          {countries.map((country) => (
            <div key={country.id} className="country-card">
              <img
                src={country.country_flag_png}
                alt={`${country.country_name} flag`}
                className="country-flag"
              />
              <div className="country-info">
                <h4>{country.country_name}</h4>
                <p>Capital: {country.country_capital?.join(', ') || 'N/A'}</p>
                <p>Region: {country.country_region}</p>
              </div>
            </div>
          ))}
        </div>
      )}

      {!loading && countries.length === 0 && stateInput && (
        <p className="no-results">No countries found with that state.</p>
      )}
    </div>
  );
}

export default StateSearchComponent;

Vue 3

<template>
  <div class="state-search">
    <h2>Find Country by State</h2>

    <form @submit.prevent="handleSearch" class="search-form">
      <input
        v-model="stateInput"
        type="text"
        placeholder="Enter state name (e.g., Texas, Catalonia)"
        class="state-input"
      />
      <button type="submit" :disabled="loading || !stateInput.trim()">
        {{ loading ? 'Searching...' : 'Search' }}
      </button>
    </form>

    <div v-if="error" class="error-message">
      {{ error }}
    </div>

    <div v-if="countries.length > 0" class="results">
      <h3>Results for "{{ lastSearch }}"</h3>
      <div
        v-for="country in countries"
        :key="country.id"
        class="country-card"
      >
        <img
          :src="country.country_flag_png"
          :alt="`${country.country_name} flag`"
          class="country-flag"
        />
        <div class="country-details">
          <h4>{{ country.country_name }}</h4>
          <p><strong>Capital:</strong> {{ formatCapital(country.country_capital) }}</p>
          <p><strong>Region:</strong> {{ country.country_region }}</p>
          <p><strong>Subregion:</strong> {{ country.country_subregion }}</p>
        </div>
      </div>
    </div>

    <p v-if="!loading && searchPerformed && countries.length === 0" class="no-results">
      No countries found with state "{{ lastSearch }}".
    </p>
  </div>
</template>

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

const API_KEY = 'YOUR_API_KEY';

const stateInput = ref('');
const lastSearch = ref('');
const countries = ref([]);
const loading = ref(false);
const error = ref(null);
const searchPerformed = ref(false);

const formatCapital = (capital) => {
  return capital?.join(', ') || 'N/A';
};

const handleSearch = async () => {
  if (!stateInput.value.trim()) return;

  loading.value = true;
  error.value = null;
  searchPerformed.value = true;
  lastSearch.value = stateInput.value;

  const params = new URLSearchParams({
    apikey: API_KEY,
    state: stateInput.value,
    fields: 'id,lang,country_name,country_flag_png,country_capital,country_region,country_subregion'
  });

  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/countries/state?${params}`
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    countries.value = await response.json();
  } catch (err) {
    error.value = err.message;
    countries.value = [];
  } finally {
    loading.value = false;
  }
};
</script>

<style scoped>
.state-search {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

.search-form {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.state-input {
  flex: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

button {
  padding: 10px 20px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:disabled {
  background-color: #ccc;
  cursor: not-allowed;
}

.country-card {
  display: flex;
  gap: 15px;
  padding: 15px;
  border: 1px solid #eee;
  border-radius: 8px;
  margin-bottom: 10px;
}

.country-flag {
  width: 80px;
  height: auto;
  border-radius: 4px;
}

.error-message {
  color: #dc3545;
  padding: 10px;
  background-color: #f8d7da;
  border-radius: 4px;
}

.no-results {
  text-align: center;
  color: #666;
}
</style>

Angular

// state-search.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, catchError, throwError } from 'rxjs';

export interface Country {
  id: string;
  lang: string;
  country_name: string;
  country_flag_png?: string;
  country_capital?: string[];
  country_region?: string;
  country_subregion?: string;
  country_cca2?: string;
}

@Injectable({
  providedIn: 'root'
})
export class StateSearchService {
  private http = inject(HttpClient);
  private readonly API_KEY = 'YOUR_API_KEY';
  private readonly BASE_URL = 'https://api.countrydataapi.com/v1/countries';

  searchByState(stateName: string, options: Record<string, string> = {}): Observable<Country[]> {
    let params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('state', stateName)
      .set('fields', 'id,lang,country_name,country_flag_png,country_capital,country_region,country_subregion');

    Object.entries(options).forEach(([key, value]) => {
      params = params.set(key, value);
    });

    return this.http.get<Country[]>(`${this.BASE_URL}/state`, { params }).pipe(
      catchError(error => {
        console.error('State search error:', error);
        return throwError(() => new Error('Failed to search country by state'));
      })
    );
  }
}

// state-search.component.ts
import { Component, inject, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { StateSearchService, Country } from './state-search.service';

@Component({
  selector: 'app-state-search',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div class="state-search-container">
      <h2>Find Country by State</h2>

      <form (ngSubmit)="searchState()" class="search-form">
        <input
          type="text"
          [(ngModel)]="stateInput"
          name="stateInput"
          placeholder="Enter state name (e.g., Florida, Ontario)"
          class="state-input"
        />
        <button type="submit" [disabled]="loading() || !stateInput.trim()">
          {{ loading() ? 'Searching...' : 'Search' }}
        </button>
      </form>

      <div *ngIf="error()" class="error-message">
        {{ error() }}
      </div>

      <div *ngIf="countries().length > 0" class="results">
        <h3>Results for "{{ lastSearch() }}"</h3>
        <div *ngFor="let country of countries()" class="country-card">
          <img
            [src]="country.country_flag_png"
            [alt]="country.country_name + ' flag'"
            class="country-flag"
          />
          <div class="country-info">
            <h4>{{ country.country_name }}</h4>
            <p><strong>Capital:</strong> {{ formatCapital(country.country_capital) }}</p>
            <p><strong>Region:</strong> {{ country.country_region }}</p>
            <p><strong>Subregion:</strong> {{ country.country_subregion }}</p>
          </div>
        </div>
      </div>

      <p *ngIf="!loading() && searchPerformed() && countries().length === 0" class="no-results">
        No countries found with state "{{ lastSearch() }}".
      </p>
    </div>
  `,
  styles: [`
    .state-search-container {
      max-width: 600px;
      margin: 0 auto;
      padding: 20px;
    }
    .search-form {
      display: flex;
      gap: 10px;
      margin-bottom: 20px;
    }
    .state-input {
      flex: 1;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 4px;
    }
    button {
      padding: 10px 20px;
      background-color: #4CAF50;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
    button:disabled {
      background-color: #ccc;
    }
    .country-card {
      display: flex;
      gap: 15px;
      padding: 15px;
      border: 1px solid #eee;
      border-radius: 8px;
      margin-bottom: 10px;
    }
    .country-flag {
      width: 80px;
      height: auto;
      border-radius: 4px;
    }
    .error-message {
      color: #dc3545;
      padding: 10px;
      background-color: #f8d7da;
      border-radius: 4px;
    }
  `]
})
export class StateSearchComponent {
  private stateSearchService = inject(StateSearchService);

  stateInput = '';
  countries = signal<Country[]>([]);
  loading = signal(false);
  error = signal<string | null>(null);
  searchPerformed = signal(false);
  lastSearch = signal('');

  formatCapital(capital?: string[]): string {
    return capital?.join(', ') || 'N/A';
  }

  searchState(): void {
    if (!this.stateInput.trim()) return;

    this.loading.set(true);
    this.error.set(null);
    this.searchPerformed.set(true);
    this.lastSearch.set(this.stateInput);

    this.stateSearchService.searchByState(this.stateInput).subscribe({
      next: (data) => {
        this.countries.set(data);
        this.loading.set(false);
      },
      error: (err) => {
        this.error.set(err.message);
        this.countries.set([]);
        this.loading.set(false);
      }
    });
  }
}

Python

import requests
from typing import Optional, List, Dict, Any
from dataclasses import dataclass

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.countrydataapi.com/v1/countries"

@dataclass
class StateSearchResult:
    """Represents a country found by state search"""
    id: str
    name: str
    flag_url: str
    capital: List[str]
    region: str
    subregion: str

def search_country_by_state(
    state_name: str,
    fields: Optional[str] = None,
    lang: str = "en",
    limit_token: int = 1000
) -> List[Dict[str, Any]]:
    """
    Search for countries by state name.

    Args:
        state_name: The state name to search for
        fields: Comma-separated list of fields to return
        lang: Language for the response (default: "en")
        limit_token: Maximum number of results (default: 1000)

    Returns:
        List of countries containing the specified state
    """
    params = {
        "apikey": API_KEY,
        "state": state_name,
        "lang": lang,
        "limitToken": limit_token
    }

    if fields:
        params["fields"] = fields

    try:
        response = requests.get(f"{BASE_URL}/state", params=params)
        response.raise_for_status()
        return response.json()
    except requests.exceptions.HTTPError as e:
        print(f"HTTP Error: {e}")
        raise
    except requests.exceptions.RequestException as e:
        print(f"Request Error: {e}")
        raise

def get_country_by_state_with_details(state_name: str) -> List[StateSearchResult]:
    """
    Get detailed country information by state name.

    Args:
        state_name: The state name to search for

    Returns:
        List of StateSearchResult objects
    """
    fields = "id,lang,country_name,country_flag_png,country_capital,country_region,country_subregion"

    countries = search_country_by_state(state_name, fields=fields)

    results = []
    for country in countries:
        results.append(StateSearchResult(
            id=country.get("id", ""),
            name=country.get("country_name", ""),
            flag_url=country.get("country_flag_png", ""),
            capital=country.get("country_capital", []),
            region=country.get("country_region", ""),
            subregion=country.get("country_subregion", "")
        ))

    return results

# Example usage
if __name__ == "__main__":
    # Basic search
    print("Searching for countries with 'California' state...")
    countries = search_country_by_state("California")
    for country in countries:
        print(f"  - {country.get('country_name')}")

    # Search with detailed results
    print("\nSearching for countries with 'Bavaria' state...")
    results = get_country_by_state_with_details("Bavaria")
    for result in results:
        print(f"  - {result.name}")
        print(f"    Capital: {', '.join(result.capital)}")
        print(f"    Region: {result.region}")

    # Search European state
    print("\nSearching for 'Catalonia' in Spanish...")
    countries = search_country_by_state("Catalonia", lang="es")
    for country in countries:
        print(f"  - {country.get('country_name')}")

PHP

<?php

class CountryStateSearch
{
    private string $apiKey;
    private string $baseUrl = 'https://api.countrydataapi.com/v1/countries';

    public function __construct(string $apiKey)
    {
        $this->apiKey = $apiKey;
    }

    /**
     * Search for countries by state name
     *
     * @param string $stateName The state name to search for
     * @param array $options Additional options (fields, lang, limitToken)
     * @return array List of countries
     * @throws Exception
     */
    public function searchByState(string $stateName, array $options = []): array
    {
        $params = array_merge([
            'apikey' => $this->apiKey,
            'state' => $stateName
        ], $options);

        $url = $this->baseUrl . '/state?' . http_build_query($params);

        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_HTTPHEADER => [
                'Accept: application/json'
            ]
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new Exception("cURL Error: $error");
        }

        if ($httpCode !== 200) {
            throw new Exception("HTTP Error: $httpCode");
        }

        return json_decode($response, true) ?? [];
    }

    /**
     * Get detailed country information by state
     *
     * @param string $stateName The state name to search for
     * @return array Countries with detailed information
     */
    public function getCountryDetailsByState(string $stateName): array
    {
        return $this->searchByState($stateName, [
            'fields' => 'id,lang,country_name,country_flag_png,country_capital,country_region,country_subregion'
        ]);
    }

    /**
     * Search for state in a specific language
     *
     * @param string $stateName The state name to search for
     * @param string $lang Language code (e.g., 'es', 'de', 'fr')
     * @return array Countries in the specified language
     */
    public function searchStateInLanguage(string $stateName, string $lang): array
    {
        return $this->searchByState($stateName, ['lang' => $lang]);
    }
}

// Example usage
$apiKey = 'YOUR_API_KEY';
$stateSearch = new CountryStateSearch($apiKey);

try {
    // Basic search
    echo "Searching for countries with 'Texas' state:\n";
    $countries = $stateSearch->searchByState('Texas');
    foreach ($countries as $country) {
        echo "  - " . $country['country_name'] . "\n";
    }

    // Search with details
    echo "\nSearching for 'Ontario' with details:\n";
    $details = $stateSearch->getCountryDetailsByState('Ontario');
    foreach ($details as $country) {
        echo "  - " . $country['country_name'] . "\n";
        echo "    Capital: " . implode(', ', $country['country_capital'] ?? []) . "\n";
        echo "    Region: " . ($country['country_region'] ?? 'N/A') . "\n";
    }

    // Search in German
    echo "\nSearching for 'Bayern' in German:\n";
    $german = $stateSearch->searchStateInLanguage('Bayern', 'de');
    foreach ($german as $country) {
        echo "  - " . $country['country_name'] . "\n";
    }

} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
?>

Error Handling

Status Code Description
200 Success - Returns array of countries
400 Bad Request - Invalid or missing state parameter
401 Unauthorized - Invalid or missing API key
404 Not Found - No countries found with the given state
429 Too Many Requests - Rate limit exceeded
500 Internal Server Error - Server-side error