Fraude de novo cadastro: como detectar CPFs que já foram banidos

Aprenda a implementar um sistema de detecção de CPFs banidos para impedir que fraudadores recriem contas em e-commerce e marketplaces.

Redação CPFHub.io
Redação CPFHub.io
··11 min de leitura
Fraude de novo cadastro: como detectar CPFs que já foram banidos

Detectar CPFs banidos em novos cadastros exige duas camadas: uma lista interna de bloqueio com os CPFs marcados como fraudulentos e a validação em tempo real via API para confirmar autenticidade. Sem essas duas camadas combinadas, o banimento é apenas um obstáculo temporário — o fraudador usa outro e-mail e recomeça.

Introdução

Uma das fraudes mais frustrantes para plataformas de e-commerce e marketplaces é a reincidência: um usuário banido por comportamento fraudulento cria uma nova conta e volta a operar como se nada tivesse acontecido. Quando a identificação se baseia apenas em e-mail ou telefone, essa manobra é trivial — basta usar um novo e-mail. Com a validação de CPF, a barreira se torna muito mais eficaz.

Segundo dados do CERT.br, os incidentes de fraude de identidade digital no Brasil crescem ano a ano, tornando a validação de CPF uma camada de proteção cada vez mais essencial para operações online.


A mecânica da reincidência

Por que fraudadores voltam

Fraudadores que obtêm sucesso em um golpe tendem a repetir o mesmo padrão. Se uma plataforma os bane mas não impede o recadastro, o fraudador simplesmente cria uma nova conta com outro e-mail e repete o ciclo. A motivação financeira é forte: cada golpe bem-sucedido gera lucro imediato.

A evolução do fraudador

Fraudadores mais sofisticados adaptam sua estratégia após cada banimento. Na primeira tentativa, usam dados básicos diferentes (e-mail, telefone). Na segunda, podem usar VPN para mascarar o IP. Na terceira, podem alterar ligeiramente o nome. O CPF, no entanto, é o único identificador que não pode ser facilmente alterado — uma pessoa tem um único CPF para toda a vida.

O custo da reincidência

Cada vez que um fraudador retorna e aplica um golpe antes de ser detectado novamente, a plataforma sofre prejuízo direto (produto perdido, chargeback) e indireto (custo de investigação, dano à reputação, perda de confiança dos vendedores). Estudos do setor indicam que fraudadores reincidentes causam 3 a 5 vezes mais prejuízo que novos fraudadores.


Arquitetura do sistema de bloqueio

O sistema de detecção de CPFs banidos opera em três componentes integrados.

Componente 1 — Lista de bloqueio

Uma tabela no banco de dados que armazena CPFs banidos, com o motivo do banimento, a data e o nível de severidade. Essa lista é consultada a cada novo cadastro.

Componente 2 — Validação de CPF via API

A API da CPFHub.io confirma que o CPF é real, ativo e pertence ao nome informado pelo usuário. Isso filtra identidades falsas que passariam despercebidas em uma verificação apenas por lista negra. A resposta chega em ~900ms e inclui nome completo, gênero e data de nascimento.

Componente 3 — Análise de proximidade

Mesmo que o CPF exato não esteja na lista de bloqueio, dados como mesmo sobrenome, mesma data de nascimento e mesmo endereço de entrega podem indicar proximidade com um CPF banido — sugerindo uso de CPF de familiar.


Implementação em Node.js

O exemplo a seguir demonstra o sistema completo de detecção de CPFs banidos.

const express = require("express");
const axios = require("axios");
const crypto = require("crypto");

const app = express();
app.use(express.json());

const CPFHUB_API_URL = "https://api.cpfhub.io/cpf";
const CPFHUB_API_KEY = "SUA_CHAVE_DE_API";
const REQUEST_TIMEOUT = 10000; // 10 segundos

// Simulação de banco de dados
const usuarios = new Map();
const cpfsAtivos = new Set();

// Lista de bloqueio com metadados
const listaBloqueio = new Map();
// cpf -> { motivo, data, severidade, nomeOriginal, dataNascimento, enderecosUsados }

function limparCpf(cpf) {
    return cpf.replace(/\D/g, "");
}

