curl -X GET 'https://api.countrystatecity.in/v1/countries' \
  -H 'X-CSCAPI-KEY: YOUR_API_KEY' \
  -w "HTTP Status: %{http_code}\n"
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Please try again later.",
  "retry_after": 3600
}

Rate Limit Overview

The Country State City API implements rate limiting to ensure fair usage and optimal performance for all users. Rate limits are enforced per API key and reset hourly.

Current Rate Limits

PlanMonthly RequestsDaily RequestsRate Limit
Community (Free)3,0001002 req/second
Supporter30,0001,00010 req/second
Professional150,0005,00025 req/second

View Full Pricing Details

Compare plans, features, and pricing options

Rate Limit Headers

Every API response includes rate limit information in the headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200
X-RateLimit-Window: 3600
HeaderDescription
X-RateLimit-LimitTotal requests allowed in current window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when the limit resets
X-RateLimit-WindowRate limit window in seconds (3600 = 1 hour)

Monitoring Your Usage

const checkRateLimit = async () => {
  const response = await fetch('https://api.countrystatecity.in/v1/countries', {
    headers: { 'X-CSCAPI-KEY': 'YOUR_API_KEY' }
  });
  
  const remaining = response.headers.get('X-RateLimit-Remaining');
  const limit = response.headers.get('X-RateLimit-Limit');
  const reset = response.headers.get('X-RateLimit-Reset');
  
  console.log(`Rate Limit: ${remaining}/${limit}`);
  console.log(`Resets at: ${new Date(reset * 1000)}`);
  
  // Warn when approaching limit
  if (remaining < limit * 0.1) {
    console.warn('⚠️ Approaching rate limit!');
  }
};

Rate Limit Exceeded (HTTP 429)

When you exceed your rate limit, the API returns a 429 Too Many Requests status:
curl -X GET 'https://api.countrystatecity.in/v1/countries' \
  -H 'X-CSCAPI-KEY: YOUR_API_KEY' \
  -w "HTTP Status: %{http_code}\n"
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Please try again later.",
  "retry_after": 3600
}

Best Practices

Implement Exponential Backoff

const makeRequestWithBackoff = async (url, options, maxRetries = 3) => {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After') || Math.pow(2, attempt);
        console.log(`Rate limited. Waiting ${retryAfter}s before retry...`);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        continue;
      }
      
      return response;
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
      
      const delay = Math.pow(2, attempt) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
};

Cache Responses Effectively

Implement intelligent caching to reduce API calls:
  • Cache country/state data for 24+ hours (rarely changes)
  • Cache city data for 12+ hours
  • Use ETags and conditional requests when available
  • Implement local fallbacks for critical data
class CSCCache {
  constructor(ttl = 24 * 60 * 60 * 1000) { // 24 hours
    this.cache = new Map();
    this.ttl = ttl;
  }
  
  set(key, data) {
    this.cache.set(key, {
      data,
      timestamp: Date.now()
    });
  }
  
  get(key) {
    const item = this.cache.get(key);
    if (!item) return null;
    
    if (Date.now() - item.timestamp > this.ttl) {
      this.cache.delete(key);
      return null;
    }
    
    return item.data;
  }
  
  async fetchCountries(apiKey) {
    const cached = this.get('countries');
    if (cached) return cached;
    
    const response = await fetch('https://api.countrystatecity.in/v1/countries', {
      headers: { 'X-CSCAPI-KEY': apiKey }
    });
    
    const countries = await response.json();
    this.set('countries', countries);
    return countries;
  }
}

Batch Requests Efficiently

Plan your requests to maximize efficiency:
  • Fetch broader datasets when possible (all countries vs individual requests)
  • Use hierarchical endpoints strategically
  • Implement request queuing for high-volume applications

Monitor and Alert

Set up monitoring to track your API usage:
const usage = {
  daily: 0,
  hourly: 0,
  
  track(response) {
    this.daily++;
    this.hourly++;
    
    const remaining = response.headers.get('X-RateLimit-Remaining');
    
    if (remaining < 100) {
      console.warn(`Low rate limit: ${remaining} requests remaining`);
      // Send alert to monitoring system
    }
  },
  
  reset() {
    this.hourly = 0;
  }
};

Upgrading Your Plan

Need higher rate limits? Contact Us:

Contact Sales

Discuss custom rate limits and enterprise features for your specific needs.