curl -X GET 'https://api.countrystatecity.in/v1/countries/IN/states/MH' \
-H 'X-CSCAPI-KEY: YOUR_API_KEY'
curl -X GET 'https://api.countrystatecity.in/v1/countries/IN/states/MH?include_translations=true' \
-H 'X-CSCAPI-KEY: YOUR_API_KEY'
import requests
def get_state_details(country_code, state_code):
response = requests.get(
f'https://api.countrystatecity.in/v1/countries/{country_code}/states/{state_code}',
headers={'X-CSCAPI-KEY': 'YOUR_API_KEY'}
)
if response.ok:
state = response.json()
print(f"{state['name']} is located at {state['latitude']}, {state['longitude']}")
return state
else:
print('State not found')
return None
state = get_state_details('IN', 'MH')
const getStateDetails = async (countryCode, stateCode) => {
const response = await fetch(
`https://api.countrystatecity.in/v1/countries/${countryCode}/states/${stateCode}`,
{
headers: { 'X-CSCAPI-KEY': 'YOUR_API_KEY' }
}
);
if (response.ok) {
const state = await response.json();
console.log(`${state.name} is located at ${state.latitude}, ${state.longitude}`);
return state;
} else {
console.error('State not found');
}
};
getStateDetails('IN', 'MH');
<?php
function getStateDetails($countryCode, $stateCode) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.countrystatecity.in/v1/countries/{$countryCode}/states/{$stateCode}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array(
'X-CSCAPI-KEY: YOUR_API_KEY'
),
));
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($httpCode == 200) {
$state = json_decode($response, true);
echo $state['name'] . " is located at " . $state['latitude'] . ", " . $state['longitude'] . "\n";
return $state;
} else {
echo "State not found\n";
return null;
}
}
$state = getStateDetails('IN', 'MH');
?>
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func getStateDetails(countryCode, stateCode string) {
url := fmt.Sprintf("https://api.countrystatecity.in/v1/countries/%s/states/%s", countryCode, stateCode)
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()
if res.StatusCode == 200 {
body, _ := ioutil.ReadAll(res.Body)
var state map[string]interface{}
json.Unmarshal(body, &state)
fmt.Printf("%s is located at %s, %s\n",
state["name"], state["latitude"], state["longitude"])
} else {
fmt.Println("State not found")
}
}
func main() {
getStateDetails("IN", "MH")
}
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.Map;
public class StateDetails {
public static void main(String[] args) throws Exception {
String countryCode = "IN";
String stateCode = "MH";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.countrystatecity.in/v1/countries/" + countryCode +
"/states/" + stateCode))
.header("X-CSCAPI-KEY", "YOUR_API_KEY")
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> state = gson.fromJson(response.body(), mapType);
System.out.println(state.get("name") + " is located at " +
state.get("latitude") + ", " + state.get("longitude"));
} else {
System.out.println("State not found");
}
}
}
require 'net/http'
require 'json'
def get_state_details(country_code, state_code)
uri = URI("https://api.countrystatecity.in/v1/countries/#{country_code}/states/#{state_code}")
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)
if response.code == '200'
state = JSON.parse(response.body)
puts "#{state['name']} is located at #{state['latitude']}, #{state['longitude']}"
state
else
puts 'State not found'
nil
end
end
state = get_state_details('IN', 'MH')
{
"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,
"translations": "{\"kr\":\"마하라슈트라\",\"de\":\"Maharashtra\",\"fr\":\"Maharashtra\",\"cn\":\"马哈拉施特拉邦\"}",
"wikiDataId": "Q1191"
}
{
"error": "No State/Region found."
}
{
"error": "Unauthorized. You shouldn't be here."
}
Get State Details
Retrieve detailed information for a specific state using country and state ISO2 codes
curl -X GET 'https://api.countrystatecity.in/v1/countries/IN/states/MH' \
-H 'X-CSCAPI-KEY: YOUR_API_KEY'
curl -X GET 'https://api.countrystatecity.in/v1/countries/IN/states/MH?include_translations=true' \
-H 'X-CSCAPI-KEY: YOUR_API_KEY'
import requests
def get_state_details(country_code, state_code):
response = requests.get(
f'https://api.countrystatecity.in/v1/countries/{country_code}/states/{state_code}',
headers={'X-CSCAPI-KEY': 'YOUR_API_KEY'}
)
if response.ok:
state = response.json()
print(f"{state['name']} is located at {state['latitude']}, {state['longitude']}")
return state
else:
print('State not found')
return None
state = get_state_details('IN', 'MH')
const getStateDetails = async (countryCode, stateCode) => {
const response = await fetch(
`https://api.countrystatecity.in/v1/countries/${countryCode}/states/${stateCode}`,
{
headers: { 'X-CSCAPI-KEY': 'YOUR_API_KEY' }
}
);
if (response.ok) {
const state = await response.json();
console.log(`${state.name} is located at ${state.latitude}, ${state.longitude}`);
return state;
} else {
console.error('State not found');
}
};
getStateDetails('IN', 'MH');
<?php
function getStateDetails($countryCode, $stateCode) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.countrystatecity.in/v1/countries/{$countryCode}/states/{$stateCode}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array(
'X-CSCAPI-KEY: YOUR_API_KEY'
),
));
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($httpCode == 200) {
$state = json_decode($response, true);
echo $state['name'] . " is located at " . $state['latitude'] . ", " . $state['longitude'] . "\n";
return $state;
} else {
echo "State not found\n";
return null;
}
}
$state = getStateDetails('IN', 'MH');
?>
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func getStateDetails(countryCode, stateCode string) {
url := fmt.Sprintf("https://api.countrystatecity.in/v1/countries/%s/states/%s", countryCode, stateCode)
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()
if res.StatusCode == 200 {
body, _ := ioutil.ReadAll(res.Body)
var state map[string]interface{}
json.Unmarshal(body, &state)
fmt.Printf("%s is located at %s, %s\n",
state["name"], state["latitude"], state["longitude"])
} else {
fmt.Println("State not found")
}
}
func main() {
getStateDetails("IN", "MH")
}
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.Map;
public class StateDetails {
public static void main(String[] args) throws Exception {
String countryCode = "IN";
String stateCode = "MH";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.countrystatecity.in/v1/countries/" + countryCode +
"/states/" + stateCode))
.header("X-CSCAPI-KEY", "YOUR_API_KEY")
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> state = gson.fromJson(response.body(), mapType);
System.out.println(state.get("name") + " is located at " +
state.get("latitude") + ", " + state.get("longitude"));
} else {
System.out.println("State not found");
}
}
}
require 'net/http'
require 'json'
def get_state_details(country_code, state_code)
uri = URI("https://api.countrystatecity.in/v1/countries/#{country_code}/states/#{state_code}")
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)
if response.code == '200'
state = JSON.parse(response.body)
puts "#{state['name']} is located at #{state['latitude']}, #{state['longitude']}"
state
else
puts 'State not found'
nil
end
end
state = get_state_details('IN', 'MH')
{
"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,
"translations": "{\"kr\":\"마하라슈트라\",\"de\":\"Maharashtra\",\"fr\":\"Maharashtra\",\"cn\":\"马哈拉施特拉邦\"}",
"wikiDataId": "Q1191"
}
{
"error": "No State/Region found."
}
{
"error": "Unauthorized. You shouldn't be here."
}
?fields=name,iso2,... to receive only the columns you need. Available on Starter+ plans. See the Field Filtering & Sorting guide for syntax.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/countries/IN/states/MH' \
-H 'X-CSCAPI-KEY: YOUR_API_KEY'
curl -X GET 'https://api.countrystatecity.in/v1/countries/IN/states/MH?include_translations=true' \
-H 'X-CSCAPI-KEY: YOUR_API_KEY'
import requests
def get_state_details(country_code, state_code):
response = requests.get(
f'https://api.countrystatecity.in/v1/countries/{country_code}/states/{state_code}',
headers={'X-CSCAPI-KEY': 'YOUR_API_KEY'}
)
if response.ok:
state = response.json()
print(f"{state['name']} is located at {state['latitude']}, {state['longitude']}")
return state
else:
print('State not found')
return None
state = get_state_details('IN', 'MH')
const getStateDetails = async (countryCode, stateCode) => {
const response = await fetch(
`https://api.countrystatecity.in/v1/countries/${countryCode}/states/${stateCode}`,
{
headers: { 'X-CSCAPI-KEY': 'YOUR_API_KEY' }
}
);
if (response.ok) {
const state = await response.json();
console.log(`${state.name} is located at ${state.latitude}, ${state.longitude}`);
return state;
} else {
console.error('State not found');
}
};
getStateDetails('IN', 'MH');
<?php
function getStateDetails($countryCode, $stateCode) {
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.countrystatecity.in/v1/countries/{$countryCode}/states/{$stateCode}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array(
'X-CSCAPI-KEY: YOUR_API_KEY'
),
));
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($httpCode == 200) {
$state = json_decode($response, true);
echo $state['name'] . " is located at " . $state['latitude'] . ", " . $state['longitude'] . "\n";
return $state;
} else {
echo "State not found\n";
return null;
}
}
$state = getStateDetails('IN', 'MH');
?>
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func getStateDetails(countryCode, stateCode string) {
url := fmt.Sprintf("https://api.countrystatecity.in/v1/countries/%s/states/%s", countryCode, stateCode)
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()
if res.StatusCode == 200 {
body, _ := ioutil.ReadAll(res.Body)
var state map[string]interface{}
json.Unmarshal(body, &state)
fmt.Printf("%s is located at %s, %s\n",
state["name"], state["latitude"], state["longitude"])
} else {
fmt.Println("State not found")
}
}
func main() {
getStateDetails("IN", "MH")
}
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.Map;
public class StateDetails {
public static void main(String[] args) throws Exception {
String countryCode = "IN";
String stateCode = "MH";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.countrystatecity.in/v1/countries/" + countryCode +
"/states/" + stateCode))
.header("X-CSCAPI-KEY", "YOUR_API_KEY")
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> state = gson.fromJson(response.body(), mapType);
System.out.println(state.get("name") + " is located at " +
state.get("latitude") + ", " + state.get("longitude"));
} else {
System.out.println("State not found");
}
}
}
require 'net/http'
require 'json'
def get_state_details(country_code, state_code)
uri = URI("https://api.countrystatecity.in/v1/countries/#{country_code}/states/#{state_code}")
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)
if response.code == '200'
state = JSON.parse(response.body)
puts "#{state['name']} is located at #{state['latitude']}, #{state['longitude']}"
state
else
puts 'State not found'
nil
end
end
state = get_state_details('IN', 'MH')
{
"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,
"translations": "{\"kr\":\"마하라슈트라\",\"de\":\"Maharashtra\",\"fr\":\"Maharashtra\",\"cn\":\"马哈拉施特拉邦\"}",
"wikiDataId": "Q1191"
}
{
"error": "No State/Region found."
}
{
"error": "Unauthorized. You shouldn't be here."
}
Common Use Cases
Location-Based Services
Location-Based Services
const calculateDistance = (lat1, lng1, lat2, lng2) => {
const R = 6371; // Earth's radius in km
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLng = (lng2 - lng1) * Math.PI / 180;
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLng/2) * Math.sin(dLng/2);
return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
};
const getDistanceFromState = async (countryCode, stateCode, targetLat, targetLng) => {
const state = await getStateDetails(countryCode, stateCode);
return calculateDistance(
parseFloat(state.latitude),
parseFloat(state.longitude),
targetLat,
targetLng
);
};
Administrative Type Validation
Administrative Type Validation
const isStateType = async (countryCode, stateCode, expectedType) => {
const state = await getStateDetails(countryCode, stateCode);
return state && state.type === expectedType;
};
Tier-Based Field Availability
| Tier | Plans | Fields |
|---|---|---|
| Basic | Community, Starter, Legacy | id, name, iso2, country_id, country_code, latitude, longitude, timezone |
| Full | Supporter, Professional, Business | All Basic + fips_code, iso3166_2, type, level, parent_id, native, population, translations, wikiDataId, localized_name, matched_locale |
translations is part of Full access but is not returned by default: add include_translations=true, or name it in ?fields=. localized_name and matched_locale are computed from the translations rather than stored, and appear only when you pass locale. See Localized Place Names.
See Pricing for plan details.Authorizations
API key for authentication. Get your free key at app.countrystatecity.in.
Path Parameters
ISO2 code of the country (e.g., IN)
"IN"
ISO2 code of the state (e.g., MH)
"MH"
Query Parameters
Comma-separated list of fields to include in the response. id is always included. Requires Starter+ plan.
"name,iso2,country_code"
BCP 47 locale code (e.g. pt-BR) to request a localized name. Adds localized_name (resolved via exact locale → base language → native name → English name fallback) and matched_locale (which tier matched) to the result; name is unaffected. Supporter+ plans only — silently omitted (not an error) on lower tiers. A malformed value is rejected with a 400 on every tier.
2 - 7^[a-zA-Z]{2}(-[a-zA-Z]{2,4})?$"pt-BR"
When true, includes the full translations field (JSON string keyed by language code). Supporter+ plans only — silently omitted (not an error) on lower tiers. Note that an explicit fields=translations also returns the field and takes precedence over this flag.
true
Response
State details
State/province/region object. Fields returned depend on your plan's data access level.
Unique identifier
4008
State name in English
"Maharashtra"
Parent country ID
Parent country ISO2 code
"IN"
State/province ISO code
"MH"
Latitude coordinate
"19.75147980"
Longitude coordinate
"75.71388840"
IANA timezone identifier
"Asia/Kolkata"
FIPS code. Coordinates tier and above.
ISO 3166-2 subdivision code. Coordinates tier and above.
Administrative type (e.g., state, province, territory). Coordinates tier and above.
"state"
Administrative level. Coordinates tier and above.
Parent subdivision ID (for nested administrative structures). Coordinates tier and above.
Name in native language. Coordinates tier and above.
Population count. Coordinates tier and above.
JSON string keyed by language code. Supporter+ plans only. Returned when include_translations=true or when fields=translations explicitly requests it.
Wikidata item identifier. Full access level only.
"Q1191"
Name resolved via the locale query param's fallback chain (exact locale → base language → native name → English name). Only present when locale was supplied. Supporter+ plans only — silently omitted on lower tiers.
"Maharashtra"
Which fallback tier satisfied the locale request: the exact locale (e.g. pt-BR), its base language (e.g. pt), native, or en (English fallback). Only present when locale was supplied. Supporter+ plans only — silently omitted on lower tiers.
"en"