async function consultarCpf(cpf) {
    const cpfLimpo = limparCpf(cpf);

    try {
    const response = await axios.get(`${CPFHUB_API_URL}/${cpfLimpo}`, {
    headers: {
    "x-api-key": CPFHUB_API_KEY,
    Accept: "application/json",
    },
    timeout: REQUEST_TIMEOUT,
    });

    if (response.data.success) {
    return response.data.data;
    }
    return null;
    } catch (error) {
    if (error.code === "ECONNABORTED") {
    throw new Error("Timeout na consulta de CPF");
    }
    if (error.response) {
    const { status } = error.response;
    if (status === 401) throw new Error("API key inválida");
    if (status === 404) return null;
    }
    throw new Error("Erro na consulta de CPF");
    }
}

function normalizarNome(nome) {
    return nome
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toUpperCase()
    .trim();
}

function extrairSobrenome(nome) {
    const partes = normalizarNome(nome).split(" ");
    return partes.length > 1 ? partes[partes.length - 1] : "";
}

// Banir CPF
app.post("/api/admin/banir", (req, res) => {
    const { cpf, motivo, severidade } = req.body;
    // severidade: "LEVE", "GRAVE", "PERMANENTE"

    const cpfLimpo = limparCpf(cpf);

    const usuario = [...usuarios.values()].find((u) => u.cpf === cpfLimpo);

    const registro = {
    cpf: cpfLimpo,
    motivo,
    severidade: severidade || "GRAVE",
    dataBanimento: new Date().toISOString(),
    nomeOriginal: usuario ? usuario.nome : null,
    nomeUpperOriginal: usuario ? usuario.nomeUpper : null,
    dataNascimento: usuario ? usuario.dataNascimento : null,
    sobrenome: usuario ? extrairSobrenome(usuario.nome) : null,
    enderecosUsados: usuario ? usuario.enderecosUsados || [] : [],
    emailsUsados: usuario ? [usuario.email] : [],
    };

    listaBloqueio.set(cpfLimpo, registro);

    // Desativa a conta
    if (usuario) {
    usuario.status = "BANIDO";
    }

    cpfsAtivos.delete(cpfLimpo);

    res.json({
    sucesso: true,
    mensagem: `CPF ${cpfLimpo} adicionado à lista de bloqueio`,
    severidade: registro.severidade,
    });
});

