Selecionar Estados

Obtenha estados/províncias por país, otimizados para dropdowns

O endpoint /v1/select/states retorna uma lista leve de estados/províncias filtrados por país, com apenas os campos id e name, otimizado para menus dropdown.

Endpoint

GET https://api.countrydataapi.com/v1/select/states

Autenticação

Inclua sua chave de API como parâmetro de consulta:

?apikey=sua-chave-api

Sua chave de API é como uma senha, mantenha-a segura. Obtenha sua chave no painel da conta.

Parâmetros de Consulta

Parâmetro Tipo Obrigatório Descrição
apikey string Sim Sua chave de autenticação da API
country string Sim ID do país (do endpoint /select/countries)
lang string Não Código do idioma para nomes dos estados (padrão: en)

Idiomas Suportados

  • en - Inglês (padrão)
  • es - Espanhol
  • pt - Português
  • fr - Francês
  • de - Alemão
  • it - Italiano

Exemplo de Requisição

# Obter estados do Brasil
curl "https://api.countrydataapi.com/v1/select/states?apikey=sua-chave-api&country=66c7a6c9e4bda21f4ab10ef5&lang=pt"

JavaScript (Fetch)

const API_KEY = 'sua-chave-api';
const COUNTRY_ID = '66c7a6c9e4bda21f4ab10ef5'; // Brasil

async function carregarEstados(countryId) {
  const response = await fetch(
    `https://api.countrydataapi.com/v1/select/states?apikey=${API_KEY}&country=${countryId}&lang=pt`
  );
  const data = await response.json();
  return data;
}

const estados = await carregarEstados(COUNTRY_ID);

JavaScript (Axios)

import axios from 'axios';

const response = await axios.get(
  'https://api.countrydataapi.com/v1/select/states',
  {
    params: {
      apikey: 'sua-chave-api',
      country: '66c7a6c9e4bda21f4ab10ef5',
      lang: 'pt',
    },
  }
);

Python

import requests

response = requests.get(
    'https://api.countrydataapi.com/v1/select/states',
    params={
        'apikey': 'sua-chave-api',
        'country': '66c7a6c9e4bda21f4ab10ef5',
        'lang': 'pt'
    }
)
data = response.json()

PHP

<?php
$apiKey = 'sua-chave-api';
$countryId = '66c7a6c9e4bda21f4ab10ef5';
$url = "https://api.countrydataapi.com/v1/select/states?apikey={$apiKey}&country={$countryId}&lang=pt";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
?>

Angular

// state.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

interface State {
  id: string;
  name: string;
}

interface ApiResponse {
  success: boolean;
  data: State[];
}

@Injectable({
  providedIn: 'root'
})
export class StateService {
  private readonly API_KEY = 'sua-chave-api';
  private readonly BASE_URL = 'https://api.countrydataapi.com/v1';

  constructor(private http: HttpClient) {}

  getStatesByCountry(countryId: string, lang: string = 'pt'): Observable<State[]> {
    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('country', countryId)
      .set('lang', lang);

    return this.http.get<ApiResponse>(
      `${this.BASE_URL}/select/states`,
      { params }
    ).pipe(
      map(response => response.data)
    );
  }
}

// state-select.component.ts
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { StateService } from './state.service';

