Skip to main content

Getting Started

The process is simple:
  1. Visit app.countrystatecity.in
  2. Sign up or log in to your account
  3. Create your API key instantly
You can make your first API call within minutes:
curl -X GET 'https://api.countrystatecity.in/v1/countries' \
  -H 'X-CSCAPI-KEY: YOUR_API_KEY'
Your API key is ready to use immediately after registration - no waiting period required.
While we don’t maintain official SDKs, our RESTful API works with any programming language that can make HTTP requests. We provide comprehensive integration examples for:
  • JavaScript/Node.js
  • Python
  • PHP
  • Java
  • C#
  • Go
  • Ruby
Community members have also created unofficial libraries for various platforms.

Authentication & Security

Authentication is done using API key headers. Include your API key in every request:
X-CSCAPI-KEY: YOUR_API_KEY
const response = await fetch('https://api.countrystatecity.in/v1/countries', {
  headers: { 'X-CSCAPI-KEY': 'YOUR_API_KEY' }
});
Never expose your API key in client-side code such as browser JavaScript, mobile apps, or public repositories.
Safe practices:
  • Use server-side applications or serverless functions
  • Store API keys in environment variables
  • Implement your own backend API that securely calls our API
  • Use build-time environment variables for static sites
Why this matters:
  • API keys in client-side code are visible to anyone
  • Malicious users could extract and abuse your API key
  • This could lead to unexpected usage and charges
Yes! You can manage your API keys through the developer portal:
  1. Log into your account
  2. Navigate to API key management
  3. Generate a new key
  4. Update your applications with the new key
  5. Revoke the old key once migration is complete
Keep both keys active during migration to avoid service interruption.
A 401 error typically indicates an authentication issue:Common causes and solutions:
  • Invalid API key: Double-check your API key for typos
  • Wrong header name: Ensure you’re using X-CSCAPI-KEY exactly
  • Missing header: Verify the header is being sent with every request
  • Expired/revoked key: Generate a new API key if needed
Test your authentication:
curl -X GET 'https://api.countrystatecity.in/v1/countries' \
  -H 'X-CSCAPI-KEY: YOUR_API_KEY' \
  -w "HTTP Status: %{http_code}\n"
A successful test returns HTTP 200 with country data.
When you exceed your rate limit, you’ll receive a 429 Too Many Requests response:
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Please try again later.",
  "retry_after": 3600
}
Best practices for handling rate limits:
  • Implement exponential backoff retry logic
  • Cache responses to reduce API calls
  • Monitor usage proactively
  • Consider upgrading your plan if limits are consistently hit
The Retry-After header indicates how long to wait before making another request.
Effective caching strategies:
  • Cache country/state data for 24+ hours (rarely changes)
  • Cache city data for 12+ hours
  • Implement local fallbacks for critical data
Efficient request patterns:
  • Fetch broader datasets when possible (all countries vs individual requests)
  • Use hierarchical endpoints strategically
  • Batch related requests together
Example caching implementation:
class APICache {
  constructor(ttl = 24 * 60 * 60 * 1000) {
    this.cache = new Map();
    this.ttl = ttl;
  }

  get(key) {
    const item = this.cache.get(key);
    if (!item || Date.now() - item.timestamp > this.ttl) {
      return null;
    }
    return item.data;
  }

  set(key, data) {
    this.cache.set(key, { data, timestamp: Date.now() });
  }
}

Data & Endpoints

Countries include:
  • ISO2 and ISO3 codes
  • Country name and native name
  • Phone code and currency information
  • Flag emoji and region information
  • Latitude and longitude coordinates
States include:
  • State name and ISO2 code
  • Country association
  • State type (state, province, region, etc.)
  • Latitude and longitude coordinates
Cities include:
  • City name and unique ID
  • Country and state association
  • Latitude and longitude coordinates
  • Timezone information (when available)
Use the detailed endpoints (/countries/{iso2}) to get complete information including additional metadata.
Our data is continuously maintained and updated:
  • Country data: Updated as needed for political changes, currency updates, etc.
  • State/Province data: Updated for administrative boundary changes
  • City data: Regular additions and corrections based on authoritative sources
We implement automated validation and quality checks to ensure data accuracy. Major updates are announced through our changelog.
The dataset includes 247+ countries, 5,000+ states/provinces, and 151,000+ cities worldwide.
No, for performance and efficiency reasons, our API is designed with hierarchical endpoints:
  • /countries - All countries
  • /countries/{countryCode}/states - States within a country
  • /countries/{countryCode}/cities - Cities within a country
  • /countries/{countryCode}/states/{stateCode}/cities - Cities within a state
Why this design:
  • Faster response times for specific data
  • Reduced bandwidth usage
  • Better caching opportunities
  • More manageable response sizes
Requesting all cities globally would result in 151,000+ records, which would be slow and consume significant bandwidth.
Yes! Latitude and longitude coordinates are included for:
  • Countries: Approximate center coordinates
  • States/Provinces: Administrative center coordinates
  • Cities: City center coordinates
Example city response:
{
  "id": 12345,
  "name": "Los Angeles",
  "latitude": "34.05223",
  "longitude": "-118.24368",
  "country_code": "US",
  "state_code": "CA"
}
Coordinates are provided as strings for precision and can be easily converted to numbers for calculations.
Yes, we follow international standards:Country Codes:
  • ISO 3166-1 alpha-2 (2-letter codes like “US”, “GB”)
  • ISO 3166-1 alpha-3 (3-letter codes like “USA”, “GBR”)
Currency Codes:
  • ISO 4217 standard (3-letter codes like “USD”, “EUR”)
Phone Codes:
  • ITU-T E.164 standard international calling codes