// Verificação completa no cadastro
app.post("/api/usuario/cadastro", async (req, res) => {
    const { nome, email, cpf, endereco } = req.body;

    if (!cpf || !nome || !email) {
    return res.status(400).json({
    erro: "Nome, email e CPF são obrigatórios",
    });
    }

    const cpfLimpo = limparCpf(cpf);
    const alertas = [];
    let bloqueado = false;
    let motivoBloqueio = null;

    // Verificação 1: CPF exato na lista de bloqueio
    if (listaBloqueio.has(cpfLimpo)) {
    const registro = listaBloqueio.get(cpfLimpo);
    bloqueado = true;
    motivoBloqueio = `CPF banido: ${registro.motivo} (${registro.severidade})`;

    // Log para análise (não expor ao usuário)
    console.log(
    `[ALERTA] Tentativa de recadastro de CPF banido: ${cpfLimpo}`
    );

    return res.status(403).json({
    erro: "Não foi possível completar o cadastro. Entre em contato com o suporte.",
    codigo: "CADASTRO_NEGADO",
    });
    }

    // Verificação 2: CPF já ativo
    if (cpfsAtivos.has(cpfLimpo)) {
    return res.status(409).json({
    erro: "Este CPF já possui uma conta ativa",
    });
    }

    // Verificação 3: Validação via API CPFHub.io
    let dadosCpf;
    try {
    dadosCpf = await consultarCpf(cpfLimpo);
    } catch (error) {
    return res.status(503).json({ erro: error.message });
    }

    if (!dadosCpf) {
    return res.status(422).json({
    erro: "CPF não encontrado na base de dados",
    });
    }

    // Verificação 4: Análise de proximidade com CPFs banidos
    const nomeCpf = normalizarNome(dadosCpf.name || "");
    const sobrenomeCpf = extrairSobrenome(dadosCpf.name || "");
    const dataNascCpf = dadosCpf.birthDate;

    for (const [cpfBanido, registro] of listaBloqueio) {
    // Mesmo sobrenome
    if (registro.sobrenome && sobrenomeCpf === registro.sobrenome) {
    alertas.push({
    tipo: "MESMO_SOBRENOME",
    detalhe: `Sobrenome "${sobrenomeCpf}" coincide com CPF banido`,
    cpfRelacionado: cpfBanido.substring(0, 3) + "***",
    severidade: "MEDIA",
    });
    }

    // Mesma data de nascimento e mesmo sobrenome (forte indicativo)
    if (
    registro.dataNascimento &&
    dataNascCpf === registro.dataNascimento &&
    registro.sobrenome === sobrenomeCpf
    ) {
    alertas.push({
    tipo: "FAMILIAR_PROVAVEL",
    detalhe: "Mesma data de nascimento e sobrenome de CPF banido",
    severidade: "ALTA",
    });
    }

    // Mesmo endereço
    if (endereco && registro.enderecosUsados) {
    const enderecoNorm = JSON.stringify(endereco).toUpperCase();
    for (const endBanido of registro.enderecosUsados) {
    if (JSON.stringify(endBanido).toUpperCase() === enderecoNorm) {
    alertas.push({
    tipo: "MESMO_ENDERECO",
    detalhe: "Endereço coincide com CPF banido",
    severidade: "ALTA",
    });
    break;
    }
    }
    }

    // Mesmo e-mail (variações)
    if (registro.emailsUsados) {
    const emailBase = email.split("@")[0].replace(/\./g, "").toLowerCase();
    for (const emailBanido of registro.emailsUsados) {
    const emailBanidoBase = emailBanido
    .split("@")[0]
    .replace(/\./g, "")
    .toLowerCase();
    if (emailBase === emailBanidoBase) {
    alertas.push({
    tipo: "EMAIL_SIMILAR",
    detalhe: "Email similar ao de CPF banido",
    severidade: "ALTA",
    });
    break;
    }
    }
    }
    }

    // Decisão baseada em alertas
    const alertasAltos = alertas.filter((a) => a.severidade === "ALTA");
    const status =
    alertasAltos.length >= 2
    ? "BLOQUEADO"
    : alertasAltos.length === 1
    ? "REVISAO_MANUAL"
    : alertas.length > 0
    ? "APROVADO_COM_RESSALVAS"
    : "APROVADO";

    if (status === "BLOQUEADO") {
    return res.status(403).json({
    erro: "Não foi possível completar o cadastro. Entre em contato com o suporte.",
    codigo: "CADASTRO_NEGADO",
    });
    }

    // Cria conta
    const id = crypto.randomUUID();

    usuarios.set(id, {
    id,
    nome: dadosCpf.name,
    nomeUpper: dadosCpf.nameUpper,
    email,
    cpf: cpfLimpo,
    dataNascimento: dadosCpf.birthDate,
    genero: dadosCpf.gender,
    enderecosUsados: endereco ? [endereco] : [],
    status,
    alertas:
    alertas.length > 0
    ? alertas.map((a) => `${a.tipo}: ${a.detalhe}`)
    : [],
    criadoEm: new Date().toISOString(),
    });

    cpfsAtivos.add(cpfLimpo);

    const resposta = {
    sucesso: true,
    usuarioId: id,
    nome: dadosCpf.name,
    status,
    };

    if (status === "REVISAO_MANUAL") {
    resposta.mensagem =
    "Cadastro em análise. Você será notificado em até 24 horas.";
    } else {
    resposta.mensagem = "Cadastro realizado com sucesso";
    }

    // Log interno de alertas (não expor ao usuário)
    if (alertas.length > 0) {
    console.log(
    `[ALERTA] Novo cadastro ${id} com ${alertas.length} alertas:`,
    alertas.map((a) => a.tipo).join(", ")
    );
    }

    res.json(resposta);
});

// Consultar lista de bloqueio (admin)
app.get("/api/admin/lista-bloqueio", (req, res) => {
    const lista = [];

    for (const [cpf, registro] of listaBloqueio) {
    lista.push({
    cpfMascarado: cpf.substring(0, 3) + ".***.***-" + cpf.substring(9),
    nome: registro.nomeOriginal,
    motivo: registro.motivo,
    severidade: registro.severidade,
    dataBanimento: registro.dataBanimento,
    });
    }

    res.json({
    total: lista.length,
    registros: lista,
    });
});

app.listen(3000, () => {
    console.log("Servidor rodando na porta 3000");
});

Níveis de severidade

O sistema de bloqueio deve operar com diferentes níveis de severidade para permitir tratamento proporcional.

Nível leve

