# 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.

- Endereço oficial: https://pradev.com.br/guias/como-buscar-endereco-pelo-cep-viacep
- Tipo: Guia
- Publicado em: 2026-10-01
- Atualizado em: 2026-10-01
- Autor: Leonardo Gaertner (https://pradev.com.br/sobre)

## 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](https://pradev.com.br/guias/mascara-cpf-cnpj-cep-telefone-javascript) 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.

```javascript
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,
  };
}
```

_JavaScript. 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.

```python
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"],
    }
```

_Python_

```php
<?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'],
    ];
}
```

_PHP_

## 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.

## 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.

## Fontes

- [ViaCEP: documentação](https://viacep.com.br/)
- [MDN: AbortSignal.timeout](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static)

## Guias relacionados

- [Máscara de CPF, CNPJ, CEP e telefone em JavaScript](https://pradev.com.br/guias/mascara-cpf-cnpj-cep-telefone-javascript): Má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 Brasil](https://pradev.com.br/guias/regex-cep-telefone-email): Expressõ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.
