# Como Lidar com Erros HTTP ao Consumir APIs de CPF

> Aprenda a tratar erros HTTP ao consumir APIs de CPF. Guia completo com status codes, retry, circuit breaker e exemplos em Python e JavaScript.

**Publicado:** 08/01/2025
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/lidar-erros-http-consumir-apis-cpf

---


Ao consumir a API de CPF do CPFHub.io em produção, erros HTTP são inevitáveis — e a diferença entre um sistema confiável e um frágil está em como cada categoria de erro é tratada: 4xx para problemas na requisição, 5xx para falhas do servidor, e retry com backoff exponencial para erros transitórios. A API do CPFHub.io **nunca retorna HTTP 429 nem bloqueia requisições**: ao ultrapassar o limite do plano, ela simplesmente cobra R$0,15 por consulta adicional.

## Introdução

Ao consumir a API de CPF do CPFHub.io em produção, erros HTTP são inevitáveis. Falhas de rede, timeouts e erros de servidor acontecem, e a diferença entre um sistema confiável e um frágil está em como você trata essas situações.

## Classificação dos erros HTTP

Os códigos de status HTTP seguem um padrão que indica a natureza do erro e a ação correta a tomar.

| Faixa | Categoria | Ação recomendada | Exemplo |
|-------|-----------|-----------------|---------|
| 2xx | Sucesso | Processar normalmente | 200 OK |
| 400 | Requisição inválida | Corrigir o input | CPF malformado |
| 401 | Não autorizado | Verificar API key | Key ausente ou inválida |
| 403 | Proibido | Verificar permissões | Plano sem acesso |
| 404 | Não encontrado | CPF não existe na base | CPF válido mas sem dados |
| 500 | Erro do servidor | Retry com backoff | Falha interna da API |
| 502/503 | Indisponível | Retry com backoff | API temporariamente fora |

- **4xx** — erros do cliente, geralmente não devem ser retentados pois a causa está na requisição
- **5xx** — erros do servidor, candidatos a retry pois são tipicamente transitórios
- **429** — a API do CPFHub.io **não emite este código**: ao ultrapassar o limite do plano gratuito, a API continua respondendo normalmente e cobra R$0,15 por consulta adicional, sem bloquear

---

## Implementando tratamento de erros em Python

Crie uma classe que trata cada categoria de erro de forma específica e oferece mensagens úteis.

```python
import requests
import time
import logging

logger = logging.getLogger(__name__)

class CPFApiError(Exception):
 def __init__(self, message: str, status_code: int = None, retryable: bool = False):
 super().__init__(message)
 self.status_code = status_code
 self.retryable = retryable

class CPFClient:
 def __init__(self, api_key: str):
 self.session = requests.Session()
 self.session.headers["x-api-key"] = api_key
 self.base_url = "https://api.cpfhub.io/cpf"

 def consultar(self, cpf: str) -> dict:
 cpf_limpo = "".join(c for c in cpf if c.isdigit())

 try:
 response = self.session.get(
 f"{self.base_url}/{cpf_limpo}",
 timeout=15
 )
 except requests.exceptions.Timeout:
 raise CPFApiError("Timeout na requisição", retryable=True)
 except requests.exceptions.ConnectionError:
 raise CPFApiError("Erro de conexão com a API", retryable=True)

 return self._tratar_resposta(response)

 def _tratar_resposta(self, response: requests.Response) -> dict:
 handlers = {
 200: self._handle_success,
 400: self._handle_bad_request,
 401: self._handle_unauthorized,
 403: self._handle_forbidden,
 404: self._handle_not_found,
 }

 handler = handlers.get(response.status_code, self._handle_server_error)
 return handler(response)

 def _handle_success(self, response):
 data = response.json()
 if not data.get("success"):
 raise CPFApiError("CPF não encontrado na base de dados")
 return data

 def _handle_bad_request(self, response):
 raise CPFApiError("CPF inválido ou malformado", status_code=400)

 def _handle_unauthorized(self, response):
 raise CPFApiError("API key inválida ou ausente", status_code=401)

 def _handle_forbidden(self, response):
 raise CPFApiError("Sem permissão para este recurso", status_code=403)

 def _handle_not_found(self, response):
 raise CPFApiError("CPF não encontrado", status_code=404)

 def _handle_server_error(self, response):
 logger.error(f"Erro do servidor: {response.status_code}")
 raise CPFApiError(
 f"Erro interno da API ({response.status_code})",
 status_code=response.status_code,
 retryable=True
 )
```

