Como buscar o endereço pelo CEP com o ViaCEP
O ViaCEP é um serviço gratuito que devolve o endereço de um CEP em JSON, sem cadastro nem chave. Este guia mostra como consultá-lo em JavaScript, Python e PHP, como diferenciar CEP com formato errado de CEP que não existe, como lidar com demora e falhas de rede e como preencher o formulário de endereço quando a pessoa termina de digitar o CEP.
Como a consulta funciona
A consulta é um GET em https://viacep.com.br/ws/01001000/json/, com o CEP só com dígitos. A resposta traz logradouro, bairro, localidade (a cidade), uf, complemento, o código ibge e o ddd. O serviço aceita chamadas direto do navegador, então dá para consultar no próprio formulário, sem passar pelo seu servidor.
- CEP com formato errado (menos de 8 dígitos, letras): a API responde com erro 400.
- CEP com formato certo que não existe: a resposta é 200, mas com um campo
erro. Trate esse caso, ou o formulário vai preencher campos vazios. - Antes de consultar, confira o formato. As máscaras e expressões do guia de máscaras ajudam.
Em JavaScript
O AbortSignal.timeout cancela a consulta se ela passar de 5 segundos, para o formulário não ficar esperando para sempre. A função devolve null para CEP inexistente e lança erro para formato inválido ou falha de rede, assim a tela pode mostrar mensagens diferentes.
const VIACEP = 'https://viacep.com.br/ws';
async function buscarCep(valor) {
const cep = valor.replace(/\D/g, '');
// Formato errado nem vai para a API: ela responderia com erro 400
if (cep.length !== 8) throw new Error('O CEP precisa ter 8 dígitos');
const resposta = await fetch(`${VIACEP}/${cep}/json/`, { signal: AbortSignal.timeout(5000) });
if (!resposta.ok) throw new Error(`Erro ${resposta.status} ao consultar o CEP`);
const dados = await resposta.json();
// CEP com formato certo que não existe: a resposta é 200, com {"erro": "true"}
if (dados.erro) return null;
return {
cep: dados.cep,
rua: dados.logradouro,
bairro: dados.bairro,
cidade: dados.localidade,
uf: dados.uf,
};
} Funciona no navegador e no Node.js 18 ou mais novo.
Para preencher o formulário, chame buscarCep quando o campo de CEP perder o foco (evento blur) ou quando chegar ao oitavo dígito, e coloque cada valor no campo correspondente. Deixe os campos editáveis: o CEP de cidades pequenas costuma vir sem rua nem bairro.
Em Python e PHP
As duas versões usam só a biblioteca padrão. No servidor, sempre defina um tempo limite: sem ele, uma API lenta prende o processo que atende o seu usuário.
import json
import re
import urllib.request
VIACEP = "https://viacep.com.br/ws"
def buscar_cep(valor: str) -> dict | None:
cep = re.sub(r"\D", "", valor)
if len(cep) != 8:
raise ValueError("O CEP precisa ter 8 dígitos")
# urlopen lança HTTPError se a API responder com erro (4xx ou 5xx)
with urllib.request.urlopen(f"{VIACEP}/{cep}/json/", timeout=5) as resposta:
dados = json.load(resposta)
if dados.get("erro"): # CEP que não existe
return None
return {
"cep": dados["cep"],
"rua": dados["logradouro"],
"bairro": dados["bairro"],
"cidade": dados["localidade"],
"uf": dados["uf"],
} <?php
const VIACEP = 'https://viacep.com.br/ws';
function buscarCep(string $valor): ?array
{
$cep = preg_replace('/\D/', '', $valor);
if (strlen($cep) !== 8) {
throw new InvalidArgumentException('O CEP precisa ter 8 dígitos');
}
$contexto = stream_context_create(['http' => ['timeout' => 5]]);
$json = @file_get_contents(VIACEP . "/$cep/json/", false, $contexto);
if ($json === false) {
throw new RuntimeException('Não foi possível consultar o CEP');
}
$dados = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
if (!empty($dados['erro'])) { // CEP que não existe
return null;
}
return [
'cep' => $dados['cep'],
'rua' => $dados['logradouro'],
'bairro' => $dados['bairro'],
'cidade' => $dados['localidade'],
'uf' => $dados['uf'],
];
} Cuidados
- Não use o ViaCEP para validar bases inteiras de uma vez. O serviço é gratuito e pede uso moderado, e consultas em massa podem ser bloqueadas. Para muitos CEPs, guarde os resultados que já consultou.
- Tenha um plano para quando a API estiver fora: deixe a pessoa preencher o endereço à mão. Há alternativas, como a BrasilAPI, que também consulta CEPs.
- O CEP existir não garante que a pessoa mora ali. Para entrega, confirme o número e o complemento com ela.
- O endereço consultado não substitui a validação no servidor, se o seu sistema depende dele.
Achou um erro neste guia? Avise por e-mail.
Perguntas frequentes
O ViaCEP é gratuito?
Sim. Não precisa de cadastro nem de chave de acesso. O serviço pede uso moderado, e consultas em massa, como validar uma base inteira, podem ser bloqueadas.
Como saber se um CEP não existe no ViaCEP?
A resposta vem com status 200 e um campo erro, em vez dos dados do endereço. Já um CEP com formato inválido, como menos de 8 dígitos, recebe erro 400.
Dá para consultar o ViaCEP direto do navegador?
Sim. O serviço permite chamadas de outros sites, então o fetch funciona direto no formulário, sem passar pelo seu servidor.
Por que o ViaCEP não trouxe a rua do meu CEP?
Em muitas cidades pequenas, um único CEP vale para a cidade inteira, e a resposta vem sem logradouro nem bairro. Nesse caso, peça para a pessoa preencher esses campos.
Outros guias
- Máscara de CPF, CNPJ, CEP e telefone em JavaScriptMáscaras de CPF, CNPJ (inclusive alfanumérico), CEP e telefone em JavaScript puro, aplicadas enquanto a pessoa digita, e a formatação em Python e PHP.
- Regex para CEP, telefone e e-mail no BrasilExpressões regulares para validar CEP, telefone com DDD e e-mail, com os erros que deixam passar valores inválidos em JavaScript, Python e PHP.