# How to Verify a Brazilian CPF Number

> Three levels of Brazilian CPF verification, from the check digit algorithm to a registry lookup and the Receita Federal status, with code you can run today.

**Published:** November 13, 2026
**Author:** Lucas Vieira
**URL:** https://www.cpfhub.io/en/blog/how-to-verify-a-brazilian-cpf

---


## Introduction

Verifying a Brazilian [CPF](/en/blog/what-is-a-brazilian-cpf) (Brazil's individual taxpayer ID) can mean three different things, and mixing them up is the most common mistake foreign teams make. A number can have valid check digits and still not exist. It can exist and belong to someone else. It can belong to the right person and still have an irregular status at the [Receita Federal](https://www.gov.br/receitafederal/pt-br/assuntos/orientacao-tributaria/cadastros/cpf) (Brazil's federal tax authority).

This guide walks through the three levels of verification, what each one proves and how to implement them.

---

## Level 1: format and check digits

A CPF has 11 digits. The last two are check digits calculated from the first nine with a modulo 11 algorithm. Validating them catches typos instantly, with no network call:

```javascript
function isValidCpfFormat(input) {
  const cpf = String(input).replace(/\D/g, '')
  if (cpf.length !== 11 || /^(\d)\1{10}$/.test(cpf)) return false

  const digit = (base) => {
    let sum = 0
    for (let i = 0; i < base.length; i++) sum += Number(base[i]) * (base.length + 1 - i)
    const rest = (sum * 10) % 11
    return rest === 10 ? 0 : rest
  }

  const d1 = digit(cpf.slice(0, 9))
  const d2 = digit(cpf.slice(0, 10))
  return d1 === Number(cpf[9]) && d2 === Number(cpf[10])
}
```

**What it proves:** the number is well formed. **What it does not prove:** that the CPF exists or belongs to your user. CPF generators that produce valid-looking numbers are one search away, so this check belongs in the form for user experience, never as your only control.

---

## Level 2: registry lookup (does the CPF exist, and whose is it?)

The second level asks: does this CPF exist, and do the name and date of birth match what the user typed? This is the check that stops fake and borrowed identities at signup.

With [**CPFHub.io**](/en), the Simple Lookup is a `GET` request that returns the holder's name, gender and date of birth. Call it from your backend, with the API key stored in an environment variable:

```python
import os
import requests

def lookup_cpf(cpf: str) -> dict | None:
    response = requests.get(
        f"https://api.cpfhub.io/cpf/{cpf}",
        headers={
            "x-api-key": os.environ["CPFHUB_API_KEY"],
            "Accept": "application/json",
        },
        timeout=10,
    )
    if response.status_code == 404:
        return None  # CPF not found: no credit is used
    response.raise_for_status()
    return response.json()["data"]

data = lookup_cpf("00000000000")
if data:
    print(data["name"], data["birthDate"])
```

Then compare the result with the form:

- **Name:** normalize both sides (uppercase, no accents) and compare. Use the `nameUpper` field, and allow for abbreviated middle names.
- **Date of birth:** compare exactly. A mismatch on a real CPF is one of the strongest fraud signals you will get.

A CPF that is not found returns 404 and does not use a credit. An invalid check digit returns 422, so you can still rely on Level 1 errors coming back from the API.

> Never call the API from browser JavaScript. The API key must stay on your server: the frontend calls your own route (for example `/api/verify-cpf`), and that route calls CPFHub.io.

---

## Level 3: registration status at the Receita Federal

Some flows need more than existence: credit, high-value payouts and regulated onboarding often require the **registration status** of the CPF at the Receita Federal (regular, pending regularization, suspended, cancelled, or holder deceased).

The CPFHub.io [**Real-Time Lookup**](/en/cpf-lookup-federal-revenue) queries the Receita Federal at the moment of the call. It requires the CPF and the holder's date of birth, and returns the name, the registration status (`situation`), the year of death when there is one, and a link to the proof issued by the Receita Federal:

```bash
curl --max-time 60 -X POST https://api.cpfhub.io/cpf/realtime \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"cpf": "00000000000", "birthDate": "15/06/1990"}'
```

Because it depends on the Receita Federal, use a generous timeout and retry on 503 after the `Retry-After` header. Fields and errors are in the [Real-Time Lookup reference](/en/documentation/reference/cpf-realtime). For a single manual check, the Receita Federal also has a [public status page](https://servicos.receita.fazenda.gov.br/servicos/cpf/consultasituacao/consultapublica.asp) with a captcha.

---

## Which level do you need?

| Flow | Level 1 | Level 2 | Level 3 |
|---|---|---|---|
| Signup form | Yes | Yes | Optional |
| Marketplace buyer checkout | Yes | Yes | No |
| Courier or driver onboarding | Yes | Yes | Recommended |
| Fintech or crypto account opening | Yes | Yes | Recommended, plus document and selfie checks |
| Credit and high-value payouts | Yes | Yes | Yes |

For regulated onboarding, combine the CPF lookup with document and selfie verification. CPFHub.io's [Identity Verification](/en/identity-verification) does liveness, face match and document reading through the same API key.

---

## Frequently asked questions

### Is the check digit algorithm enough to validate a CPF?

No. It only catches typos. Generated numbers pass it, so you still need a registry lookup to confirm that the CPF exists and belongs to your user.

### What does the API return when the CPF does not exist?

The Simple Lookup returns HTTP 404, and the lookup does not use a credit. An invalid check digit returns 422.

### Do I need the date of birth to verify a CPF?

Not for the Simple Lookup, which only needs the CPF and returns the date of birth for you to compare. The Real-Time Lookup at the Receita Federal requires both the CPF and the date of birth.

### Can I verify thousands of CPFs at once?

Yes. The batch endpoint accepts up to 10,000 CPFs per request, and only CPFs found use credits. See [bulk CPF lookup](/en/bulk-cpf-lookup).

---

### Read also

- [What Is a Brazilian CPF? A Guide for Foreign Companies](/en/blog/what-is-a-brazilian-cpf)
- [Brazil KYC Requirements in 2026: What Foreign Companies Need to Know](/en/blog/brazil-kyc-requirements)
- [Brazil Identity Verification API: What Data You Can Get from a CPF](/en/blog/brazil-identity-verification-api)

## Conclusion

Verifying a CPF properly is a ladder: check digits in the form, a registry lookup on the backend to confirm the person exists and matches, and the Receita Federal status when the risk justifies it. Each level answers a different question, and most fraud slips through when teams stop at the first one.

Start with 50 free credits and no credit card at [cpfhub.io](/en), and see every endpoint in the [documentation](/en/documentation/getting-started).