- **retryable** — flag que indica se o erro é candidato a retry automático
- **Handler map** — mapeia cada status code para um método específico de tratamento
- **Timeout explícito** — sempre defina timeout para evitar requisições penduradas

---

## Implementando tratamento de erros em JavaScript

A mesma abordagem estruturada aplicada em JavaScript com fetch e classes de erro.

```javascript
class CPFApiError extends Error {
 constructor(message, statusCode = null, retryable = false) {
 super(message);
 this.name = "CPFApiError";
 this.statusCode = statusCode;
 this.retryable = retryable;
 }
}

class CPFClient {
 constructor(apiKey) {
 this.apiKey = apiKey;
 this.baseUrl = "https://api.cpfhub.io/cpf";
 }

 async consultar(cpf) {
 const cpfLimpo = cpf.replace(/\D/g, "");
 const controller = new AbortController();
 const timeoutId = setTimeout(() => controller.abort(), 15000);

 try {
 const response = await fetch(`${this.baseUrl}/${cpfLimpo}`, {
 headers: { "x-api-key": this.apiKey },
 signal: controller.signal,
 });

 clearTimeout(timeoutId);
 return this.#tratarResposta(response);
 } catch (error) {
 clearTimeout(timeoutId);
 if (error.name === "AbortError") {
 throw new CPFApiError("Timeout na requisição", null, true);
 }
 if (error instanceof CPFApiError) throw error;
 throw new CPFApiError(`Erro de conexão: ${error.message}`, null, true);
 }
 }

 async #tratarResposta(response) {
 const handlers = {
 400: () => new CPFApiError("CPF inválido ou malformado", 400),
 401: () => new CPFApiError("API key inválida ou ausente", 401),
 403: () => new CPFApiError("Sem permissão para este recurso", 403),
 404: () => new CPFApiError("CPF não encontrado", 404),
 };

 if (response.ok) {
 const data = await response.json();
 if (!data.success) {
 throw new CPFApiError("CPF não encontrado na base");
 }
 return data;
 }

 const handler = handlers[response.status];
 if (handler) throw handler();

 throw new CPFApiError(
 `Erro do servidor (${response.status})`,
 response.status,
 response.status >= 500
 );
 }
}
```