Aplicado a infrações menores, como atraso excessivo em pagamentos ou múltiplos cancelamentos. O CPF é marcado com restrição temporária — após 30 a 90 dias, o recadastro é permitido mediante revisão.

Nível grave

Aplicado a fraudes confirmadas, como chargebacks fraudulentos ou venda de produtos falsificados. O bloqueio é de longo prazo (1 ano ou mais) e qualquer novo cadastro com proximidade ao CPF banido é encaminhado para revisão manual.

Nível permanente

Reservado para fraudes graves ou reincidência. O CPF é permanentemente impedido de operar na plataforma. Tentativas de recadastro são silenciosamente rejeitadas.


Detecção de evasão

Fraudadores sofisticados tentam contornar a lista de bloqueio usando CPFs de terceiros — familiares, amigos ou CPFs obtidos ilegalmente.

Sinais de evasão

Novo CPF com mesmo sobrenome e faixa etária de um CPF banido. Mesmo endereço de entrega de um CPF banido. Mesmo dispositivo (fingerprint) ou IP de um CPF banido. Padrão de compra idêntico ao do CPF banido — mesmos produtos, mesmos horários, mesmo comportamento.

Resposta à evasão

Quando sinais de evasão são detectados, o novo cadastro deve ser encaminhado para revisão manual. A decisão final cabe a um analista humano, pois nem todo caso de mesmo sobrenome ou endereço indica fraude — pode ser um familiar legítimo.


Privacidade e LGPD

A manutenção de listas de bloqueio com CPFs levanta questões de proteção de dados que devem ser tratadas com cuidado.

A base legal para o tratamento é o legítimo interesse (Art. 7, IX da LGPD) combinado com a prevenção à fraude. Os CPFs na lista de bloqueio devem ser armazenados de forma segura, com acesso restrito. O titular pode solicitar informações sobre o tratamento de seus dados, conforme previsto na LGPD. A API da CPFHub.io não armazena os CPFs consultados além do necessário para o processamento da requisição, o que facilita a conformidade com os princípios de minimização de dados da LGPD.


Perguntas frequentes

O que é fraude de novo cadastro com CPF banido?

É quando um usuário banido por comportamento fraudulento tenta criar uma nova conta usando o mesmo CPF (ou CPFs diferentes para o mesmo dispositivo). Detectar o CPF já banido no momento do cadastro impede que o fraudador reincida na plataforma.

Como funciona uma lista interna de CPFs banidos?

É um registro dos CPFs associados a comportamento confirmado como fraudulento — chargeback aprovado, devolução abusiva, multi-accounting comprovado. Em novos cadastros, o sistema consulta essa lista antes de confirmar a criação da conta.

Combinar lista negra com validação de API é necessário?

Sim. A API valida que o CPF é real e o nome corresponde (filtra identidades falsas). A lista negra interna filtra reincidentes. São camadas diferentes: uma verifica autenticidade, a outra verifica histórico. As duas são necessárias para uma defesa completa.

O que fazer quando um CPF banido tenta criar nova conta?

Rejeite silenciosamente o cadastro (sem explicar o motivo, para não fornecer informação ao fraudador) e registre a tentativa no log. Se o volume de tentativas do mesmo CPF for alto, considere acionar o time de segurança para investigação.


Conclusão

A detecção de CPFs banidos é uma peça fundamental na estratégia de prevenção a fraudes de qualquer e-commerce ou marketplace. Sem ela, o banimento é apenas um inconveniente temporário para o fraudador. Com a validação de CPF via CPFHub.io integrada à lista negra interna e à análise de proximidade, a plataforma cria uma barreira real: o fraudador não consegue recadastrar nem usando CPFs de familiares sem acionar alertas para revisão manual.

O sistema descrito aqui — lista de bloqueio por severidade, validação via API em ~900ms e análise de sinais indiretos (mesmo sobrenome, endereço, e-mail) — pode ser implementado em Node.js ou qualquer linguagem backend em poucas horas. O retorno sobre o investimento é imediato: cada reincidência bloqueada evita chargebacks, custos de investigação e perda de reputação.

Crie sua conta gratuita em cpfhub.io e faça até 50 consultas por mês sem cartão de crédito. Para operações em escala, o plano Pro parte de R$149/mês — e cada consulta adicional custa R$0,15, sem bloqueios.

CPFHub.io

Pronto para integrar a API?

50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.

Redação CPFHub.io

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.

WhatsAppFale conosco via WhatsApp