Python SDK
Official SDK for Python 3.8+. It makes the Simple Lookup (GET /cpf/{cpf}) and returns the API's JSON as a dict. A CPF is Brazil's individual taxpayer ID.
Installation
pip install cpfhubWith Poetry:
poetry add cpfhubRequirements: Python 3.8+
Initialization
import os
from cpfhub import CPFHub
client = CPFHub(api_key=os.environ["CPFHUB_API_KEY"])The client sends the key in the x-api-key header and uses a 10-second timeout. It can also be used as a context manager, which closes the connection when the block ends:
with CPFHub(api_key=os.environ["CPFHUB_API_KEY"]) as client:
result = client.lookup("12345678909")Constructor parameters
| Parameter | Type | Description |
|---|---|---|
api_key | str | Your API key (required). If empty, raises ValueError |
Methods
client.lookup(cpf)
Looks up a CPF and returns the API response body as a dict.
result = client.lookup("123.456.789-09")
print(result["data"]["name"]) # "Fulano de Tal"
print(result["data"]["birthDate"]) # "15/06/1990"Parameters:
| Parameter | Type | Description |
|---|---|---|
cpf | str | CPF with or without formatting |
Returns: a dict in the Simple Lookup format:
{
"success": True,
"data": {
"cpf": "12345678909",
"name": "Fulano de Tal",
"nameUpper": "FULANO DE TAL",
"gender": "M",
"birthDate": "15/06/1990",
"day": 15,
"month": 6,
"year": 1990,
},
}The Real-Time Lookup and the batch lookup are made through the REST API: POST https://api.cpfhub.io/cpf/realtime and POST https://api.cpfhub.io/cpf/bulk.
Do not use client.get_quota()
Version 1.0.0 of the package includes a get_quota() method that calls the wrong address and does not work. To see your balance and plan, call GET https://api.cpfhub.io/quota directly (it does not use a credit).
Error handling
- CPF without 11 digits:
lookupraisesValueErrorbefore calling the API (no credit is used). - 4xx and 5xx responses: the SDK raises
httpx.HTTPStatusError. The status is ine.response.status_codeand the API body ine.response.json(). Theerrorfield comes as text ("...") or as an object ({"message": "..."}), depending on the status.
import os
import httpx
from cpfhub import CPFHub
client = CPFHub(api_key=os.environ["CPFHUB_API_KEY"])
try:
result = client.lookup("12345678909")
except httpx.HTTPStatusError as e:
print(e.response.status_code) # 404
print(e.response.json()) # {"success": False, "data": None, "error": {"message": "CPF não encontrado na base de dados"}} (the API replies in Portuguese: "CPF not found in the database")| Status | Reason |
|---|---|
401 | Missing or invalid API key |
403 | Credits exhausted or blocked account |
404 | CPF not found (no credit is used) |
422 | Incorrect check digit (no credit is used) |
429 | Requests-per-minute limit: wait the number of seconds in the Retry-After header |
Full list in Error Codes.
Integration examples
FastAPI
import os
import httpx
from fastapi import FastAPI, HTTPException
from cpfhub import CPFHub
app = FastAPI()
client = CPFHub(api_key=os.environ["CPFHUB_API_KEY"])
@app.get("/cpf/{cpf}")
def lookup_cpf_route(cpf: str):
try:
return client.lookup(cpf)["data"]
except ValueError:
raise HTTPException(status_code=400, detail="CPF must contain 11 digits")
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
raise HTTPException(status_code=404, detail="CPF not found")
if e.response.status_code == 422:
raise HTTPException(status_code=422, detail="Invalid CPF")
# 401, 403, 429 and 5xx: key, credits or rate limit. Log it and do not expose it to the client.
try:
error_detail = e.response.json()
except ValueError:
error_detail = e.response.text
print("CPFHub.io", e.response.status_code, error_detail)
raise HTTPException(status_code=503, detail="CPF lookup unavailable right now")Django view
import os
import httpx
from django.http import JsonResponse
from cpfhub import CPFHub
client = CPFHub(api_key=os.environ["CPFHUB_API_KEY"])
def lookup_cpf_route(request, cpf):
try:
data = client.lookup(cpf)["data"]
return JsonResponse({"name": data["name"], "gender": data["gender"]})
except ValueError:
return JsonResponse({"error": "CPF must contain 11 digits"}, status=400)
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
return JsonResponse({"error": "CPF not found"}, status=404)
if e.response.status_code == 422:
return JsonResponse({"error": "Invalid CPF"}, status=422)
# 401, 403, 429 and 5xx: key, credits or rate limit. Do not expose it to the client.
return JsonResponse({"error": "CPF lookup unavailable right now"}, status=503)Form validation
import os
import httpx
from cpfhub import CPFHub
client = CPFHub(api_key=os.environ["CPFHUB_API_KEY"])
def validate_cpf_onboarding(cpf: str) -> dict:
try:
data = client.lookup(cpf)["data"]
return {"valid": True, "name": data["name"]}
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
return {"valid": False, "name": None}
raiseRepository and support
- github.com/cpfhub/cpfhub-python: source code, issues and contributions
- PyPI: cpfhub: versions
Updated on October 3, 2026