Artigo Build·Desenvolvimento·12 min de leitura

Como Gerar CPF Válido em JavaScript: Algoritmo Completo

Gerar um CPF matematicamente válido em JavaScript é trivial depois que você entende o algoritmo de módulo 11. Este guia traz o código completo (20 linhas), variações (TypeScript, geração em lote, por região fiscal, com máscara) e o contexto legal — porque CPF gerado pode coincidir com um real.

Vitor Morais

Por Vitor Morais

Fundador do MochaLabz ·

🪪

Prefere uma ferramenta pronta?

Gere CPFs válidos para teste com formatação, em lote e opção por estado — 100% no navegador.

Usar gerador de CPF →

Gerar um CPF matematicamente válido em JavaScript é trivial depois de entender o algoritmo de módulo 11 que a Receita Federal usa para calcular os dígitos verificadores. Em ~20 linhas você tem uma função pronta; em 50 linhas tem uma versão robusta com TypeScript, geração em lote e por região fiscal. Este guia cobre tudo, com o contexto legal importante (CPFs gerados podem coincidir com CPFs reais — use apenas em testes).

Como o algoritmo do CPF funciona

O CPF tem 11 dígitos. Os 9 primeiros são o número-base (sequencial emitido pela Receita); os 2 últimos são os dígitos verificadores (DV) calculados com módulo 11 sobre os 9 primeiros. Para gerar um CPF válido, basta:

  1. Gerar 9 dígitos aleatórios (o número-base).
  2. Calcular o 1º DV com módulo 11 (pesos 10 a 2).
  3. Calcular o 2º DV com módulo 11 (pesos 11 a 2).
  4. Rejeitar sequências repetidas (111...1, 222...2 etc).

Para a teoria detalhada do módulo 11, veja algoritmo do dígito verificador do CPF.

Implementação completa em JavaScript

