1. Introduction
The CPF (Cadastro de Pessoas Físicas) is the primary identification number for Brazilian taxpayers. Managed by the Receita Federal (Federal Revenue Service), it is required for everything from opening a bank account to filing taxes. Understanding how it is structured and how to validate it is a fundamental skill for developers working in the Brazilian market.
2. The Anatomy of a CPF
A CPF consists of 11 decimal digits. The first 8 digits are base numbers, the 9th digit represents the region of issuance, and the last two digits (10th and 11th) are the Verification Digits (Dígitos Verificadores - DV). These DVs are calculated using the Module 11 algorithm.
3. The Module 11 Algorithm
The Module 11 algorithm is a checksum method used to verify the integrity of a number. It works by assigning weights to each digit and calculating a remainder.
Step-by-step example for CPF 123.456.789-09:
Sum (1*10 + 2*9 + ... + 9*2) = 210
210 % 11 = 1 (Remainder)
11 - 1 = 10 -> Result is 0
4. The Role of CPF in Brazil
The CPF is more than just a tax ID; it is a central key in the Brazilian digital ecosystem. It is linked to the "Gov.br" identity system, which provides access to hundreds of public services. Because it is a permanent and unique number, it is also widely used as a primary key in private sector databases.
5. LGPD and Data Privacy
The Brazilian General Data Protection Law (LGPD) classifies the CPF as personal data. Storing or processing real CPFs without a clear legal basis and proper security measures can lead to heavy fines.
Never use real CPFs in testing.
Use Generated Data.
Masking in UIs.
6. Implementation Guide
function validateCPF(cpf) {
cpf = cpf.replace(/[^\d]/g, '');
if (cpf.length !== 11 || /^(\d)\1+$/.test(cpf)) return false;
let add = 0;
for (let i=0; i < 9; i++) add += parseInt(cpf.charAt(i)) * (10 - i);
let rev = 11 - (add % 11);
if (rev === 10 || rev === 11) rev = 0;
if (rev !== parseInt(cpf.charAt(9))) return false;
add = 0;
for (let i=0; i < 10; i++) add += parseInt(cpf.charAt(i)) * (11 - i);
rev = 11 - (add % 11);
if (rev === 10 || rev === 11) rev = 0;
return rev === parseInt(cpf.charAt(10));
}
import re
def validate_cpf(cpf):
cpf = re.sub(r'\D', '', cpf)
if len(cpf) != 11 or cpf == cpf[0] * 11:
return False
for i in range(9, 11):
value = sum((int(cpf[num]) * ((i + 1) - num) for num in range(0, i)))
digit = ((value * 10) % 11) % 10
if digit != int(cpf[i]):
return False
return True
public class CPFValidator {
public static boolean isValid(String cpf) {
cpf = cpf.replaceAll("\\D", "");
if (cpf.length() != 11 || cpf.matches("(\\d)\\1{10}")) return false;
try {
int add = 0;
for (int i = 0; i < 9; i++) add += (cpf.charAt(i) - '0') * (10 - i);
int rev = 11 - (add % 11);
if (rev == 10 || rev == 11) rev = 0;
if (rev != (cpf.charAt(9) - '0')) return false;
add = 0;
for (int i = 0; i < 10; i++) add += (cpf.charAt(i) - '0') * (11 - i);
int rev2 = 11 - (add % 11);
if (rev2 == 10 || rev2 == 11) rev2 = 0;
return rev2 == (cpf.charAt(10) - '0');
} catch (Exception e) { return false; }
}
}