Introduction
A CPF check digit validator tells you whether a Brazilian CPF number is well formed. A registry lookup tells you whether that number exists and whose it is. The first is free, runs offline and catches typos. The second needs an API call and is the only one of the two that stops fake or borrowed identities.
Most teams need both, in that order. This guide explains the algorithm step by step, shows where it stops being useful and what a lookup adds.
How the CPF check digit algorithm works
A CPF has 11 digits, usually written as 000.000.000-00. The first nine are the base number, assigned by the Receita Federal (Brazil's Federal Revenue Service). The last two are check digits calculated from the base with a modulo 11 rule.
First check digit
- Multiply the nine base digits by the weights 10, 9, 8, 7, 6, 5, 4, 3 and 2.
- Add the results.
- Multiply the sum by 10 and take the remainder of the division by 11.
- If the remainder is 10, the digit is 0. Otherwise the digit is the remainder.
Second check digit
Repeat the process over the nine base digits plus the first check digit, with weights from 11 down to 2.
A worked example
Take the base 123456789, a sequence used here only to show the arithmetic:
| Step | First digit | Second digit |
|---|---|---|
| Digits used | 1 2 3 4 5 6 7 8 9 | 1 2 3 4 5 6 7 8 9 0 |
| Weights | 10 to 2 | 11 to 2 |
| Sum of products | 210 | 255 |
| (sum x 10) mod 11 | 2100 mod 11 = 10 | 2550 mod 11 = 9 |
| Check digit | 0 | 9 |
The same rule in Python
def is_valid_cpf_format(value: str) -> bool:
cpf = "".join(ch for ch in value if ch.isdigit())
if len(cpf) != 11 or cpf == cpf[0] * 11:
return False
def check_digit(base: str) -> int:
weight = len(base) + 1
total = sum(int(d) * (weight - i) for i, d in enumerate(base))
rest = (total * 10) % 11
return 0 if rest == 10 else rest
return (
check_digit(cpf[:9]) == int(cpf[9])
and check_digit(cpf[:10]) == int(cpf[10])
)
The repeated-digit rule matters: sequences like 11111111111 pass the arithmetic but are not valid CPFs, so every validator rejects them explicitly. The ninth digit also carries meaning, as it indicates the fiscal region where the CPF was first registered. That says nothing about where the person lives today.
What a check digit validator cannot prove
The algorithm is public, and so are dozens of CPF generators that produce valid-looking numbers on demand. A number that passes the check could be:
- Generated. Valid arithmetic, never issued to anyone.
- Real but someone else's. CPFs appear on invoices, receipts and pay slips, so real numbers are easy to collect.
- Real and the user's, but irregular. Suspended, cancelled or tied to a holder who has died.
None of these cases can be detected offline. The check digit only rules out typing errors, which is useful for user experience and nothing more.
What a registry lookup adds
A registry lookup asks a database of issued CPFs. With the CPFHub.io Simple Lookup, a GET request returns the holder's name, gender and date of birth:
curl --max-time 10 \
-H "x-api-key: YOUR_API_KEY" \
-H "Accept: application/json" \
https://api.cpfhub.io/cpf/00000000000
The API runs the same check digit test first, so you get a clear answer for every case:
| Situation | Check digit only | Simple Lookup |
|---|---|---|
| Typo in the number | Invalid | 422, no credit used |
| Fewer than 11 digits | Invalid | 400, no credit used |
| Generated number | Looks valid | 404, no credit used |
| Real CPF, wrong person | Looks valid | 200 with a name and date of birth that do not match the form |
| Real CPF, right person | Looks valid | 200 with matching data |
The comparison step is what catches identity misuse. Compare the returned name and date of birth with what the user typed, after removing accents and normalizing case. A wrong date of birth on an existing CPF is a strong fraud signal.
And the registration status?
The Simple Lookup does not return registration status. To know whether a CPF is regular, suspended or cancelled at the Receita Federal, or whether the holder has died, use the Real-Time Lookup. It needs the CPF and the date of birth and returns the status, the year of death when there is one and the proof issued by the Receita Federal. For a single manual check, the Receita Federal also offers a public status page.
How to combine them
The usual pattern is three steps:
- In the form: run the check digit validator as the user types. Show an error before submission. No network call, no cost.
- On the server: call the Simple Lookup from your backend, with the key in the
CPFHUB_API_KEYenvironment variable, and compare the result with the form. Never call the API from browser code. - When the risk justifies it: add the Real-Time Lookup for status, and document and selfie checks through Identity Verification for regulated onboarding.
Because invalid numbers are rejected before step 2 and a CPF that is not found does not use a credit, the validator also keeps your lookup volume clean. The CPF validation API page has more on this flow.
Under the LGPD (Brazil's data protection law, Law 13,709/2018), look up only CPFs your users give you, for a purpose you have told them about.
Frequently asked questions
Is a CPF validator enough for signup?
It is enough to catch typos, not to verify identity. Generated numbers pass it, so any flow that needs to know the person is real should add a registry lookup on the server.
Why does the API return 422 for some numbers?
A 422 means the check digits are wrong, which includes repeated sequences like 11111111111. No credit is used, so you can rely on the API as a second layer even if your form validator has a bug.
Can I find the holder's state from the CPF number?
Only the fiscal region where the CPF was first registered, from the ninth digit. People move, and that digit does not change, so do not use it as an address check.
Does the check digit algorithm change with the new identity card?
No. Brazil's new national identity card uses the CPF as its number, and the CPF keeps the same 11 digits and the same check digit rule. See the CPF overview for how the documents relate.
Read also
- How to Verify a Brazilian CPF Number
- How to Use a CPF Lookup API in Python
- How to Use a CPF Lookup API in Node.js
- CPF vs CNPJ: Brazil's Individual and Company Tax IDs Explained
Conclusion
The CPF check digit algorithm is a format test: two modulo 11 calculations that catch typing errors without a network call. It cannot tell a generated number from a real one, or a real one from someone else's. A registry lookup answers those questions, and the Real-Time Lookup adds the status at the Receita Federal when you need it.
Try both layers with 50 free credits and no credit card at cpfhub.io.
CPFHub.io
Ready to integrate the API?
50 free credits to test now. No credit card. Instant access to the documentation.




