API Documentation - Endpoints & Examples

Cities by State

Overview

This endpoint retrieves all cities that belong to a specific state. It is perfect for building location selectors, filtering geographical data by state, or when you need to display all cities within a particular administrative region.

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/cities/state

Returns a list of all cities from a state

Every 5 cities returned will consume 1 token

Query Params


Parameter Type Description
apikey required, token Account authentication key
state required, id or string State ID or name
limitToken optional, number 1000 (default). Maximum number of tokens you want to spend on this request
lang optional, lang en (default). Expected language of the response

Response

Response Example

[
  {
    "id": "d54ba796-1136-4776-9776-537fd5a857c9",
    "lang": "en",
    "city_name": "Bala Morghab"
  }
]

Code Examples

JavaScript (Fetch)

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

async function getCitiesByState(stateName) {
  try {
    const params = new URLSearchParams({
      apikey: API_KEY,
      state: stateName,
      lang: 'en'
    });

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

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

    const cities = await response.json();
    console.log(`Cities in ${stateName}:`, cities);
    return cities;
  } catch (error) {
    console.error('Error fetching cities by state:', error);
    throw error;
  }
}

// Usage
getCitiesByState('California');
getCitiesByState('Texas');
getCitiesByState('Florida');

JavaScript (Axios)

import axios from 'axios';

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

