Gerador de CEP para testes: formato, algoritmo e estados cobe...
Gerador de CEP para testes: formato, algoritmo e estados cobertos
CEP não é só um número de 8 dígitos. É um código com estrutura hierárquica definida pelos Correios, onde cada faixa de dígitos carrega informação geográfica. Gerar um CEP aleatório para teste e esperar que ele passe num formulário real é a receita para falsos positivos em QA — o campo aceita o dado, mas a integração com ViaCEP, o checkout ou o cálculo de frete quebra em produção. Este artigo explica a estrutura do CEP, como gerar valores geograficamente plausíveis e como o FakeForge resolve isso para os 10 estados com maior volume de testes.
CEP é um código estruturado, não aleatório
Anatomia dos 8 dígitos (faixa regional + setor + sufixo)
O CEP tem formato NNNNN-NNN. Os Correios dividem os 8 dígitos em três níveis:
- Dígitos 1-5 (faixa de distribuição): identificam a região de entrega. Os dois primeiros dígitos definem a grande região do país, e os três seguintes afunilam até o município ou distrito postal.
- Dígito 6 (setor): subdivide a faixa dentro da cidade.
- Dígitos 7-8 (sufixo): identificam o logradouro específico dentro do setor.
Um CEP como 01310-100 é a Avenida Paulista em São Paulo. O 01 indica a capital paulista, o 3 aponta para o setor Centro, e o sufixo 100 define o trecho exato da avenida.
Como os Correios atribuem faixas por estado e por cidade
Os Correios atribuem faixas por estado em blocos contíguos, definidos administrativamente. São Paulo começa em 01000-000 por ter o maior volume de logradouros. Estados menores recebem faixas mais estreitas. Essa atribuição não segue nenhum algoritmo público e padrão — é resultado de decisões administrativas históricas dos Correios, com a tabela oficial disponível no site ECT.
Faixas de CEP por estado: tabela de referência
Cobertura das 27 UFs com prefixos iniciais e finais
A tabela abaixo lista os prefixos (primeiros dois dígitos) por UF. Alguns estados compartilham prefixo — nesses casos, o terceiro dígito diferencia.
| UF | Prefixo inicial | Prefixo final | Exemplo de capital |
|---|---|---|---|
| SP | 01000-000 | 19999-999 | São Paulo |
| RJ | 20000-000 | 28999-999 | Rio de Janeiro |
| ES | 29000-000 | 29999-999 | Vitória |
| MG | 30000-000 | 39999-999 | Belo Horizonte |
| BA | 40000-000 | 48999-999 | Salvador |
| SE | 49000-000 | 49999-999 | Aracaju |
| PE | 50000-000 | 56999-999 | Recife |
| AL | 57000-000 | 57999-999 | Maceió |
| PB | 58000-000 | 58999-999 | João Pessoa |
| RN | 59000-000 | 59999-999 | Natal |
| CE | 60000-000 | 63999-999 | Fortaleza |
| PI | 64000-000 | 64999-999 | Teresina |
| MA | 65000-000 | 65999-999 | São Luís |
| PA | 66000-000 | 68899-999 | Belém |
| AP | 68900-000 | 68999-999 | Macapá |
| AM | 69000-000 | 69299-999 | Manaus |
| RR | 69300-000 | 69399-999 | Boa Vista |
| AC | 69900-000 | 69999-999 | Rio Branco |
| DF | 70000-000 | 73699-999 | Brasília |
| GO | 73700-000 | 76799-999 | Goiânia |
| TO | 77000-000 | 77999-999 | Palmas |
| MS | 79000-000 | 79999-999 | Campo Grande |
| MT | 78000-000 | 78899-999 | Cuiabá |
| RO | 78900-000 | 78999-999 | Porto Velho |
| PR | 80000-000 | 87999-999 | Curitiba |
| SC | 88000-000 | 89999-999 | Florianópolis |
| RS | 90000-000 | 99999-999 | Porto Alegre |
Por que CEPs de regiões distintas têm estruturas diferentes
A faixa de SP vai de 01000-000 a 19999-999 — quase 19 milhões de CEPs possíveis para cobrir o estado mais populoso. O AM vai de 69000-000 a 69299-999 — cerca de 300 mil CEPs para um estado com distribuição urbana concentrada em Manaus. Essa assimetria reflete densidade populacional e volume de logradouros cadastrados. Para testes que envolvem cálculo de frete por região, ignorar essas faixas gera dados que nunca existiriam na base dos Correios.
O que torna um CEP "válido" para fins de teste
Formato obrigatório (NNNNN-NNN) e regras de comprimento
O formato NNNNN-NNN é obrigatório. Oito dígitos numéricos, hífen obrigatório na posição 6. Sistemas legados às vezes aceitam NNNNNNNN sem hífen, mas qualquer API pública dos Correios ou serviço como ViaCEP rejeita o formato sem separador. Validação de comprimento é necessária, mas não suficiente.
Correlação obrigatória: CEP + cidade + estado + bairro precisam ser coerentes
Um CEP 01310-100 que vem acompanhado de cidade: Curitiba, estado: PR vai falhar em qualquer integração que consulte o CEP numa API de endereço. A cidade e o estado precisam bater com a faixa do CEP. Para fixtures de banco de dados, isso significa que gerar CEP e cidade independentemente cria dados inconsistentes que causam regressão em testes de integração.
Diferença entre CEP sintaticamente correto e CEP geograficamente plausível
99999-999 passa qualquer validação de formato. Não existe na base dos Correios. 01000-000 também passa a validação e é o CEP do Largo do Paissandu em São Paulo — existe de verdade. Para a maioria dos testes, um CEP dentro da faixa correta da UF é suficiente. Para testes de integração com ViaCEP ou APIs de frete, o CEP precisa existir na base.
DICA: Para testes unitários de validação de formulário, um CEP dentro da faixa da UF é suficiente. Para testes de integração que consultam APIs externas, use CEPs reais conhecidos como constantes de fixture — não tente gerá-los sinteticamente.
Abordagem naive e por que ela falha em testes reais
Gerar string aleatória de 8 dígitos: o que quebra downstream
// Não faça isso
const cep = Math.floor(Math.random() * 100000000).toString().padStart(8, '0');Esse trecho produz CEPs como 00000000 ou 99999999, que não pertencem a nenhum estado. Em produção, o campo de formulário pode aceitar o valor, mas o cálculo de frete retorna erro, o preenchimento automático de endereço falha e o log de erro não indica onde está o problema — porque o dado passou na validação de formato.
Casos concretos: campo de endereço, integração com ViaCEP, checkout de e-commerce
- Campo de endereço com autopreenchimento: consulta o ViaCEP com o CEP do fixture. CEP fora de faixa retorna 404. O teste falha com mensagem de erro de rede, não de lógica de negócio.
- Checkout de e-commerce: calculadoras de frete como Melhor Envio usam o CEP de destino para determinar prazo e valor. Um CEP
00000000retorna erro de UF desconhecida. - Cadastro de fornecedor com CNPJ: o endereço do CNPJ precisa ter CEP coerente com o estado do CNPJ. Um CNPJ com inscrição estadual de SP acompanhado de CEP
90000-000(RS) levanta flag em validações de consistência.
Como implementar um gerador de CEP correlacionado
Estrutura de dados mínima: tabela de faixas por UF
interface UFRange {
uf: string;
city: string;
min: number;
max: number;
neighborhoods: string[];
}
const UF_RANGES: UFRange[] = [
{
uf: 'SP',
city: 'São Paulo',
min: 1000000,
max: 5999999,
neighborhoods: ['Centro', 'Pinheiros', 'Vila Madalena', 'Moema', 'Santana'],
},
{
uf: 'RJ',
city: 'Rio de Janeiro',
min: 20000000,
max: 23799999,
neighborhoods: ['Centro', 'Copacabana', 'Ipanema', 'Tijuca', 'Botafogo'],
},
{
uf: 'PR',
city: 'Curitiba',
min: 80000000,
max: 82999999,
neighborhoods: ['Centro', 'Batel', 'Água Verde', 'Portão', 'Boa Vista'],
},
];Sorteio dentro da faixa + composição de cidade e bairro coerentes
function generateCEP(uf: string): string {
const range = UF_RANGES.find((r) => r.uf === uf);
if (!range) throw new Error(`UF não suportada: ${uf}`);
const raw = Math.floor(Math.random() * (range.max - range.min + 1)) + range.min;
const digits = raw.toString().padStart(8, '0');
return `${digits.slice(0, 5)}-${digits.slice(5)}`;
}Exemplo de implementação em TypeScript
interface Address {
cep: string;
city: string;
state: string;
neighborhood: string;
}
function generateAddress(uf: string): Address {
const range = UF_RANGES.find((r) => r.uf === uf);
if (!range) throw new Error(`UF não suportada: ${uf}`);
const cep = generateCEP(uf);
const neighborhood =
range.neighborhoods[Math.floor(Math.random() * range.neighborhoods.length)];
return {
cep,
city: range.city,
state: range.uf,
neighborhood,
};
}
// Uso
const address = generateAddress('SP');
// { cep: '03421-780', city: 'São Paulo', state: 'SP', neighborhood: 'Moema' }Geração em volume: seed scripts e fixtures
Gerar N endereços distintos para popular banco de dados de teste
Para popular uma tabela de clientes de teste com endereços distribuídos entre estados, a abordagem mais simples é iterar sobre as UFs disponíveis em round-robin:
function generateAddresses(count: number): Address[] {
const ufs = UF_RANGES.map((r) => r.uf);
return Array.from({ length: count }, (_, i) =>
generateAddress(ufs[i % ufs.length])
);
}Export SQL com CREATE TABLE pronto para rodar em CI
O FakeForge gera o bloco SQL completo, incluindo CREATE TABLE e os INSERT correspondentes. O export está disponível via API com format=sql. O resultado é pronto para rodar em PostgreSQL, MySQL ou SQLite sem ajuste manual.
-- Generated by FakeForge BR -- free Brazilian test data
-- https://fakeforge.com.br
-- Generated at: 2026-06-04T10:00:00Z
-- License: CC0 (public domain test data)
CREATE TABLE IF NOT EXISTS enderecos (
id SERIAL PRIMARY KEY,
cep VARCHAR(9) NOT NULL,
cidade VARCHAR(100) NOT NULL,
estado CHAR(2) NOT NULL,
bairro VARCHAR(100) NOT NULL
);
INSERT INTO enderecos (cep, cidade, estado, bairro) VALUES
('01310-100', 'São Paulo', 'SP', 'Centro'),
('80010-020', 'Curitiba', 'PR', 'Batel'),
('90010-150', 'Porto Alegre', 'RS', 'Centro Histórico');Integração com a API do FakeForge
Endpoint /api/generate?type=cep&quantity=50&format=json
O endpoint REST aceita type=cep, quantity de 1 a 10.000 e format como json, csv ou sql. Sem autenticação para até 100 chamadas por dia no plano gratuito. Acima disso, os planos pagos desbloqueiam volume maior e SLA de resposta.
Parâmetros de formato: json, csv, sql
curl "https://fakeforge.com.br/api/generate?type=cep&quantity=10&format=csv"A resposta CSV inclui cabeçalho com os nomes das colunas. O formato SQL inclui o CREATE TABLE seguido dos INSERT. O formato JSON retorna um array de objetos com os campos cep, cidade, estado e bairro.
Exemplo de chamada com fetch e com curl
interface CEPResponse {
_meta: {
source: string;
url: string;
generated_at: string;
license: string;
};
type: string;
quantity: number;
data: Array<{
cep: string;
cidade: string;
estado: string;
bairro: string;
}>;
}
async function fetchCEPs(quantity: number): Promise<CEPResponse> {
const response = await fetch(
`https://fakeforge.com.br/api/generate?type=cep&quantity=${quantity}&format=json`
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json() as Promise<CEPResponse>;
}
// Uso em setup de teste
const { data: enderecos } = await fetchCEPs(50);A documentação completa da API, incluindo todos os tipos e parâmetros disponíveis, está em /docs.
Considerações de LGPD ao usar CEPs em testes
CEP não é dado pessoal isolado, mas pode ser quando combinado
O CEP sozinho não identifica uma pessoa. Combinado com nome, CPF ou data de nascimento, passa a integrar um conjunto de dados pessoais conforme LGPD Art. 5º, I. Um banco de dados de teste com cpf + nome + endereço real é um conjunto de dados pessoais, mesmo que seja para fins internos.
Ambientes de teste devem usar dados sintéticos, não dumps de produção
O LGPD Art. 46 exige medidas técnicas e administrativas para proteger dados pessoais contra acessos não autorizados. Um dump de produção usado em ambiente de desenvolvimento — com acesso menos restrito, sem criptografia completa, compartilhado entre membros da equipe — falha nesse requisito. A ANPD já indicou, em guias de boas práticas, que a anonimização ou síntese de dados para ambientes de teste é a abordagem adequada.
Por que dados gerados sinteticamente eliminam o risco de exposição
Dados gerados pelo FakeForge não têm correspondência com pessoas reais. O CEP 03421-780 gerado sinteticamente não pertence a nenhum titular identificável. Mesmo que o banco de dados de teste vaze, não há dado pessoal exposto — porque nenhum dado pessoal foi inserido. Isso elimina a necessidade de anonimização post-hoc e simplifica o processo de resposta a incidentes.
AVISO: Usar dados reais de clientes em ambiente de staging ou desenvolvimento é infração ao Art. 46 da LGPD e sujeita a multa de até 2% do faturamento, limitada a R$ 50 milhões por infração, conforme Art. 52.
Estados e capitais cobertos no FakeForge
As 10 capitais com dados de bairro curados
O gerador de CEP do FakeForge tem dados de bairro curados para 10 capitais: São Paulo, Rio de Janeiro, Belo Horizonte, Porto Alegre, Salvador, Fortaleza, Recife, Manaus, Brasília e Curitiba. Para essas cidades, o endereço gerado inclui bairros reais com nomes corretos e CEP dentro da faixa correta da capital. As páginas específicas, como /gerador-cep/sao-paulo e /gerador-cep/rio-de-janeiro, mostram exemplos com os bairros disponíveis.
Cobertura das demais UFs por faixa de prefixo sem dados de bairro específicos
Para os 17 estados restantes, o FakeForge gera CEPs dentro da faixa correta da UF com cidade capital e estado coerentes, mas sem lista curada de bairros. O bairro retornado é genérico ("Centro") ou omitido, dependendo do contexto. Isso é suficiente para a maioria dos testes de formulário e integração que só validam estado e cidade.
Como o projeto define o equilíbrio entre cobertura e precisão geográfica
Manter dados de bairro curados para 27 estados exige atualização contínua, porque os Correios alteram faixas de CEP com frequência. O recorte das 10 capitais cobre mais de 60% dos testes típicos de sistemas BR, onde o foco é nos grandes centros urbanos. Para casos que precisam de cobertura completa de bairros por estado, a integração com a API dos Correios ou com o ViaCEP em ambiente de teste controlado é a abordagem mais precisa.
Para gerar uma pessoa completa com endereço correlacionado — nome, CPF, telefone e CEP do mesmo estado — ou uma empresa com CNPJ e endereço coerente, os geradores compostos do FakeForge fazem esse trabalho de correlação automaticamente.
Resumo
- CEP tem estrutura hierárquica definida pelos Correios. Gerar 8 dígitos aleatórios produz dados fora de qualquer faixa de UF e quebra integrações downstream.
- Cada UF tem faixas de prefixo específicas. A tabela neste artigo cobre as 27 UFs com os limites inicial e final de cada estado.
- Um CEP válido para teste precisa de correlação: CEP + cidade + estado + bairro devem ser coerentes entre si, não gerados independentemente.
- Use CEPs sintéticos dentro da faixa correta da UF para testes unitários e de formulário. Para testes de integração com ViaCEP ou APIs de frete, prefira CEPs reais conhecidos como constantes de fixture.
- Dados sintéticos eliminam o risco de LGPD em ambientes de teste. Dumps de produção com CEP + CPF + nome constituem conjunto de dados pessoais sujeito ao Art. 46.
- O FakeForge cobre 10 capitais com bairros curados e todas as 27 UFs por faixa de prefixo, com export via API em JSON, CSV e SQL com
CREATE TABLEpronto para CI.
Perguntas frequentes
Como validar se um CEP gerado está dentro da faixa correta sem chamar API?+
Precisa estar entre min e max da UF. Exemplo: SP [01000000, 19999999]. Extraia os 2 primeiros dígitos como número inteiro, compare com a tabela de ranges do artigo. Não confunda com validação de formato (NNNNN-NNN) — essa só garante sintaxe, não faixa. Para testes unitários, basta isso. Para integração, CEP real é mais seguro.
Posso usar qualquer CEP dentro da faixa de São Paulo em um teste de e-commerce?+
Para validação de formato, sim. Para checkout com cálculo de frete real, não — a maioria das APIs (Melhor Envio, Sedex) rejeita CEPs inexistentes. Use CEPs reais conhecidos como constantes (`01310-100` = Avenida Paulista). Gerar sintético serve para testes unitários, não para integração com terceiros.
Como estruturar fixtures de teste (CPF + nome + CEP) sem violar LGPD?+
Gere tudo sinteticamente com o FakeForge — CPF, nome e CEP não correspondem a pessoas reais. Não use dumps de produção nem dados de clientes reais. Dados sintéticos sem correspondência à realidade não são "dados pessoais" conforme LGPD Art. 5º, eliminando risco de infração ao Art. 46.
Os CEPs gerados pelo FakeForge existem realmente nos Correios?+
Não. São sinteticamente válidos dentro da faixa de cada UF, mas não correspondem a logradouros reais cadastrados nos Correios. Para testes unitários de validação de formato, é suficiente. Para testes de integração com ViaCEP que consultam a base real, use CEPs conhecidos ou mock a resposta da API.
Como debugar se o teste falha por CEP inválido ou por lógica bugada?+
Valide o CEP isoladamente contra a faixa da UF antes de rodar o teste. Se passa nessa validação mas falha em integração com ViaCEP, o problema é a lógica ou a API mockada, não o formato. Log o CEP, cidade, estado recebidos e compare com a resposta esperada — identifica mismatch entre geração e integração rapidamente.