Skip to main content
GET
/
v1
/
states
curl -X GET 'https://api.countrystatecity.in/v1/states' \
  -H 'X-CSCAPI-KEY: YOUR_API_KEY'
curl -X GET 'https://api.countrystatecity.in/v1/states?q=texas' \
  -H 'X-CSCAPI-KEY: YOUR_API_KEY'
import requests

response = requests.get(
  'https://api.countrystatecity.in/v1/states',
  headers={'X-CSCAPI-KEY': 'YOUR_API_KEY'}
)

states = response.json()
print(f'Found {len(states)} states')
const response = await fetch('https://api.countrystatecity.in/v1/states', {
  headers: { 'X-CSCAPI-KEY': 'YOUR_API_KEY' }
});

const states = await response.json();
console.log(`Found ${states.length} states`);
<?php
$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://api.countrystatecity.in/v1/states',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => array(
    'X-CSCAPI-KEY: YOUR_API_KEY'
  ),
));

$response = curl_exec($curl);
curl_close($curl);

$states = json_decode($response, true);
echo "Found " . count($states) . " states\n";
?>
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    url := "https://api.countrystatecity.in/v1/states"
    
    client := &http.Client{}
    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Add("X-CSCAPI-KEY", "YOUR_API_KEY")
    
    res, _ := client.Do(req)
    defer res.Body.Close()
    
    body, _ := ioutil.ReadAll(res.Body)
    
    var states []map[string]interface{}
    json.Unmarshal(body, &states)
    
    fmt.Printf("Found %d states\n", len(states))
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class AllStates {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.countrystatecity.in/v1/states"))
            .header("X-CSCAPI-KEY", "YOUR_API_KEY")
            .build();

        HttpResponse<String> response = client.send(request,
            HttpResponse.BodyHandlers.ofString());
            
        Gson gson = new Gson();
        Type listType = new TypeToken<List<Map<String, Object>>>(){}.getType();
        List<Map<String, Object>> states = gson.fromJson(response.body(), listType);
        
        System.out.println("Found " + states.size() + " states");
    }
}
require 'net/http'
require 'json'

uri = URI("https://api.countrystatecity.in/v1/states")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
request['X-CSCAPI-KEY'] = 'YOUR_API_KEY'

response = http.request(request)
states = JSON.parse(response.body)

puts "Found #{states.length} states"
[
  {
    "id": 4008,
    "name": "Maharashtra",
    "country_id": 101,
    "country_code": "IN",
    "iso2": "MH",
    "latitude": "19.75147980",
    "longitude": "75.71388840",
    "timezone": "Asia/Kolkata"
  }
]
[
  {
    "id": 4008,
    "name": "Maharashtra",
    "country_id": 101,
    "country_code": "IN",
    "iso2": "MH",
    "latitude": "19.75147980",
    "longitude": "75.71388840",
    "timezone": "Asia/Kolkata",
    "fips_code": "16",
    "iso3166_2": "IN-MH",
    "type": "state",
    "level": 1,
    "parent_id": null,
    "native": "महाराष्ट्र",
    "population": 112374333
  }
]
{
  "error": "Unauthorized. You shouldn't be here."
}
Retrieve a complete list of all states, provinces, regions, and territories from around the world with basic geographical information.
Availability: Supporter plan and above. Calling /states without filtering by country (bulkStates) is gated to Supporter+. Community/Starter users must call /countries/{iso2}/states instead. The fields returned also vary by tier — see Tier-Based Field Availability below.
Trim and order results: Add ?fields= to limit columns returned, or ?sort= to order the list. Both are available on Supporter+ plans. See the Field Filtering & Sorting guide for syntax and per-entity sortable fields.

Authentication

X-CSCAPI-KEY
string
required
Your API key for authentication

Query Parameters

q
string
Search filter on name. Case-insensitive match on name and native fields. Minimum 2 characters. Requires Supporter+ plan. Without this parameter, all results are returned (no plan restriction for search).

Response

id
integer
Unique identifier for the state/province
name
string
Official name of the state/province
country_id
integer
Unique identifier of the parent country
country_code
string
ISO2 code of the parent country
iso2
string
ISO2 code for the state/province
latitude
string
Approximate latitude coordinate of the state/province center
longitude
string
Approximate longitude coordinate of the state/province center
timezone
string
IANA timezone identifier (e.g., "Asia/Kolkata")
type
string
Administrative division type (e.g., "state", "province", "region"). Coordinates tier and above.
Additional fields like fips_code, iso3166_2, level, parent_id, native, population, translations, and wikiDataId are returned on higher tiers. See Tier-Based Field Availability below.
curl -X GET 'https://api.countrystatecity.in/v1/states' \
  -H 'X-CSCAPI-KEY: YOUR_API_KEY'