@Component({
  selector: 'app-state-select',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div *ngIf="loading">Carregando estados...</div>
    <div *ngIf="error" class="error">{{ error }}</div>
    <select
      *ngIf="!loading && !error"
      [(ngModel)]="selectedState"
      (ngModelChange)="onStateChange($event)"
      [disabled]="!countryId"
    >
      <option value="">Selecione um estado...</option>
      <option *ngFor="let state of states" [value]="state.id">
        {{ state.name }}
      </option>
    </select>
  `
})
export class StateSelectComponent implements OnChanges {
  @Input() countryId: string = '';
  @Output() stateChange = new EventEmitter<string>();

  states: any[] = [];
  selectedState = '';
  loading = false;
  error: string | null = null;

  constructor(private stateService: StateService) {}

  ngOnChanges(changes: SimpleChanges) {
    if (changes['countryId'] && this.countryId) {
      this.loadStates();
    } else {
      this.states = [];
      this.selectedState = '';
    }
  }

  loadStates() {
    this.loading = true;
    this.error = null;

    this.stateService.getStatesByCountry(this.countryId, 'pt').subscribe({
      next: (data) => {
        this.states = data;
        this.loading = false;
      },
      error: (err) => {
        this.error = 'Falha ao carregar estados';
        this.loading = false;
      }
    });
  }

  onStateChange(stateId: string) {
    this.stateChange.emit(stateId);
  }
}

Formato da Resposta

Resposta de Sucesso (Brasil)

{
  "success": true,
  "data": [
    {
      "id": "66c7a6cae4bda21f4ab11d16",
      "name": "Acre"
    },
    {
      "id": "66c7a6cae4bda21f4ab11d17",
      "name": "Alagoas"
    },
    {
      "id": "66c7a6cae4bda21f4ab11d18",
      "name": "Amapá"
    },
    {
      "id": "66c7a6cae4bda21f4ab11d19",
      "name": "Amazonas"
    },
    {
      "id": "66c7a6cae4bda21f4ab11d1a",
      "name": "Bahia"
    }
    // ... 27 estados no total
  ]
}

Campos da Resposta

Campo Tipo Descrição
success boolean Indica se a requisição foi bem-sucedida
data array Array de objetos de estado/província
data[].id string Identificador único do estado (MongoDB ObjectId)
data[].name string Nome do estado/província no idioma solicitado

Resposta de Erro

{
  "success": false,
  "error": {
    "code": "MISSING_PARAMETER",
    "message": "O parâmetro obrigatório 'country' está faltando"
  }
}

Resultado Vazio

Se um país não tem estados (ex: países pequenos):

{
  "success": true,
  "data": []
}

Uso de Tokens

Este endpoint consome 1 token por requisição.

Dica: Armazene dados de estados por ID do país em cache para reduzir chamadas de API quando usuários navegam para trás e para frente.

Exemplo de Dropdown em Cascata

HTML

<select id="country" onchange="carregarEstados(this.value)">
  <option value="">Selecione o país...</option>
  <!-- Preenchido de /select/countries -->
</select>

<select id="state" disabled>
  <option value="">Selecione o estado...</option>
</select>

<script>
const API_KEY = 'sua-chave-api';

async function carregarEstados(countryId) {
  const stateSelect = document.getElementById('state');

  // Resetar e desabilitar
  stateSelect.innerHTML = '<option value="">Carregando...</option>';
  stateSelect.disabled = true;

  if (!countryId) {
    stateSelect.innerHTML = '<option value="">Selecione o estado...</option>';
    return;
  }

  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/select/states?apikey=${API_KEY}&country=${countryId}&lang=pt`
    );
    const { success, data, error } = await response.json();

    if (!success) {
      console.error('Erro da API:', error);
      stateSelect.innerHTML = '<option value="">Erro ao carregar estados</option>';
      return;
    }

    stateSelect.innerHTML = '<option value="">Selecione o estado...</option>';
    data.forEach(state => {
      stateSelect.add(new Option(state.name, state.id));
    });
    stateSelect.disabled = false;
  } catch (err) {
    console.error('Erro de Rede:', err);
    stateSelect.innerHTML = '<option value="">Erro ao carregar estados</option>';
  }
}
</script>

Componente React

import { useState, useEffect } from 'react';

function StateSelect({ countryId, onChange }) {
  const [states, setStates] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    if (!countryId) {
      setStates([]);
      return;
    }

    setLoading(true);
    fetch(
      `https://api.countrydataapi.com/v1/select/states?apikey=sua-chave-api&country=${countryId}&lang=pt`
    )
      .then(res => res.json())
      .then(({ data }) => {
        setStates(data || []);
        setLoading(false);
      })
      .catch(err => {
        console.error(err);
        setLoading(false);
      });
  }, [countryId]);

  return (
    <select onChange={e => onChange(e.target.value)} disabled={!countryId || loading}>
      <option value="">
        {loading ? 'Carregando...' : 'Selecione o estado...'}
      </option>
      {states.map(state => (
        <option key={state.id} value={state.id}>
          {state.name}
        </option>
      ))}
    </select>
  );
}

Componente Vue

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

const props = defineProps(['countryId']);
const emit = defineEmits(['change']);

const states = ref([]);
const loading = ref(false);

