API Documentation - Endpoints & Examples

Country by City

Overview

The Country by City endpoint allows you to find the country that contains a specific city. This is useful for geocoding applications, address validation, and location-based services where you need to determine the country from a city name.


Authentication

All requests require an API key passed as a query parameter. You can obtain your API key by registering at CountryDataAPI.

Request

HTTP GET

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

Returns the country that has that city.

Some examples of the structure

Country: USA, State: Colorado, City: Denver

Country: Spain, State: Valencian Community, 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 API Key associated with your account
city required, string Name of the city that is located in the country
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": "f7a8b9c0-1234-5678-90ab-cdef12345678",
    "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"
  }
]

Code Examples

cURL

curl -X GET "https://api.countrydataapi.com/v1/countries/city?apikey=YOUR_API_KEY&city=Denver"

JavaScript (Fetch)

const API_KEY = 'YOUR_API_KEY';

async function getCountryByCity(cityName) {
  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/countries/city?apikey=${API_KEY}&city=${encodeURIComponent(cityName)}`
    );

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

    const countries = await response.json();
    console.log(countries);
    return countries;
  } catch (error) {
    console.error('Error fetching country by city:', error);
    throw error;
  }
}

// Find country for Denver
getCountryByCity('Denver');

JavaScript (Axios)

import axios from 'axios';

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

async function getCountryByCity(cityName) {
  try {
    const { data } = await axios.get(`${BASE_URL}/countries/city`, {
      params: {
        apikey: API_KEY,
        city: cityName,
        fields: 'id,country_name,country_short_iso,country_flag_png'
      }
    });

    console.log(data);
    return data;
  } catch (error) {
    console.error('Error fetching country by city:', error.response?.data || error.message);
    throw error;
  }
}

// Find country for Valencia
getCountryByCity('Valencia');

React

import { useState } from 'react';

const API_KEY = 'YOUR_API_KEY';

function CityToCountrySearch() {
  const [city, setCity] = useState('');
  const [countries, setCountries] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  async function handleSearch(e) {
    e.preventDefault();
    if (!city.trim()) return;

    setLoading(true);
    setError(null);

    try {
      const response = await fetch(
        `https://api.countrydataapi.com/v1/countries/city?apikey=${API_KEY}&city=${encodeURIComponent(city)}`
      );

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

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

  return (
    <div className="city-search">
      <h2>Find Country by City</h2>

      <form onSubmit={handleSearch}>
        <input
          type="text"
          value={city}
          onChange={(e) => setCity(e.target.value)}
          placeholder="Enter city name..."
        />
        <button type="submit" disabled={loading}>
          {loading ? 'Searching...' : 'Search'}
        </button>
      </form>

      {error && <div className="error">Error: {error}</div>}

      {countries.length > 0 && (
        <div className="results">
          <h3>Results ({countries.length} countries found)</h3>
          <p className="note">Note: Some cities exist in multiple countries</p>
          <ul>
            {countries.map((country) => (
              <li key={country.id}>
                <span className="flag">{country.country_flag}</span>
                <span className="name">{country.country_name}</span>
                <span className="code">({country.country_cca2})</span>
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

export default CityToCountrySearch;

Vue 3

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

const API_KEY = 'YOUR_API_KEY';

const city = ref('');
const countries = ref([]);
const loading = ref(false);
const error = ref(null);

async function searchByCity() {
  if (!city.value.trim()) return;

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

  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/countries/city?apikey=${API_KEY}&city=${encodeURIComponent(city.value)}`
    );

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

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

<template>
  <div class="city-search">
    <h2>Find Country by City</h2>

    <form @submit.prevent="searchByCity">
      <input
        v-model="city"
        type="text"
        placeholder="Enter city name..."
      />
      <button type="submit" :disabled="loading">
        {{ loading ? 'Searching...' : 'Search' }}
      </button>
    </form>

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

    <div v-if="countries.length > 0" class="results">
      <h3>Results ({{ countries.length }} countries found)</h3>
      <p class="note">Note: Some cities exist in multiple countries</p>
      <ul>
        <li v-for="country in countries" :key="country.id">
          <span class="flag">{{ country.country_flag }}</span>
          <span class="name">{{ country.country_name }}</span>
          <span class="code">({{ country.country_cca2 }})</span>
        </li>
      </ul>
    </div>
  </div>
</template>

Angular

import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

interface Country {
  id: string;
  country_name: string;
  country_short_iso: string;
  country_cca2: string;
  country_flag?: string;
}

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

      <form (ngSubmit)="searchByCity()">
        <input
          [(ngModel)]="city"
          name="city"
          type="text"
          placeholder="Enter city name..."
        />
        <button type="submit" [disabled]="loading">
          {{ loading ? 'Searching...' : 'Search' }}
        </button>
      </form>

      <div *ngIf="error" class="error">Error: {{ error }}</div>

      <div *ngIf="countries.length > 0" class="results">
        <h3>Results ({{ countries.length }} countries found)</h3>
        <p class="note">Note: Some cities exist in multiple countries</p>
        <ul>
          <li *ngFor="let country of countries">
            <span class="flag">{{ country.country_flag }}</span>
            <span class="name">{{ country.country_name }}</span>
            <span class="code">({{ country.country_cca2 }})</span>
          </li>
        </ul>
      </div>
    </div>
  `
})
export class CitySearchComponent {
  private http = inject(HttpClient);
  private readonly API_KEY = 'YOUR_API_KEY';
  private readonly BASE_URL = 'https://api.countrydataapi.com/v1';

  city = '';
  countries: Country[] = [];
  loading = false;
  error: string | null = null;

  searchByCity(): void {
    if (!this.city.trim()) return;

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

    this.http.get<Country[]>(
      `${this.BASE_URL}/countries/city`,
      {
        params: {
          apikey: this.API_KEY,
          city: this.city
        }
      }
    ).subscribe({
      next: (data) => {
        this.countries = data;
        this.loading = false;
      },
      error: (err) => {
        this.error = err.message;
        this.loading = false;
      }
    });
  }
}

Python

import requests
from urllib.parse import quote

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

def get_country_by_city(city_name):
    """Find the country that contains a specific city."""
    try:
        response = requests.get(
            f'{BASE_URL}/countries/city',
            params={
                'apikey': API_KEY,
                'city': city_name
            }
        )
        response.raise_for_status()

        countries = response.json()
        return countries
    except requests.exceptions.RequestException as e:
        print(f'Error fetching country by city: {e}')
        raise

# Usage
if __name__ == '__main__':
    # Find country for Denver
    city_name = 'Denver'
    countries = get_country_by_city(city_name)

    print(f"Countries containing '{city_name}':")
    for country in countries:
        print(f"  - {country['country_name']} ({country['country_short_iso']})")

    # Note: Some cities exist in multiple countries
    city_name = 'Valencia'
    countries = get_country_by_city(city_name)

    print(f"\nCountries containing '{city_name}':")
    for country in countries:
        print(f"  - {country['country_name']} ({country['country_short_iso']})")

PHP

<?php

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

function getCountryByCity($apiKey, $baseUrl, $cityName) {
    $url = sprintf(
        '%s/countries/city?apikey=%s&city=%s',
        $baseUrl,
        urlencode($apiKey),
        urlencode($cityName)
    );

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Accept: 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 {
    // Find country for Denver
    $cityName = 'Denver';
    $countries = getCountryByCity($apiKey, $baseUrl, $cityName);

    echo "Countries containing '$cityName':\n";
    foreach ($countries as $country) {
        echo sprintf(
            "  - %s (%s)\n",
            $country['country_name'],
            $country['country_short_iso']
        );
    }

    // Note: Some cities exist in multiple countries
    $cityName = 'Valencia';
    $countries = getCountryByCity($apiKey, $baseUrl, $cityName);

    echo "\nCountries containing '$cityName':\n";
    foreach ($countries as $country) {
        echo sprintf(
            "  - %s (%s)\n",
            $country['country_name'],
            $country['country_short_iso']
        );
    }
} catch (Exception $e) {
    echo 'Error: ' . $e->getMessage();
}

Error Handling

Status Code Description
200 Success - Returns array of countries
400 Bad Request - Missing required city parameter
401 Unauthorized - Invalid or missing API key
404 Not Found - No country found with that city
429 Too Many Requests - Rate limit exceeded
500 Internal Server Error - Something went wrong on our end

Error Response Example

{
  "statusCode": 404,
  "message": "No country found with city: UnknownCity",
  "error": "Not Found"
}

Notes

  • Duplicate city names: Many cities share the same name across different countries (e.g., "Valencia" exists in Spain and Venezuela). The API may return multiple countries when searching for such cities.
  • Case sensitivity: City names are case-insensitive.
  • Special characters: City names with special characters (accents, umlauts) should be URL-encoded.