NewFacial identity verification

CPF Check Digits vs a Real Registry Lookup

How the Brazilian CPF check digit algorithm works, what a CPF validator can and cannot prove, and when you need a registry lookup to stop fake identities.

Lucas Vieira
Lucas Vieira
··7 min read
CPF Check Digits vs a Real Registry Lookup

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

  1. Multiply the nine base digits by the weights 10, 9, 8, 7, 6, 5, 4, 3 and 2.
  2. Add the results.
  3. Multiply the sum by 10 and take the remainder of the division by 11.
  4. 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:

StepFirst digitSecond digit
Digits used1 2 3 4 5 6 7 8 91 2 3 4 5 6 7 8 9 0
Weights10 to 211 to 2
Sum of products210255
(sum x 10) mod 112100 mod 11 = 102550 mod 11 = 9
Check digit09

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:

SituationCheck digit onlySimple Lookup
Typo in the numberInvalid422, no credit used
Fewer than 11 digitsInvalid400, no credit used
Generated numberLooks valid404, no credit used
Real CPF, wrong personLooks valid200 with a name and date of birth that do not match the form
Real CPF, right personLooks valid200 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:

  1. In the form: run the check digit validator as the user types. Show an error before submission. No network call, no cost.
  2. On the server: call the Simple Lookup from your backend, with the key in the CPFHUB_API_KEY environment variable, and compare the result with the form. Never call the API from browser code.
  3. 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

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.

WhatsApp