- **AbortController** — mecanismo nativo do browser e Node.js para cancelar requisições com timeout
- **Private method (#)** — método privado usando a sintaxe nativa do JavaScript
- **Sem 429** — a API do CPFHub.io não bloqueia por volume; consultas além do plano são cobradas automaticamente a R$0,15 cada

---

## Construindo um wrapper com retry automático

Combine o tratamento de erros com retry inteligente que só retenta erros marcados como retryable.

```python
import time
import random

def consultar_com_retry(
 client: CPFClient,
 cpf: str,
 max_tentativas: int = 3,
 delay_base: float = 1.0
) -> dict:
 for tentativa in range(max_tentativas):
 try:
 return client.consultar(cpf)
 except CPFApiError as e:
 if not e.retryable or tentativa == max_tentativas - 1:
 raise

 delay = delay_base * (2 ** tentativa)
 jitter = random.uniform(0, delay * 0.1)
 tempo_espera = delay + jitter

 logger.warning(
 f"Tentativa {tentativa + 1}/{max_tentativas} falhou: {e}. "
 f"Retentando em {tempo_espera:.1f}s"
 )
 time.sleep(tempo_espera)

 raise CPFApiError("Todas as tentativas falharam")
```

```javascript
async function consultarComRetry(client, cpf, maxTentativas = 3) {
 for (let tentativa = 0; tentativa < maxTentativas; tentativa++) {
 try {
 return await client.consultar(cpf);
 } catch (error) {
 if (!error.retryable || tentativa === maxTentativas - 1) {
 throw error;
 }

 const delay = Math.pow(2, tentativa) * 1000;
 const jitter = Math.random() * delay * 0.1;
 console.warn(
 `Tentativa ${tentativa + 1}/${maxTentativas} falhou. ` +
 `Retentando em ${((delay + jitter) / 1000).toFixed(1)}s`
 );
 await new Promise((r) => setTimeout(r, delay + jitter));
 }
 }
}
```

| Tentativa | Delay base | Com jitter (exemplo) |
|-----------|-----------|---------------------|
| 1 | 1s | 1.0 - 1.1s |
| 2 | 2s | 2.0 - 2.2s |
| 3 | 4s | 4.0 - 4.4s |

- **Exponential backoff** — dobrar o delay a cada tentativa reduz a pressão sobre a API
- **Jitter** — variação aleatória evita que múltiplos clientes retentem simultaneamente
- **Erros não retentáveis** — 400 e 401 são lançados imediatamente, sem desperdício de tentativas

---

## Perguntas frequentes

### A API do CPFHub.io retorna HTTP 429 quando o limite de consultas é atingido?
Não. A API do CPFHub.io **nunca retorna HTTP 429 nem bloqueia requisições** por excesso de volume. Ao ultrapassar o limite do plano gratuito (50 consultas/mês), a API continua respondendo normalmente e cobra R$0,15 por consulta adicional. Não é necessário implementar lógica de espera por rate limit — apenas monitore seu consumo em [app.cpfhub.io/settings/billing](https://app.cpfhub.io/settings/billing).

### Quais erros HTTP devo tratar com retry automático?
Erros de servidor (5xx) e falhas de rede (timeout, connection error) são os candidatos naturais ao retry, pois são transitórios. Erros de cliente (400, 401, 403, 404) não devem ser retentados — a causa está na requisição e repetir a chamada sem corrigir o problema gera desperdício. Use o padrão de backoff exponencial com jitter para evitar sobrecarga em situações de falha.

### Como definir um timeout adequado para a API de CPF?
A latência típica da API do CPFHub.io é de aproximadamente 900ms. Recomenda-se configurar o timeout entre 10 e 15 segundos para absorver variações de rede sem bloquear o usuário por tempo excessivo. Use `AbortController` no JavaScript e o parâmetro `timeout` do `requests` no Python. Timeouts devem ser tratados como erros retentáveis.

### O que fazer quando todos os retries falham?
Após esgotar as tentativas de retry, lance o erro para o chamador e registre o evento nos logs com o CPF (mascarado), timestamp, status code e número de tentativas. Se a consulta é crítica para um fluxo (como onboarding), enfileire para processamento posterior em vez de bloquear o usuário. Implemente alertas automáticos quando a taxa de falha ultrapassar um limiar — veja mais em [developer.mozilla.org/pt-BR/docs/Web/HTTP/Status](https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Status) para referência completa de status codes HTTP.

### Leia também

- [API de CPF: guia prático para debugging de erros de integração](https://cpfhub.io/blog/api-cpf-guia-pratico-debugging-erros-integracao)
- [API de CPF: como tratar respostas de erro (4xx e 5xx) de forma robusta](https://cpfhub.io/blog/api-de-cpf-como-tratar-respostas-de-erro-4xx-e-5xx-de-forma-robusta)
- [Como implementar retry automático em consultas de CPF que falham](https://cpfhub.io/blog/como-implementar-retry-automatico-em-consultas-de-cpf-que-falham)
- [Como implementar circuit breaker em integrações com API de CPF](https://cpfhub.io/blog/como-implementar-circuit-breaker-em-integracoes-com-api-de-cpf)

---

## Conclusão

Tratar erros HTTP corretamente é a diferença entre um sistema que degrada graciosamente e um que falha catastroficamente. Classifique cada erro por natureza, implemente handlers específicos por status code e adicione retry com backoff para erros transitórios. Vale lembrar: a API do CPFHub.io nunca retorna HTTP 429 — consultas além do plano são cobradas automaticamente, sem bloqueio.

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/) — 50 consultas mensais gratuitas, sem cartão de crédito — e comece a construir integrações robustas com tratamento de erros adequado hoje mesmo.