/** * Calcula um dígito verificador via módulo 11. * @param digits - array de dígitos base * @param pesoInicial - peso do primeiro dígito (10 para DV1, 11 para DV2) */ function calcDV(digits, pesoInicial) { const soma = digits.reduce( (acc, d, i) => acc + d * (pesoInicial - i), 0, ); const resto = soma % 11; return resto < 2 ? 0 : 11 - resto; } /** * Gera um CPF matematicamente válido. * @param format - true retorna "000.000.000-00"; false retorna "00000000000" */ function generateCPF(format = true) { // 1. Gera 9 dígitos aleatórios const base = Array.from( { length: 9 }, () => Math.floor(Math.random() * 10), ); // 2. Rejeita sequências repetidas (000...0 até 999...9) if (base.every((d) => d === base[0])) return generateCPF(format); // 3. Calcula os dois dígitos verificadores const dv1 = calcDV(base, 10); const dv2 = calcDV([...base, dv1], 11); const cpf = [...base, dv1, dv2].join(''); if (!format) return cpf; // 4. Aplica máscara XXX.XXX.XXX-XX return cpf.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4'); } // Uso generateCPF(); // "432.519.873-05" generateCPF(false); // "43251987305"

Versão em TypeScript

function calcDV(digits: number[], pesoInicial: number): number { const soma = digits.reduce( (acc, d, i) => acc + d * (pesoInicial - i), 0, ); const resto = soma % 11; return resto < 2 ? 0 : 11 - resto; } export function generateCPF(format = true): string { const base = Array.from( { length: 9 }, () => Math.floor(Math.random() * 10), ); if (base.every((d) => d === base[0])) return generateCPF(format); const dv1 = calcDV(base, 10); const dv2 = calcDV([...base, dv1], 11); const cpf = [...base, dv1, dv2].join(''); if (!format) return cpf; return cpf.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4'); } export function generateCPFs(count: number, format = true): string[] { return Array.from({ length: count }, () => generateCPF(format)); }

Geração em lote com unicidade garantida

Para muitos CPFs sem duplicatas, use Set para deduplicar:

function generateUniqueCPFs(count: number, format = true): string[] { const set = new Set<string>(); while (set.size < count) { set.add(generateCPF(false)); // sempre sem máscara no Set } const arr = Array.from(set); if (!format) return arr; return arr.map((cpf) => cpf.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4') ); } // 10 mil CPFs únicos em ~50ms no Node moderno const cpfs = generateUniqueCPFs(10_000);

Lotes muito grandes

Para lotes > 100k, gere sequencialmente partindo de um número-base incrementando em 1 e calculando os DVs. Garante unicidade sem custo de hash do Set, útil em seeds massivos de banco de dados.

Gerar CPF de uma região fiscal específica

O 9º dígito do CPF (posição 9 do número-base de 11 dígitos) identifica a região fiscal. Para gerar CPF de SP, por exemplo, fixe o 9º dígito como 8:

9º dígito do CPF e região fiscal correspondente
CritérioRegião Fiscal
1DF, GO, MS, MT, TO
2AC, AM, AP, PA, RO, RR
3CE, MA, PI
4AL, PB, PE, RN
5BA, SE
6MG
7ES, RJ
8SP
9PR, SC
0RS
type RegiaoFiscal = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; export function generateCPFByRegion( regiao: RegiaoFiscal, format = true, ): string { // 8 dígitos aleatórios + regiao na posição 9 const base = [ ...Array.from({ length: 8 }, () => Math.floor(Math.random() * 10)), regiao, ]; // Evita sequência toda igual (caso particular quando regiao // também é o dígito aleatório) if (base.every((d) => d === base[0])) return generateCPFByRegion(regiao, format); const dv1 = calcDV(base, 10); const dv2 = calcDV([...base, dv1], 11); const cpf = [...base, dv1, dv2].join(''); if (!format) return cpf; return cpf.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4'); } generateCPFByRegion(8); // CPF emitido em SP generateCPFByRegion(6); // CPF emitido em MG

Versão com crypto.getRandomValues

Para apps que precisam de aleatoriedade criptograficamente forte (raro em geração de CPF de teste, mas disponível):

function randomDigit(): number { // Usa 4 bytes e mapeia para 0-9 sem módulo bias const buf = new Uint32Array(1); crypto.getRandomValues(buf); return buf[0] % 10; } export function generateCPFCrypto(format = true): string { const base = Array.from({ length: 9 }, randomDigit); if (base.every((d) => d === base[0])) return generateCPFCrypto(format); const dv1 = calcDV(base, 10); const dv2 = calcDV([...base, dv1], 11); const cpf = [...base, dv1, dv2].join(''); if (!format) return cpf; return cpf.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4'); }

Integrando com Faker.js

Para gerar personas fictícias completas (nome, e-mail, endereço e CPF), combine com Faker.js:

// npm install @faker-js/faker import { fakerPT_BR as faker } from '@faker-js/faker'; export interface Persona { nome: string; cpf: string; email: string; telefone: string; endereco: { rua: string; cidade: string; uf: string; cep: string; }; } export function generatePersona(): Persona { return { nome: faker.person.fullName(), cpf: generateCPF(), email: faker.internet.email(), telefone: faker.phone.number({ style: 'national' }), endereco: { rua: faker.location.street(), cidade: faker.location.city(), uf: faker.location.state({ abbreviated: true }), cep: faker.location.zipCode('#####-###'), }, }; } // Gerar 100 personas para seed de teste const users = Array.from({ length: 100 }, generatePersona);

Testes para o gerador

// __tests__/cpf.test.ts (Vitest / Jest) import { describe, expect, it } from 'vitest'; import { generateCPF, generateCPFs, validateCPF } from './cpf'; describe('generateCPF', () => { it('gera CPF no formato XXX.XXX.XXX-XX', () => { expect(generateCPF()).toMatch(/^\d{3}\.\d{3}\.\d{3}-\d{2}$/); }); it('gera CPF sem máscara quando format=false', () => { expect(generateCPF(false)).toMatch(/^\d{11}$/); }); it('gera CPF que passa na validação', () => { for (let i = 0; i < 100; i++) { expect(validateCPF(generateCPF())).toBe(true); } }); it('nunca gera sequência repetida', () => { for (let i = 0; i < 10_000; i++) { const cpf = generateCPF(false); expect(cpf).not.toMatch(/^(\d)\1{10}$/); } }); }); describe('generateCPFs', () => { it('gera a quantidade pedida', () => { expect(generateCPFs(50)).toHaveLength(50); }); });

Validação (complementar à geração)

A mesma função calcDV serve para validar um CPF fornecido:

export function validateCPF(input: string): boolean { const cpf = input.replace(/[^\d]/g, ''); if (cpf.length !== 11) return false; if (/^(\d)\1{10}$/.test(cpf)) return false; const nums = cpf.split('').map(Number); const dv1 = calcDV(nums.slice(0, 9), 10); const dv2 = calcDV(nums.slice(0, 10), 11); return nums[9] === dv1 && nums[10] === dv2; } validateCPF('432.519.873-05'); // true (ou false, depende do cálculo) validateCPF('111.111.111-11'); // false (repetido) validateCPF('abc'); // false (formato errado)

CPF alfanumérico (a partir de julho/2026)

A partir de julho de 2026, a Receita começa a emitir CPFs com letras (A-Z) nos 9 primeiros caracteres. Os 2 últimos continuam sendo dígitos verificadores. Versão adaptada do gerador:

// Alfabeto permitido nas 9 primeiras posições const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; function toValue(c: string): number { // Valor ASCII menos 48 (padrão Receita) return c.charCodeAt(0) - 48; } export function generateCPFAlfa(format = true): string { const base = Array.from( { length: 9 }, () => ALPHABET[Math.floor(Math.random() * ALPHABET.length)], ); // DV usa valor ASCII-48 de cada caractere const values = base.map(toValue); const calcDVAlfa = (vals: number[], pesoInicial: number) => { const soma = vals.reduce( (acc, v, i) => acc + v * (pesoInicial - i), 0, ); const resto = soma % 11; return resto < 2 ? 0 : 11 - resto; }; const dv1 = calcDVAlfa(values, 10); const dv2 = calcDVAlfa([...values, dv1], 11); const cpf = [...base, String(dv1), String(dv2)].join(''); if (!format) return cpf; return cpf.replace(/^(.{3})(.{3})(.{3})(.{2})$/, '$1.$2.$3-$4'); } // Exemplo: "AB2.5C7.89X-42"

Comparativo de implementações

Formas de gerar CPF válido e quando usar cada uma
CritérioQuando usar
Implementação manual (mostrada acima)Aprendizado, controle total, sem dependência
@faker-js/faker (faker.br.cpf)Personas completas em massa, seed de banco
cpf-cnpj-validator (npm)Só validação — não gera
brazilian-values (npm)Validar + gerar + formatar, TypeScript-first
Gerador online (sem código)Testes manuais, populando forms UI

Aviso legal importante

Use apenas em testes

CPFs gerados por algoritmo são matematicamente válidos, mas podem coincidir com CPFs de pessoas reais. Há 1 bilhão de combinações possíveis de número-base, e a Receita já emitiu mais de 280 milhões de CPFs — a probabilidade de colisão é baixa mas não zero.

Usar CPF gerado para qualquer transação real (abrir conta, cadastro fiscal, compra em nome de terceiro) pode configurar falsidade ideológica e estelionato — crimes previstos nos artigos 299 e 171 do Código Penal. Use SEMPRE apenas em ambientes de desenvolvimento e teste isolados.

Casos de uso legítimos

  • Seed de banco de dados para desenvolvimento local.
  • Dados fictícios para QA em ambientes de staging/teste.
  • Testes automatizados (unit, integração, e2e) que precisam de CPF válido.
  • Validação de formulários com payload sintético.
  • Demos e screencasts sem expor dados reais.
  • Load testing com usuários sintéticos.
  • Mock de API em desenvolvimento offline.

Para contexto completo sobre testes com dados fictícios, veja CPF para testes: como usar com segurança e dados fictícios para testes de software.

Erros comuns ao implementar

Armadilhas frequentes

  • Esquecer de rejeitar sequências repetidas: 111.111.111-11 passa no módulo 11 mas é oficialmente inválido.
  • Usar Math.floor(Math.random() * 10) em loop sem Array.from: JS tem semântica peculiar em new Array(n).fill() — prefira Array.from.
  • Peso errado no DV2: começa em 11, não em 10. Erro comum que gera CPFs com DV2 inválido.
  • Não validar o resultado: sempre teste o CPF gerado contra sua função de validação para pegar bugs.
  • Formatar antes de usar em teste: armazene os 11 dígitos puros; formate só na exibição.
  • Regex de máscara mal feita: (\d{3})(\d{3})(\d{3})(\d{2}) exige exatamente 11 dígitos; verifique antes de aplicar.

Checklist do gerador completo

  • ✅ Função calcDV isolada, testável e reutilizável.
  • ✅ Geração de 9 dígitos aleatórios com Math.random() ou crypto.getRandomValues().
  • ✅ Rejeição de sequências repetidas.
  • ✅ Cálculo dos 2 DVs com pesos corretos (10-2 e 11-2).
  • ✅ Opção de formatar com máscara ou não.
  • ✅ Versão em lote deduplicada (Set ou sequencial).
  • ✅ Variante por região fiscal quando útil.
  • ✅ Testes cobrindo valid, mask, sem mask, lote, sequências repetidas.
  • ✅ Integração com Faker.js para personas completas.
  • ✅ Comentários / documentação sobre uso apenas em teste.
  • ✅ Uma linha explícita de aviso legal no README.

Perguntas frequentes

É legal gerar CPFs válidos em código?+

Gerar CPFs matematicamente válidos para uso em DESENVOLVIMENTO e TESTES é completamente legal. O que é crime é usar CPF alheio (real, de outra pessoa) sem autorização ou para se passar por alguém (falsidade ideológica, estelionato). CPFs gerados por algoritmo passam na validação matemática mas NÃO são cadastrados na Receita Federal — são apenas 11 dígitos que seguem a regra do módulo 11.

Um CPF gerado pode coincidir com o de uma pessoa real?+

Matematicamente, pode — há apenas 9 dígitos-base possíveis (1 bilhão de combinações), e a Receita já emitiu mais de 280 milhões de CPFs. Por isso NUNCA use CPFs gerados fora de ambiente de teste: é possível que um CPF fictício "bata" com o de alguém real, e usar isso para transações reais é crime independente da intenção.

Math.random() é seguro para gerar CPF?+

Para testes e desenvolvimento, é perfeitamente adequado. Math.random() não é criptograficamente seguro (previsível com esforço), mas para seedar dados fictícios que não precisam ser imprevisíveis, funciona bem. Para aplicações onde imprevisibilidade importa (geração de tokens, IDs de sessão), use crypto.getRandomValues() — mas CPF de teste não é um desses casos.

Como gerar CPF de um estado específico?+

O 9º dígito do CPF (posição 9 do número-base) identifica a região fiscal: 1=DF/GO/MS/MT/TO, 2=AC/AM/AP/PA/RO/RR, 3=CE/MA/PI, 4=AL/PB/PE/RN, 5=BA/SE, 6=MG, 7=ES/RJ, 8=SP, 9=PR/SC, 0=RS. Para gerar CPF de SP, basta fixar o 9º dígito como 8 antes de calcular os verificadores.

Como integrar com Faker.js para dados fictícios completos?+

Faker.js tem locale pt-BR com faker.br.cpf(), mas a implementação do Faker só funciona em @faker-js/faker 8+. Para personas completas (nome + email + CPF + endereço), combine faker.person.fullName() + faker.internet.email() + sua função generateCPF(). Bibliotecas como brazilian-values do GitHub também oferecem geradores específicos com boa qualidade.

Posso gerar CPF alfanumérico para testes do novo formato 2026?+

Sim. A partir de julho/2026 a Receita começa a emitir CPFs alfanuméricos (letras A-Z + dígitos nos 9 primeiros caracteres, os 2 últimos sempre dígitos). O algoritmo de módulo 11 continua, mas opera sobre o valor ASCII-48 de cada caractere (A=17, B=18, etc). Sua função de geração deve ser atualizada para escolher aleatoriamente entre [0-9A-Z] nas 9 primeiras posições.

Como gerar 10 mil CPFs rapidamente sem duplicar?+

Para lotes pequenos, gere e filtre com Set. Para lotes grandes (100k+), considere gerar sequencialmente partindo de um número-base e calcular DVs — evita colisão garantidamente. Performance: gerar 10 mil CPFs com módulo 11 leva ~50ms em Node moderno; não vale otimizar prematuramente.

Existe alguma biblioteca pronta em vez de implementar?+

Sim. Em npm: cpf-cnpj-validator, @faker-js/faker (com locale pt_BR), brazilian-values, gerador-validador-de-cpf-e-cnpj. Para TypeScript, cpf-cnpj-validator tem tipos bem definidos. Para testes, @faker-js/faker é a escolha padrão porque já vem com gerador de nome + endereço + telefone em português.

#cpf#javascript#typescript#algoritmo#gerador#validação#módulo 11#faker#região fiscal#testes

Continue lendo