Falcon Data Hub
← Blog

Validar CPF em PHP: algoritmo, biblioteca e API com fallback

Três formas de validar CPF em PHP: do algoritmo cru do DV à biblioteca pronta, terminando com API para checagem anti-fraude. Código pronto pra copiar.

Validar CPF em PHP parece trivial até você descobrir que 70% dos snippets espalhados pela internet têm bug — não rejeitam sequências como 111.111.111-11 ou falham em CPFs com zeros à esquerda. Este guia mostra três formas correta, do simples ao paranoico.

O algoritmo do dígito verificador

CPF tem 11 dígitos. Os dois últimos são os DVs calculados a partir dos nove primeiros. A regra é fixa há décadas:

  1. Multiplica os nove primeiros dígitos por 10, 9, 8, 7, 6, 5, 4, 3, 2 respectivamente.
  2. Soma os resultados.
  3. Multiplica a soma por 10 e divide por 11. O resto é o primeiro DV (se for 10, vira 0).
  4. Repete o processo incluindo o primeiro DV, multiplicando por 11, 10, 9... 2.

Implementação 1: função pura sem dependência

<?php

function validarCpf(string $cpf): bool
{
    // Tira pontuação
    $cpf = preg_replace('/\D/', '', $cpf);

    // Tem que ter 11 dígitos
    if (strlen($cpf) !== 11) {
        return false;
    }

    // Rejeita sequências repetidas (111.111.111-11, 222.222.222-22...)
    if (preg_match('/^(\d)\1{10}$/', $cpf)) {
        return false;
    }

    // Calcula primeiro DV
    $soma = 0;
    for ($i = 0; $i < 9; $i++) {
        $soma += (int) $cpf[$i] * (10 - $i);
    }
    $dv1 = ($soma * 10) % 11;
    if ($dv1 === 10) {
        $dv1 = 0;
    }
    if ($dv1 !== (int) $cpf[9]) {
        return false;
    }

    // Calcula segundo DV
    $soma = 0;
    for ($i = 0; $i < 10; $i++) {
        $soma += (int) $cpf[$i] * (11 - $i);
    }
    $dv2 = ($soma * 10) % 11;
    if ($dv2 === 10) {
        $dv2 = 0;
    }
    return $dv2 === (int) $cpf[10];
}

// Uso
var_dump(validarCpf('123.456.789-09'));   // true ou false
var_dump(validarCpf('111.111.111-11'));   // false (sequência)
var_dump(validarCpf('11144477735'));      // true (CPF didático válido)

Essa função cobre 99% dos casos. Aceita CPF com pontos, hífens ou só números. Rejeita sequências repetidas (que tecnicamente passam no DV mas claramente são falsas).

Implementação 2: biblioteca pronta (Laravel)

Se você está no Laravel, a forma idiomática é usar uma rule de validação. A community lib mais popular é laravel-validation-rules/cpf-cnpj:

composer require laravel-validation-rules/cpf-cnpj
use LaravelValidationRules\Rules\Cpf;

$request->validate([
    'cpf' => ['required', new Cpf()],
]);

Vantagem: integra direto com FormRequest, mensagens de erro traduzidas, sem você precisar manter o algoritmo. Use para forms internos.

Implementação 3: API anti-fraude

Validação local resolve a parte matemática mas não detecta CPFs falsos com DV correto. Para checkouts críticos vale uma checagem complementar via API que cruza com bases reais:

use Falcon\DataHub\Client;

$client = new Client('SEU_TOKEN');
$result = $client->cpf('12345678909');

if (!$result->valid) {
    return 'CPF inválido';
}

if ($result->suspicious) {
    return 'CPF suspeito (sequência ou padrão atípico)';
}

// Premium: cruzamento com QSA de CNPJ, XML de NFe etc.
if ($result->found_in && count($result->found_in) > 0) {
    echo "CPF aparece em: ";
    foreach ($result->found_in as $context) {
        echo "{$context->type} ";
    }
}

Aqui o ganho não é validação do DV — isso já fez localmente em microsegundos. O ganho é o cruzamento. Saber que o CPF aparece como sócio em algum CNPJ ou como destinatário em NFes legítimas é forte sinal anti-fraude.

Qual abordagem escolher

CenárioAbordagem
Form interno de cadastroFunção pura ou rule do Laravel
Validação em tempo real no frontAlgoritmo no client (JS) + função no backend
Checkout de e-commerceRule do Laravel + API anti-fraude para risco alto
Verificação de sócio em B2BAPI com enriquecimento (qsa, xml)

A maioria dos sistemas começa com 1 ou 2 e adiciona 3 quando começa a tomar fraude. Não precisa over-engineering desde o dia zero.

Cuidado comum: zero à esquerda

PHP tem uma armadilha clássica: se você fizer (int) '01234567890', vira 1234567890 e perde um dígito. Por isso o código acima trata o CPF como string até o último momento, e só converte cada dígito individualmente para int dentro do loop. Cuidado com intval($cpf) antes da validação — vai te morder.

Conclusão

Para 90% dos usos, a função pura resolve. Lib do Laravel é açúcar para FormRequest. API anti-fraude entra quando o custo de aceitar um CPF falso é maior que o custo da chamada externa. Comece simples e suba o nível conforme o problema aparecer.

Gostou do artigo?

Comece a usar a API do Falcon Data Hub agora. Plano grátis, sem cartão.

Criar conta grátis
Como validar CPF em PHP — 3 formas com código | Falcon Data Hub