watch(() => props.countryId, async (countryId) => {
  if (!countryId) {
    states.value = [];
    return;
  }

  loading.value = true;
  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/select/states?apikey=sua-chave-api&country=${countryId}&lang=pt`
    );
    const { data } = await response.json();
    states.value = data || [];
  } catch (err) {
    console.error(err);
  } finally {
    loading.value = false;
  }
});
</script>

<template>
  <select @change="emit('change', $event.target.value)" :disabled="!countryId || loading">
    <option value="">{{ loading ? 'Carregando...' : 'Selecione o estado...' }}</option>
    <option v-for="state in states" :key="state.id" :value="state.id">
      {{ state.name }}
    </option>
  </select>
</template>

Exemplos por País

Brasil (27 estados)

const BRAZIL_ID = '66c7a6c9e4bda21f4ab10ef5';
const response = await fetch(
  `https://api.countrydataapi.com/v1/select/states?apikey=sua-chave-api&country=${BRAZIL_ID}&lang=pt`
);
// Retorna: Acre, Alagoas, Amapá, ... Tocantins

Portugal (18 distritos + 2 regiões autônomas)

const PORTUGAL_ID = '66c7a6c9e4bda21f4ab10fc5';
const response = await fetch(
  `https://api.countrydataapi.com/v1/select/states?apikey=sua-chave-api&country=${PORTUGAL_ID}&lang=pt`
);
// Retorna: Aveiro, Beja, ... Açores, Madeira

Estados Unidos (50 estados)

const US_ID = '66c7a6c9e4bda21f4ab10fd5';
const response = await fetch(
  `https://api.countrydataapi.com/v1/select/states?apikey=sua-chave-api&country=${US_ID}&lang=pt`
);
// Retorna: Alabama, Alaska, Arizona, ... Wyoming

Estratégia de Cache

Armazene estados por país em cache para minimizar chamadas de API:

const stateCache = new Map();

async function getEstados(countryId) {
  // Verificar cache primeiro
  if (stateCache.has(countryId)) {
    return stateCache.get(countryId);
  }

  // Buscar da API
  const response = await fetch(
    `https://api.countrydataapi.com/v1/select/states?apikey=sua-chave-api&country=${countryId}&lang=pt`
  );
  const { data } = await response.json();

  // Salvar em cache
  stateCache.set(countryId, data);

  return data;
}

Tratamento de Erros

Sempre trate erros de forma elegante:

async function carregarEstados(countryId) {
  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/select/states?apikey=sua-chave-api&country=${countryId}`
    );

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

    const result = await response.json();

    if (!result.success) {
      throw new Error(result.error?.message || 'Erro da API');
    }

    return result.data;
  } catch (err) {
    console.error('Falha ao carregar estados:', err);
    // Mostrar mensagem amigável ao usuário
    alert('Falha ao carregar estados. Por favor, tente novamente.');
    return [];
  }
}

Dicas de Performance

  1. Carregamento lazy: Só buscar quando o país for selecionado
  2. Cache por país: Armazenar em memória ou localStorage
  3. Debounce nas requisições: Se usar busca/filtro
  4. Mostrar estado de carregamento: Fornecer feedback visual

Limites de Taxa

  • Plano gratuito: 100 requisições/dia
  • Plano Basic: 1.000 requisições/dia
  • Plano Pro: 10.000 requisições/dia
  • Plano Enterprise: Ilimitado

Confira nossa página de preços para mais detalhes.

Erros Comuns

Código de Erro Descrição Solução
INVALID_API_KEY Chave de API inválida Verifique sua chave de API no painel da conta
MISSING_PARAMETER Parâmetro country faltando Inclua o ID do país na requisição
INVALID_COUNTRY_ID Formato do ID do país inválido Use um MongoDB ObjectId válido de /select/countries
QUOTA_EXCEEDED Limite diário de tokens atingido Atualize o plano ou aguarde o reset

Consulte a documentação de Códigos de Erro para todos os erros possíveis.

Endpoints Relacionados

Guias de Integração Completos

Precisa de Ajuda?


Nota: Alguns países não têm divisões administrativas (ex: Mônaco, Cidade do Vaticano) e retornarão um array vazio. Sempre trate resultados vazios de forma elegante na sua interface.