curl -X GET 'https://api.countrystatecity.in/v1/states?q=texas' \
  -H 'X-CSCAPI-KEY: YOUR_API_KEY'
import requests

response = requests.get(
  'https://api.countrystatecity.in/v1/states',
  headers={'X-CSCAPI-KEY': 'YOUR_API_KEY'}
)

states = response.json()
print(f'Found {len(states)} states')
const response = await fetch('https://api.countrystatecity.in/v1/states', {
  headers: { 'X-CSCAPI-KEY': 'YOUR_API_KEY' }
});

const states = await response.json();
console.log(`Found ${states.length} states`);
<?php
$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://api.countrystatecity.in/v1/states',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => array(
    'X-CSCAPI-KEY: YOUR_API_KEY'
  ),
));

$response = curl_exec($curl);
curl_close($curl);

$states = json_decode($response, true);
echo "Found " . count($states) . " states\n";
?>
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    url := "https://api.countrystatecity.in/v1/states"
    
    client := &http.Client{}
    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Add("X-CSCAPI-KEY", "YOUR_API_KEY")
    
    res, _ := client.Do(req)
    defer res.Body.Close()
    
    body, _ := ioutil.ReadAll(res.Body)
    
    var states []map[string]interface{}
    json.Unmarshal(body, &states)
    
    fmt.Printf("Found %d states\n", len(states))
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class AllStates {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.countrystatecity.in/v1/states"))
            .header("X-CSCAPI-KEY", "YOUR_API_KEY")
            .build();

        HttpResponse<String> response = client.send(request,
            HttpResponse.BodyHandlers.ofString());
            
        Gson gson = new Gson();
        Type listType = new TypeToken<List<Map<String, Object>>>(){}.getType();
        List<Map<String, Object>> states = gson.fromJson(response.body(), listType);
        
        System.out.println("Found " + states.size() + " states");
    }
}
require 'net/http'
require 'json'

uri = URI("https://api.countrystatecity.in/v1/states")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
request['X-CSCAPI-KEY'] = 'YOUR_API_KEY'

response = http.request(request)
states = JSON.parse(response.body)

puts "Found #{states.length} states"
[
  {
    "id": 4008,
    "name": "Maharashtra",
    "country_id": 101,
    "country_code": "IN",
    "iso2": "MH",
    "latitude": "19.75147980",
    "longitude": "75.71388840",
    "timezone": "Asia/Kolkata"
  }
]
[
  {
    "id": 4008,
    "name": "Maharashtra",
    "country_id": 101,
    "country_code": "IN",
    "iso2": "MH",
    "latitude": "19.75147980",
    "longitude": "75.71388840",
    "timezone": "Asia/Kolkata",
    "fips_code": "16",
    "iso3166_2": "IN-MH",
    "type": "state",
    "level": 1,
    "parent_id": null,
    "native": "महाराष्ट्र",
    "population": 112374333
  }
]
{
  "error": "Unauthorized. You shouldn't be here."
}

Common Use Cases

Analyze administrative divisions across different countries.
const analyzeStateTypes = (states) => {
  const typeCount = states.reduce((acc, state) => {
    acc[state.type] = (acc[state.type] || 0) + 1;
    return acc;
  }, {});
  
  console.log('State types distribution:', typeCount);
  return typeCount;
};
Use coordinate data for mapping applications.
const getStatesBounds = (states) => {
  const lats = states.map(s => parseFloat(s.latitude));
  const lngs = states.map(s => parseFloat(s.longitude));
  
  return {
    north: Math.max(...lats),
    south: Math.min(...lats),
    east: Math.max(...lngs),
    west: Math.min(...lngs)
  };
};
This endpoint returns a large dataset (5,299+ states). Consider using the filtered endpoints for better performance in most applications.

Tier-Based Field Availability

TierPlansFields
BasicCommunity, Starter, Legacyid, name, iso2, country_id, country_code, latitude, longitude, timezone
CoordinatesSupporterAll Basic + fips_code, iso3166_2, type, level, parent_id, native, population
FullProfessional, BusinessAll Coordinates + translations, wikiDataId
See Pricing for plan details.