This ensures compatibility with other international systems and databases.

Integration & Development

We strongly recommend against making direct API calls from browser applications due to security concerns with exposing API keys.
Recommended approaches:
  1. Server-side proxy: Create your own API endpoint that calls our API
  2. Serverless functions: Use services like Vercel Functions, Netlify Functions, or AWS Lambda
  3. Static site generation: Fetch data at build time for static sites
Why avoid direct browser calls:
  • API keys are visible in browser developer tools
  • Risk of key theft and unauthorized usage
  • Potential CORS restrictions
Implement cascading dropdowns by chaining API calls based on user selections:React example pattern:
const [selectedCountry, setSelectedCountry] = useState('');
const [states, setStates] = useState([]);
const [cities, setCities] = useState([]);

// Load states when country changes
useEffect(() => {
  if (selectedCountry) {
    loadStates(selectedCountry);
    setCities([]); // Clear cities when country changes
  }
}, [selectedCountry]);

const loadStates = async (countryCode) => {
  const statesData = await api.getStates(countryCode);
  setStates(statesData);
};

Complete Example

See our comprehensive cascading dropdown implementation guide
Implement comprehensive error handling for different scenarios:Error types and handling:
async function makeAPIRequest(endpoint) {
  try {
    const response = await fetch(endpoint, { headers });

    if (response.status === 401) {
      throw new Error('INVALID_API_KEY');
    } else if (response.status === 404) {
      throw new Error('NOT_FOUND');
    } else if (!response.ok) {
      throw new Error('API_ERROR');
    }

    return await response.json();

  } catch (error) {
    if (error.message === 'INVALID_API_KEY') {
      // Notify user to check API configuration
      console.error('Invalid API key configuration');
    }
    throw error;
  }
}
Best practices:
  • Always check response status codes
  • Implement retry logic for temporary failures
  • Provide meaningful error messages to users
  • Log errors for debugging purposes
Yes, caching is highly recommended and beneficial:Recommended cache durations:
  • Countries: 24-48 hours (very stable data)
  • States: 12-24 hours (occasionally updated)
  • Cities: 6-12 hours (more frequently updated)
Implementation strategies:
// Browser localStorage
const cacheKey = 'countries_data';
const cachedData = localStorage.getItem(cacheKey);
const isExpired = Date.now() - cachedData?.timestamp > 24 * 60 * 60 * 1000;

if (cachedData && !isExpired) {
  return JSON.parse(cachedData).data;
}

// Server-side caching (Redis, Memcached, etc.)
const redis = require('redis');
const client = redis.createClient();

const cached = await client.get('countries');
if (cached) return JSON.parse(cached);

const data = await fetchFromAPI();
await client.setex('countries', 86400, JSON.stringify(data)); // 24h TTL
Caching reduces API usage, improves performance, and provides offline fallbacks.

Troubleshooting

This can happen for several reasons:Common causes:
  1. Incorrect country/state codes: Verify you’re using the correct ISO codes
  2. Case sensitivity: Country codes should be uppercase (“US”, not “us”)
  3. State code format: Use 2-letter state codes when available
  4. Data availability: Some territories may have incomplete subdivision data
Debugging steps:
// First, verify the country exists
const countries = await api.getCountries();
const country = countries.find(c => c.iso2 === 'US');
console.log('Country found:', country);

// Then check states
const states = await api.getStates('US');
console.log('States count:', states.length);
Use our detailed country endpoint to verify exact country and state codes available.
Performance optimization strategies:
  1. Implement caching (most important)
  2. Use specific endpoints instead of filtering large datasets
  3. Parallel requests for independent data
  4. CDN/Edge caching for static geographical data
Example parallel requests:
// Instead of sequential requests
const countries = await api.getCountries();
const states = await api.getStates('US');

// Use parallel requests
const [countries, states] = await Promise.all([
  api.getCountries(),
  api.getStates('US')
]);
Server-side optimizations:
  • Use HTTP/2 for multiplexed requests
  • Implement connection pooling
  • Add response compression
This is typically due to caching issues or incorrect API usage:Check these common issues:
  1. Browser caching: Different cache states in development
  2. API versioning: Ensure you’re using the same API version
  3. Mixed endpoints: Don’t mix different API base URLs
  4. Concurrent updates: Our data is occasionally updated
Troubleshooting steps:
// Add request debugging
console.log('Request URL:', fullUrl);
console.log('Request headers:', headers);
console.log('Response status:', response.status);
console.log('Response headers:', [...response.headers.entries()]);
Force fresh data:
// Add cache-busting parameter for testing
const url = `${baseUrl}?_t=${Date.now()}`;
If issues persist, contact support with specific request/response examples.
Testing strategy:
  1. Start with cURL to verify basic connectivity
  2. Test each endpoint individually
  3. Verify error handling with invalid inputs
Basic connectivity test:
curl -X GET 'https://api.countrystatecity.in/v1/countries' \
  -H 'X-CSCAPI-KEY: YOUR_API_KEY' \
  -w "HTTP Status: %{http_code}\n"
Automated testing example:
describe('Country State City API', () => {
  test('should fetch countries successfully', async () => {
    const countries = await api.getCountries();
    expect(countries).toBeInstanceOf(Array);
    expect(countries.length).toBeGreaterThan(0);
    expect(countries[0]).toHaveProperty('iso2');
  });

  test('should handle invalid country code', async () => {
    await expect(api.getStates('INVALID')).rejects.toThrow();
  });
});
A successful countries request should return 247+ countries with proper ISO codes.

Still Need Help?

Can’t find what you’re looking for? Contact our support team with specific questions about your integration or use case.