Para integrar validação de CPF em formulários HTML com JavaScript puro, combine três camadas: máscara de formatação automática no campo, validação local dos dígitos verificadores (algoritmo módulo 11) e consulta à API via backend para confirmar que o CPF existe. Nenhuma biblioteca externa é necessária — o código funciona em qualquer navegador moderno sem dependências.
Introdução
A validação de CPF em formulários HTML é uma das implementações mais comuns no desenvolvimento web brasileiro. Seja em cadastros de e-commerce, sistemas de atendimento, plataformas de serviços ou aplicações internas, o CPF é um campo presente em praticamente todo formulário voltado para o mercado nacional.
Implementar essa validação com JavaScript puro -- sem dependência de frameworks ou bibliotecas externas -- garante compatibilidade universal, performance máxima e controle total sobre o comportamento do campo. Combinada com uma consulta à API da CPFHub.io, a solução confirma que o CPF informado é real e retorna os dados do titular para cruzamento de identidade.
Estrutura do formulário HTML
O ponto de partida é um formulário HTML bem estruturado com os atributos corretos para campos de CPF:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cadastro com Validação de CPF</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: #f0f2f5;
padding: 40px 20px;
}
.form-container {
max-width: 480px;
margin: 0 auto;
background: white;
padding: 32px;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
}
h1 { font-size: 22px; margin-bottom: 24px; color: #1a1a2e; }
.form-group { margin-bottom: 20px; }
label {
display: block;
font-size: 14px;
font-weight: 600;
color: #374151;
margin-bottom: 6px;
}
input {
width: 100%;
padding: 12px 14px;
border: 2px solid #e5e7eb;
border-radius: 6px;
font-size: 16px;
transition: border-color 0.2s;
}
input:focus { outline: none; border-color: #3b82f6; }
input.valido { border-color: #16a34a; }
input.invalido { border-color: #ef4444; }
.mensagem {
font-size: 13px;
margin-top: 4px;
min-height: 18px;
}
.mensagem.sucesso { color: #16a34a; }
.mensagem.erro { color: #ef4444; }
.mensagem.info { color: #6b7280; }
button {
width: 100%;
padding: 14px;
background: #3b82f6;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
margin-top: 8px;
}
button:hover { background: #2563eb; }
button:disabled { background: #93c5fd; cursor: not-allowed; }
.resultado {
margin-top: 20px;
padding: 16px;
background: #f0fdf4;
border: 1px solid #bbf7d0;
border-radius: 6px;
display: none;
}
.resultado p { font-size: 14px; color: #166534; margin-bottom: 4px; }
</style>
</head>
<body>
<div class="form-container">
<h1>Cadastro</h1>
<form id="formCadastro" novalidate>
<div class="form-group">
<label for="nome">Nome completo</label>
<input type="text" id="nome" name="nome" placeholder="Seu nome completo"
required autocomplete="name" />
</div>
<div class="form-group">
<label for="cpf">CPF</label>
<input type="text" id="cpf" name="cpf" inputmode="numeric"
pattern="[0-9]*" maxlength="14" placeholder="000.000.000-00"
required autocomplete="off" />
<div id="cpfMensagem" class="mensagem"></div>
</div>
<div class="form-group">
<label for="email">E-mail</label>
<input type="email" id="email" name="email"
placeholder="seu@email.com" required autocomplete="email" />
</div>
<button type="submit" id="btnSubmit">Cadastrar</button>
</form>
<div id="resultado" class="resultado">
<p id="resultadoNome"></p>
<p id="resultadoCPF"></p>
</div>
</div>
<script src="cpf-validacao.js"></script>
</body>
</html>
Pontos importantes do HTML:
inputmode="numeric"-- Exibe o teclado numérico em dispositivos móveis.pattern="[0-9]*"-- Reforça a validação de formato no lado do cliente.maxlength="14"-- Limita o campo ao tamanho do CPF formatado (000.000.000-00).autocomplete="off"-- Evita autopreenchimento indesejado para o campo de CPF.
Máscara de formatação automática
A máscara formata o CPF enquanto o usuário digita, aplicando automaticamente os pontos e o hífen:
// cpf-validacao.js
/**
* Aplica máscara de formatação ao campo de CPF.
* Formato: 000.000.000-00
*/
function aplicarMascaraCPF(input) {
input.addEventListener('input', function () {
let valor = this.value.replace(/\D/g, '');
valor = valor.slice(0, 11);
if (valor.length > 9) {
valor = valor.replace(
/(\d{3})(\d{3})(\d{3})(\d{1,2})/,
'$1.$2.$3-$4'
);
} else if (valor.length > 6) {
valor = valor.replace(
/(\d{3})(\d{3})(\d{1,3})/,
'$1.$2.$3'
);
} else if (valor.length > 3) {
valor = valor.replace(
/(\d{3})(\d{1,3})/,
'$1.$2'
);
}
this.value = valor;
});
}
A máscara funciona removendo todos os caracteres não numéricos, limitando a 11 dígitos e aplicando a formatação conforme o número de dígitos digitados.
Validação dos dígitos verificadores
O CPF possui dois dígitos verificadores (10o e 11o dígitos) calculados pelo algoritmo módulo 11. A validação local verifica se esses dígitos estão corretos:
/**
* Valida os dígitos verificadores do CPF.
* Retorna true se o CPF é matematicamente válido.
*/
function validarCPFLocal(cpf) {
// Remover caracteres não numéricos
cpf = cpf.replace(/\D/g, '');
// Verificar se tem 11 dígitos
if (cpf.length !== 11) {
return false;
}
// Rejeitar CPFs com todos os dígitos iguais
if (/^(\d)\1{10}$/.test(cpf)) {
return false;
}
// Calcular dígitos verificadores
for (let t = 9; t < 11; t++) {
let soma = 0;
for (let i = 0; i < t; i++) {
soma += parseInt(cpf.charAt(i)) * ((t + 1) - i);
}
let digito = ((soma * 10) % 11) % 10;
if (digito !== parseInt(cpf.charAt(t))) {
return false;
}
}
return true;
}
Essa validação é instantânea e não requer chamada à API. Ela elimina CPFs com formato inválido antes de consumir consultas do seu plano.
Feedback visual em tempo real
Combine a máscara e a validação para fornecer feedback visual imediato ao usuário:
/**
* Configura validação em tempo real com feedback visual.
*/
function configurarValidacaoCPF(inputId, mensagemId) {
const input = document.getElementById(inputId);
const mensagem = document.getElementById(mensagemId);
// Aplicar máscara
aplicarMascaraCPF(input);
// Validar após cada entrada
input.addEventListener('input', function () {
const digitos = this.value.replace(/\D/g, '');
if (digitos.length < 11) {
// CPF incompleto
this.className = '';
mensagem.textContent = '';
mensagem.className = 'mensagem';
return;
}
if (validarCPFLocal(digitos)) {
// CPF com formato válido
this.className = 'valido';
mensagem.textContent = 'CPF com formato válido';
mensagem.className = 'mensagem sucesso';
} else {
// CPF com formato inválido
this.className = 'invalido';
mensagem.textContent = 'CPF inválido. Verifique os dígitos.';
mensagem.className = 'mensagem erro';
}
});
}
Consulta à API via backend
A validação local verifica apenas se o formato matemático está correto. Para confirmar que o CPF existe e obter os dados do titular, é necessário consultar a API da CPFHub.io via backend — nunca expondo a chave de API no front-end.
A chave de API nunca deve ser exposta no front-end. Sempre faça a chamada via backend:
Backend em Node.js (Express)
const express = require('express');
const app = express();
app.get('/api/validar-cpf/:cpf', async (req, res) => {
const { cpf } = req.params;
try {
const response = await fetch(`https://api.cpfhub.io/cpf/${cpf}`, {
method: 'GET',
headers: {
'x-api-key': process.env.CPFHUB_API_KEY,
'Accept': 'application/json'
},
timeout: 10000
});
const data = await response.json();
res.json(data);
} catch (error) {
res.status(500).json({ success: false, error: 'Erro na consulta' });
}
});
app.listen(3000);
Chamada à API no front-end (via backend)
/**
* Consulta a API (via backend) para verificar os dados do CPF.
*/
async function verificarCPFAPI(cpf) {
try {
const response = await fetch(`/api/validar-cpf/${cpf}`, {
method: 'GET',
headers: { 'Accept': 'application/json' }
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Erro na verificação:', error);
return { success: false, error: error.message };
}
}
Integrando tudo no formulário
Agora vamos conectar todas as peças -- máscara, validação local, consulta à API e envio do formulário:
document.addEventListener('DOMContentLoaded', function () {
// Configurar campo de CPF
configurarValidacaoCPF('cpf', 'cpfMensagem');
// Interceptar envio do formulário
const form = document.getElementById('formCadastro');
const btnSubmit = document.getElementById('btnSubmit');
const resultado = document.getElementById('resultado');
form.addEventListener('submit', async function (event) {
event.preventDefault();
const cpfInput = document.getElementById('cpf');
const nomeInput = document.getElementById('nome');
const mensagem = document.getElementById('cpfMensagem');
const cpf = cpfInput.value.replace(/\D/g, '');
// Validação local
if (!validarCPFLocal(cpf)) {
cpfInput.className = 'invalido';
mensagem.textContent = 'CPF inválido. Verifique os dígitos.';
mensagem.className = 'mensagem erro';
return;
}
// Desabilitar botão durante a consulta
btnSubmit.disabled = true;
btnSubmit.textContent = 'Verificando...';
mensagem.textContent = 'Consultando dados...';
mensagem.className = 'mensagem info';
// Consultar API via backend
const data = await verificarCPFAPI(cpf);
if (data.success) {
cpfInput.className = 'valido';
mensagem.textContent = 'CPF verificado com sucesso!';
mensagem.className = 'mensagem sucesso';
// Exibir resultado
document.getElementById('resultadoNome').textContent =
'Nome: ' + data.data.name;
document.getElementById('resultadoCPF').textContent =
'CPF: ' + cpfInput.value;
resultado.style.display = 'block';
// Aqui você pode prosseguir com o cadastro
// enviarCadastro({ cpf, nome: nomeInput.value, ... });
} else {
cpfInput.className = 'invalido';
mensagem.textContent = 'CPF não encontrado. Verifique o número.';
mensagem.className = 'mensagem erro';
resultado.style.display = 'none';
}
btnSubmit.disabled = false;
btnSubmit.textContent = 'Cadastrar';
});
});
Exemplo completo com cURL
Para testar a API diretamente, sem front-end:
curl -X GET https://api.cpfhub.io/cpf/12345678900 \
-H "x-api-key: SUA_CHAVE_DE_API" \
-H "Accept: application/json"
Resposta:
{
"success": true,
"data": {
"cpf": "12345678900",
"name": "João da Silva",
"nameUpper": "JOAO DA SILVA",
"gender": "M",
"birthDate": "15/06/1990",
"day": 15,
"month": 6,
"year": 1990
}
}
Boas práticas de segurança
Nunca exponha a API key no front-end
A chave de API deve estar apenas no servidor. O front-end chama o backend, que por sua vez chama a API da CPFHub.io.
Implemente rate limiting no seu backend
Para evitar abusos, limite o número de consultas que um único IP ou sessão pode fazer por minuto:
// Exemplo simples de rate limiting
const limitePorIP = {};
function verificarRateLimit(ip) {
const agora = Date.now();
if (!limitePorIP[ip]) {
limitePorIP[ip] = { contagem: 1, inicio: agora };
return true;
}
if (agora - limitePorIP[ip].inicio > 60000) {
limitePorIP[ip] = { contagem: 1, inicio: agora };
return true;
}
limitePorIP[ip].contagem++;
return limitePorIP[ip].contagem <= 10; // Máximo 10 consultas por minuto
}
Valide no servidor também
Nunca confie apenas na validação do front-end. O servidor deve validar o formato do CPF antes de chamar a API, pois requisições podem ser enviadas diretamente ao backend sem passar pelo front-end.
Sanitize os dados
Remova caracteres não numéricos do CPF antes de enviar à API e antes de armazenar no banco de dados. Para orientações de segurança mais amplas, o OWASP mantém guias sobre validação e sanitização de entrada de dados.
Compatibilidade de navegadores
A solução apresentada utiliza apenas JavaScript vanilla (puro) e é compatível com todos os navegadores modernos:
| Navegador | Versão mínima |
|---|---|
| Chrome | 55+ |
| Firefox | 52+ |
| Safari | 11+ |
| Edge | 79+ |
| Opera | 42+ |
| Samsung Internet | 6.2+ |
Para navegadores mais antigos que não suportam fetch, utilize XMLHttpRequest como fallback ou um polyfill.
Perguntas frequentes
Por que fazer a validação local antes de chamar a API?
A validação dos dígitos verificadores é instantânea e gratuita. Ela elimina CPFs matematicamente inválidos (digitados errado, sequências como 111.111.111-11) antes de consumir uma consulta do seu plano. A regra prática é: valide localmente primeiro, só chame a API quando o formato estiver correto.
A chave de API pode ser usada diretamente no JavaScript do front-end?
Não. Qualquer pessoa que inspecionar o código-fonte ou o tráfego de rede encontraria a chave e poderia consumi-la em nome da sua conta. Sempre faça a chamada à API pelo servidor, usando variáveis de ambiente para armazenar a chave (process.env.CPFHUB_API_KEY no Node.js).
O que fazer quando a API retorna success: false?
Exiba uma mensagem pedindo que o usuário verifique o número digitado. Não informe se o CPF "não existe" — isso pode ser explorado para enumerar CPFs válidos. Registre o evento no backend para monitorar tentativas suspeitas e aplique rate limiting por IP para dificultar ataques de força bruta.
Como adaptar essa solução para frameworks como React ou Vue?
A lógica de validação local (validarCPFLocal) e a máscara (aplicarMascaraCPF) funcionam como funções puras e podem ser importadas em qualquer componente. A chamada à API continua via backend — em React, por exemplo, use useEffect com debounce para disparar a consulta quando o CPF atingir 11 dígitos válidos.
Conclusão
Integrar a validação de CPF em formulários HTML com JavaScript puro é uma solução leve, performática e universalmente compatível. A combinação de máscara de formatação automática, validação local dos dígitos verificadores e consulta à API da CPFHub.io entrega uma experiência fluida para o usuário e segurança real para o sistema. Com tempo de resposta de aproximadamente 900ms e suporte a mais de 13 linguagens no backend, a integração funciona em qualquer stack tecnológica.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e adicione validação de CPF ao seu formulário HTML hoje mesmo.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



