Node.js · algoritmo local + API
Validar CEP em Node.js
Para validar CEP em Node.js, confira o formato de 8 dígitos com hífen opcional e consulte o ViaCEP, porque o CEP não tem dígito verificador. Formato correto não garante que o CEP existe: 00000-000 passa na regex e não está na base dos Correios. Abaixo: uma função ES6 sem dependências para o formato, a consulta de existência e testes sem depender de rede.
Fonte: estrutura do CEP definida pelos Correios. A consulta de existência usa o ViaCEP, serviço público e gratuito.
TL;DR
const cep = '01310-100';
if (!/^\d{5}-?\d{3}$/.test(cep)) throw new Error('formato inválido');
const res = await fetch(`https://viacep.com.br/ws/${cep.replace('-', '')}/json/`);
const dados = await res.json();
console.log(dados.erro ? 'não existe' : `${dados.logradouro}, ${dados.localidade}/${dados.uf}`);Node 18+ (fetch nativo), sem npm install. Salve como .mjs e rode com node.
Rota 1: validar o formato do CEP em Node.js
Validação offline, instantânea e sem rede. Serve para barrar erro de digitação no formulário antes de qualquer consulta.
// validador-cep.mjs: formato (offline, Node 18+, zero dependências)
import { fileURLToPath } from 'node:url';
const FORMATO_CEP = /^\d{5}-?\d{3}$/;
/** 8 dígitos, hífen opcional depois do quinto. Não confirma que o CEP existe. */
export function cepFormatoValido(cep) {
return typeof cep === 'string' && FORMATO_CEP.test(cep.trim());
}
/** '01310-100' -> '01310100'. Lança erro se o formato for inválido. */
export function normalizaCep(cep) {
if (!cepFormatoValido(cep)) throw new Error(`CEP com formato inválido: ${cep}`);
return cep.trim().replace('-', '');
}
if (process.argv[1] === fileURLToPath(import.meta.url)) {
for (const cep of ['01310-100', '01310100', '1310-100', '01310-10', 'abcde-fgh']) {
console.log(cep.padEnd(12), cepFormatoValido(cep));
}
}Como o CEP é estruturado (e por que não existe dígito verificador)
Um exemplo calculado à mão, para você conferir o código contra a conta.
CEP 01310-100
0 1 3 1 0 - 1 0 0
| | | | | +-- 3 últimos dígitos: sufixo de distribuição (identifica o logradouro ou a unidade)
| | | | +-- 5º dígito: subdivisor de subsetor
| | | +-- 4º dígito: subsetor
| | +-- 3º dígito: setor
| +-- 2º dígito: subregião
+-- 1º dígito: região postal (0 = Grande São Paulo)
Não há dígito verificador: nenhuma conta prova que o CEP existe.
Só a consulta à base (ViaCEP) confirma.Rota 2: confirmar que o CEP existe com o ViaCEP
O ViaCEP responde 400 quando o formato é inválido e 200 com o campo erro quando o formato está certo mas o CEP não existe. O código abaixo trata os dois casos e deixa falha de rede propagar, sem confundir queda de serviço com CEP inexistente.
// existencia-cep.mjs: consulta ViaCEP (Node 18+). Salve a Rota 1 como validador-cep.mjs
import { fileURLToPath } from 'node:url';
import { cepFormatoValido, normalizaCep } from './validador-cep.mjs';
/** true se o CEP existe na base do ViaCEP. Erros de rede e 5xx viram exceção. */
export async function cepExiste(cep) {
if (!cepFormatoValido(cep)) return false;
const res = await fetch(`https://viacep.com.br/ws/${normalizaCep(cep)}/json/`, {
signal: AbortSignal.timeout(5000),
});
if (res.status === 400) return false; // ViaCEP responde 400 quando o formato é inválido
if (!res.ok) throw new Error(`ViaCEP respondeu ${res.status}`);
const dados = await res.json();
return !dados.erro; // CEP inexistente: 200 com { erro: "true" }
}
if (process.argv[1] === fileURLToPath(import.meta.url)) {
console.log(await cepExiste('01310-100')); // true (Av. Paulista, São Paulo)
console.log(await cepExiste('99999-999')); // false (formato ok, não existe)
console.log(await cepExiste('1234')); // false (formato inválido, nem consulta)
}Como testar o validador de CEP com Jest
Com Jest em modo ESM. Os testes trocam o fetch por um dublê, então rodam em CI sem acessar a internet.
// existencia-cep.test.mjs (Jest, sem rede: fetch é trocado por um dublê)
import { cepFormatoValido, normalizaCep } from './validador-cep.mjs';
import { cepExiste } from './existencia-cep.mjs';
describe('formato', () => {
test.each(['01310-100', '01310100', ' 01310-100 '])('aceita %p', (cep) => {
expect(cepFormatoValido(cep)).toBe(true);
});
test.each(['1310-100', '01310-10', '013101000', 'abcde-fgh', '', '01310--100'])('rejeita %p', (cep) => {
expect(cepFormatoValido(cep)).toBe(false);
});
test('normaliza', () => {
expect(normalizaCep('01310-100')).toBe('01310100');
expect(() => normalizaCep('123')).toThrow();
});
});
describe('existência (ViaCEP mockado)', () => {
const fetchOriginal = globalThis.fetch;
afterEach(() => { globalThis.fetch = fetchOriginal; });
const resposta = (status, corpo) => async () => ({ status, ok: status < 400, json: async () => corpo });
test('CEP existente', async () => {
globalThis.fetch = resposta(200, { cep: '01310-100', uf: 'SP' });
await expect(cepExiste('01310-100')).resolves.toBe(true);
});
test('CEP inexistente', async () => {
globalThis.fetch = resposta(200, { erro: 'true' });
await expect(cepExiste('99999-999')).resolves.toBe(false);
});
test('formato inválido nem consulta', async () => {
globalThis.fetch = () => { throw new Error('consultou a rede com CEP inválido'); };
await expect(cepExiste('123')).resolves.toBe(false);
});
});Validar CEP: algoritmo local ou serviço externo
| Cenário | Regex local | Consulta ao ViaCEP |
|---|---|---|
| Confere o formato de 8 dígitos | Sim | Sim, responde 400 |
| Confirma que o CEP existe | Não | Sim |
| Devolve logradouro, bairro, cidade e UF | Não | Sim |
| Funciona offline | Sim | Não |
| Latência | Desprezível | Depende da rede |
| Custo | R$ 0 | Gratuito |
Perguntas frequentes sobre validar CEP em Node.js
Como validar CEP em Node.js?+
Valide o formato com a regex /^\d{5}-?\d{3}$/ e depois consulte https://viacep.com.br/ws/{cep}/json/ com fetch. Resposta com o campo erro significa CEP inexistente. Sem dependências no Node 18+.
CEP tem dígito verificador?+
Não. O CEP tem 8 dígitos, escritos como 5 + hífen + 3, e nenhum deles é verificador. Validar um CEP significa checar o formato e depois confirmar a existência numa base, como o ViaCEP.
Como checar se um CEP existe?+
Consulte GET https://viacep.com.br/ws/{cep}/json/ com os 8 dígitos. Resposta 200 com dados significa que existe. Resposta 200 com o campo erro significa formato certo e CEP inexistente. HTTP 400 significa formato inválido.
O CEP 00000-000 é válido?+
No formato, sim: são 8 dígitos. Na existência, não: o ViaCEP devolve erro. É o exemplo clássico de por que só a regex não basta.
A API do FakeForge valida CEP?+
Não. A API gera CEPs com prefixo de região coerente (type=cep), mas não garante que cada um exista na base dos Correios. Para confirmar existência, use o ViaCEP ou a página /buscar-cep.