async function getCitiesByState(stateName) {
  try {
    const response = await axios.get(BASE_URL, {
      params: {
        apikey: API_KEY,
        state: stateName,
        lang: 'en'
      }
    });

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

// Usage
getCitiesByState('New York');

React

import { useState, useEffect } from 'react';

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

function CitiesByState({ state }) {
  const [cities, setCities] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchCities = async () => {
      if (!state) {
        setCities([]);
        return;
      }

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

        const params = new URLSearchParams({
          apikey: API_KEY,
          state: state,
          lang: 'en'
        });

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

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

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

    fetchCities();
  }, [state]);

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

  return (
    <div>
      <h2>Cities in {state}</h2>
      <p>Total: {cities.length} cities</p>
      <ul>
        {cities.map((city) => (
          <li key={city.id}>{city.city_name}</li>
        ))}
      </ul>
    </div>
  );
}

// State selector with cities dropdown
function StateCitySelector() {
  const [selectedState, setSelectedState] = useState('');
  const [cities, setCities] = useState([]);
  const [selectedCity, setSelectedCity] = useState('');
  const [loading, setLoading] = useState(false);

  const states = ['California', 'Texas', 'Florida', 'New York', 'Colorado'];

  useEffect(() => {
    if (!selectedState) {
      setCities([]);
      return;
    }

    const fetchCities = async () => {
      setLoading(true);
      const params = new URLSearchParams({
        apikey: API_KEY,
        state: selectedState,
        lang: 'en'
      });

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

    fetchCities();
  }, [selectedState]);

  return (
    <div>
      <select
        value={selectedState}
        onChange={(e) => setSelectedState(e.target.value)}
      >
        <option value="">Select State</option>
        {states.map((s) => (
          <option key={s} value={s}>{s}</option>
        ))}
      </select>

      <select
        value={selectedCity}
        onChange={(e) => setSelectedCity(e.target.value)}
        disabled={loading || !cities.length}
      >
        <option value="">
          {loading ? 'Loading...' : 'Select City'}
        </option>
        {cities.map((c) => (
          <option key={c.id} value={c.id}>{c.city_name}</option>
        ))}
      </select>
    </div>
  );
}

export default CitiesByState;

Vue 3

<template>
  <div>
    <div v-if="loading">Loading cities...</div>
    <div v-else-if="error">Error: {{ error }}</div>
    <div v-else>
      <h2>Cities in {{ state }}</h2>
      <p>Total: {{ cities.length }} cities</p>
      <ul>
        <li v-for="city in cities" :key="city.id">
          {{ city.city_name }}
        </li>
      </ul>
    </div>
  </div>
</template>

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

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

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

const cities = ref([]);
const loading = ref(false);
const error = ref(null);

const fetchCities = async () => {
  if (!props.state) {
    cities.value = [];
    return;
  }

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

    const params = new URLSearchParams({
      apikey: API_KEY,
      state: props.state,
      lang: 'en'
    });

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

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

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

watch(() => props.state, fetchCities);
onMounted(fetchCities);
</script>

Angular

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';

interface City {
  id: string;
  city_name: string;
  lang: string;
}

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

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

  cities: City[] = [];
  loading = false;
  error: string | null = null;

  constructor(private http: HttpClient) {}

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

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

  private fetchCities(): void {
    if (!this.state) {
      this.cities = [];
      return;
    }

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

    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('state', this.state)
      .set('lang', 'en');

    this.http.get<City[]>(this.BASE_URL, { params }).subscribe({
      next: (data) => {
        this.cities = data;
        this.loading = false;
      },
      error: (err) => {
        this.error = err.message;
        this.loading = false;
      }
    });
  }
}

// State-City selector component
@Component({
  selector: 'app-state-city-selector',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div>
      <select [(ngModel)]="selectedState" (ngModelChange)="onStateChange()">
        <option value="">Select State</option>
        <option *ngFor="let s of states" [value]="s">{{ s }}</option>
      </select>

      <select
        [(ngModel)]="selectedCity"
        [disabled]="loading || cities.length === 0"
      >
        <option value="">{{ loading ? 'Loading...' : 'Select City' }}</option>
        <option *ngFor="let c of cities" [value]="c.id">
          {{ c.city_name }}
        </option>
      </select>
    </div>
  `
})
export class StateCitySelectorComponent {
  private readonly API_KEY = 'YOUR_API_KEY';
  private readonly BASE_URL = 'https://api.countrydataapi.com/v1/cities/state';

  states = ['California', 'Texas', 'Florida', 'New York', 'Colorado'];
  selectedState = '';
  selectedCity = '';
  cities: City[] = [];
  loading = false;

  constructor(private http: HttpClient) {}

  onStateChange(): void {
    if (!this.selectedState) {
      this.cities = [];
      return;
    }

    this.loading = true;
    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('state', this.selectedState)
      .set('lang', 'en');

    this.http.get<City[]>(this.BASE_URL, { params }).subscribe({
      next: (data) => {
        this.cities = data;
        this.selectedCity = '';
        this.loading = false;
      },
      error: () => {
        this.loading = false;
      }
    });
  }
}

PHP

<?php

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

function getCitiesByState($stateName, $apiKey, $limitToken = 1000) {
    $baseUrl = 'https://api.countrydataapi.com/v1/cities/state';

    $params = http_build_query([
        'apikey' => $apiKey,
        'state' => $stateName,
        'lang' => 'en',
        'limitToken' => $limitToken
    ]);

    $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 {
    $stateName = 'California';
    $cities = getCitiesByState($stateName, $apiKey);

    echo "Cities in $stateName:\n";
    echo "Total: " . count($cities) . " cities\n\n";

    // Display first 20 cities
    foreach (array_slice($cities, 0, 20) as $city) {
        echo "- " . $city['city_name'] . "\n";
    }

    if (count($cities) > 20) {
        echo "... and " . (count($cities) - 20) . " more cities\n";
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

// Calculate token usage
function calculateTokenUsage($cityCount) {
    return ceil($cityCount / 5);
}

$cities = getCitiesByState('Texas', $apiKey);
echo "\nCities in Texas: " . count($cities) . "\n";
echo "Tokens consumed: " . calculateTokenUsage(count($cities)) . "\n";
?>

Python

import requests

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

def get_cities_by_state(state_name, limit_token=1000):
    """Fetch all cities for a specific state."""
    params = {
        'apikey': API_KEY,
        'state': state_name,
        'lang': 'en',
        'limitToken': limit_token
    }

    try:
        response = requests.get(BASE_URL, params=params)
        response.raise_for_status()

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

def calculate_token_usage(city_count):
    """Calculate tokens consumed (5 cities = 1 token)."""
    return (city_count + 4) // 5

# Usage
if __name__ == '__main__':
    state = 'California'
    cities = get_cities_by_state(state)

    print(f"Cities in {state}:")
    print(f"Total: {len(cities)} cities")
    print(f"Tokens consumed: {calculate_token_usage(len(cities))}")
    print("\nFirst 10 cities:")

    for city in cities[:10]:
        print(f"  - {city['city_name']}")


# Async version with aiohttp
import aiohttp
import asyncio

async def get_cities_by_state_async(state_name):
    """Fetch cities by state asynchronously."""
    params = {
        'apikey': API_KEY,
        'state': state_name,
        'lang': 'en'
    }

    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 cities for multiple states concurrently
async def get_cities_for_multiple_states(states):
    """Fetch cities for multiple states concurrently."""
    tasks = [get_cities_by_state_async(state) for state in states]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(states, results))

# Usage
# states = ['California', 'Texas', 'Florida', 'New York']
# results = asyncio.run(get_cities_for_multiple_states(states))
# for state, cities in results.items():
#     if isinstance(cities, list):
#         print(f"{state}: {len(cities)} cities")

cURL

# Get cities for California
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=YOUR_API_KEY&state=California&lang=en"

# Get cities for Texas
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=YOUR_API_KEY&state=Texas&lang=en"

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

# Limit token usage
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=YOUR_API_KEY&state=New%20York&limitToken=500"

# Get cities by state ID
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=YOUR_API_KEY&state=8dd25479-067a-43b0-ac4a-8e7faf2bcafb&lang=en"

# Save response to file
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=YOUR_API_KEY&state=Colorado&lang=en" -o colorado_cities.json

# Get cities for multiple states
for state in California Texas Florida; do
  echo "State: $state"
  curl -s "https://api.countrydataapi.com/v1/cities/state?apikey=YOUR_API_KEY&state=$state" | json_pp | head -20
  echo ""
done

Error Handling

The API may return the following error responses:

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

Error Response Example

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

Token Consumption

Every 5 cities returned will consume 1 token. For example:

  • 50 cities = 10 tokens
  • 100 cities = 20 tokens
  • 500 cities = 100 tokens

Use the limitToken parameter to control your token usage.