Projeto 5: Buscador de CEP com Fetch (ViaCEP)
Crie uma aplicação onde o usuário digita um CEP e o sistema busca, via fetch, logradouro, bairro, cidade e estado.
Este projeto fecha o submódulo com chave de ouro, porque conecta tudo: interface, eventos, validação, requisição HTTP, tratamento de erros e atualização dinâmica da tela.
Pense nele como um “atendente digital”:
- o usuário informa um CEP,
- o JavaScript consulta uma base externa (API),
- e devolve os dados de endereço sem recarregar a página.
O que este projeto consolida
Com o buscador de CEP, você pratica:
- Eventos de formulário (
submit). - Validação de entrada.
- Requisições HTTP com
fetch. - Conversão de resposta para JSON.
- Assincronicidade com
async/await. - Tratamento de erro com
try...catch. - Manipulação do DOM para exibir resultados e mensagens.
- Boas práticas de experiência do usuário (estado de carregamento, mensagens claras).
Fluxo mental do projeto
A lógica principal:
- Usuário digita um CEP.
- Sistema limpa caracteres não numéricos.
- Sistema valida se tem 8 dígitos.
- Faz requisição para a API ViaCEP.
- Se vier sucesso, exibe rua, bairro, cidade e estado.
- Se vier erro, mostra mensagem amigável.
- Tudo isso sem recarregar a página.
Exemplo completo (HTML + CSS + JS em um único arquivo)
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Buscador de CEP</title>
<style>
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
background: #f5f7fb;
font-family: Arial, sans-serif;
}
.card {
width: 100%;
max-width: 420px;
background: #fff;
border-radius: 12px;
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.08);
padding: 20px;
}
h1 {
margin-top: 0;
text-align: center;
font-size: 1.3rem;
color: #222;
}
form {
display: flex;
gap: 8px;
margin-bottom: 12px;
}
input {
flex: 1;
padding: 10px;
border: 1px solid #cfd6e4;
border-radius: 8px;
font-size: 0.95rem;
}
button {
border: none;
background: #2563eb;
color: white;
padding: 10px 14px;
border-radius: 8px;
cursor: pointer;
}
button:hover {
background: #1f54c7;
}
#mensagem {
min-height: 20px;
margin: 8px 0;
color: #374151;
font-size: 0.95rem;
}
.erro {
color: #b91c1c;
}
.sucesso {
color: #065f46;
}
.resultado {
background: #eef2ff;
border-radius: 8px;
padding: 12px;
font-size: 0.95rem;
color: #1e3a8a;
line-height: 1.6;
}
</style>
</head>
<body>
<main class="card">
<h1>Buscador de CEP</h1>
<form id="form-cep">
<input id="cep" type="text" placeholder="Digite o CEP (ex: 01001000)" maxlength="9" />
<button type="submit">Buscar</button>
</form>
<p id="mensagem"></p>
<div id="resultado" class="resultado" style="display: none;"></div>
</main>
<script>
const form = document.getElementById("form-cep");
const inputCep = document.getElementById("cep");
const mensagem = document.getElementById("mensagem");
const resultado = document.getElementById("resultado");
function limparResultado() {
resultado.style.display = "none";
resultado.innerHTML = "";
}
function mostrarMensagem(texto, tipo = "") {
mensagem.textContent = texto;
mensagem.className = tipo;
}
function cepValido(cep) {
return /^[0-9]{8}$/.test(cep);
}
async function buscarCep(cep) {
const url = `https://viacep.com.br/ws/${cep}/json/`;
const resposta = await fetch(url);
if (!resposta.ok) {
throw new Error("Falha na comunicação com o servidor.");
}
const dados = await resposta.json();
if (dados.erro) {
throw new Error("CEP não encontrado.");
}
return dados;
}
function renderizarEndereco(dados) {
resultado.innerHTML = `
<strong>Logradouro:</strong> ${dados.logradouro || "-"}<br>
<strong>Bairro:</strong> ${dados.bairro || "-"}<br>
<strong>Cidade:</strong> ${dados.localidade || "-"}<br>
<strong>Estado:</strong> ${dados.uf || "-"}
`;
resultado.style.display = "block";
}
form.addEventListener("submit", async (event) => {
event.preventDefault();
limparResultado();
mostrarMensagem("");
const cepDigitado = inputCep.value.replace(/\D/g, "");
if (!cepValido(cepDigitado)) {
mostrarMensagem("Digite um CEP válido com 8 números.", "erro");
return;
}
try {
mostrarMensagem("Buscando CEP...", "");
const dados = await buscarCep(cepDigitado);
renderizarEndereco(dados);
mostrarMensagem("CEP encontrado com sucesso!", "sucesso");
} catch (erro) {
mostrarMensagem(erro.message, "erro");
}
});
</script>
</body>
</html>
Conceitos-chave que aparecem aqui
fetch(...): faz a requisição para a API.await: espera a resposta sem travar a interface.try...catch: captura e trata erros de forma amigável.- Regex
/\D/g: remove caracteres que não são números. - Validação de CEP: evita requisições desnecessárias.
- Atualização do DOM: mostra mensagens e dados na tela em tempo real.
Boas práticas usadas
- Validar antes de consultar API.
- Exibir estado de carregamento.
- Separar funções por responsabilidade.
- Tratar erros de rede e de CEP inexistente.
- Mensagens claras para o usuário final.
Ideias para evoluir o projeto
- Máscara de CEP automática (00000-000).
- Salvar histórico de buscas no
localStorage. - Buscar CEP ao sair do campo (
blur) além do botão. - Adicionar botão para limpar resultados.
- Usar
debouncepara evitar chamadas excessivas.