# Como integrar validação de CPF em Cloudflare Workers com fetch API

> Aprenda a criar um Cloudflare Worker que válida CPF usando a API CPFHub.io com fetch nativo, KV para cache e deploy global em edge.

**Publicado:** 23/09/2026
**Autor:** Redação CPFHub.io
**URL:** https://www.cpfhub.io/blog/como-integrar-validacao-cpf-cloudflare-workers-fetch-api

---


Para integrar validação de CPF em Cloudflare Workers, crie um Worker em TypeScript que recebe o CPF via rota `/cpf/{numero}`, verifica o cache no KV e, se necessário, consulta a API da CPFHub.io com `fetch` nativo e o header `x-api-key`. Os Workers rodam na edge da rede Cloudflare — em mais de 300 datacenters — com cold starts abaixo de 5ms, tornando-os ideais para validações que precisam de resposta rápida próxima ao usuário. A [documentação do Cloudflare Workers](https://developers.cloudflare.com/workers/) detalha o modelo de execução, limites de CPU e como configurar segredos com o Wrangler.

---

## Configuração do projeto

Crie o projeto com o Wrangler, a CLI do Cloudflare:

```bash
npm create cloudflare@latest cpf-validator -- --type=hello-world
cd cpf-validator
```

Configure o `wrangler.toml`:

```toml
name = "cpf-validator"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[vars]
ENVIRONMENT = "production"

[[kv_namespaces]]
binding = "CPF_CACHE"
id = "seu_kv_namespace_id"
```

---

## Implementação do Worker

O Worker principal recebe requisições, consulta o cache e, se necessário, chama a API da CPFHub.io:

```typescript
// src/index.ts

interface Env {
 CPFHUB_API_KEY: string;
 CPF_CACHE: KVNamespace;
 ENVIRONMENT: string;
}

interface CPFApiResponse {
 success: boolean;
 data?: {
 cpf: string;
 name: string;
 nameUpper: string;
 gender: string;
 birthDate: string;
 day: number;
 month: number;
 year: number;
 };
}

const CORS_HEADERS = {
 "Access-Control-Allow-Origin": "*",
 "Access-Control-Allow-Methods": "GET, OPTIONS",
 "Access-Control-Allow-Headers": "Content-Type",
};

const CACHE_TTL_SECONDS = 86400; // 24 horas
const API_TIMEOUT_MS = 10000;

function jsonResponse(body: object, status = 200): Response {
 return new Response(JSON.stringify(body), {
 status,
 headers: {
 ...CORS_HEADERS,
 "Content-Type": "application/json",
 "Cache-Control": "no-store",
 },
 });
}

function limparCPF(cpf: string): string {
 return cpf.replace(/\D/g, "");
}

function validarFormatoCPF(cpf: string): string | null {
 if (cpf.length !== 11) return "CPF deve conter 11 digitos";
 if (/^(\d)\1+$/.test(cpf)) return "CPF invalido";
 return null;
}

async function consultarCPFHub(
 cpf: string,
 apiKey: string
): Promise<CPFApiResponse> {
 const controller = new AbortController();
 const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT_MS);

 try {
 const response = await fetch(`https://api.cpfhub.io/cpf/${cpf}`, {
 method: "GET",
 headers: {
 "x-api-key": apiKey,
 "Accept": "application/json",
 },
 signal: controller.signal,
 });

 clearTimeout(timeoutId);

 if (!response.ok) {
 throw new Error(`API retornou status ${response.status}`);
 }

 return await response.json();
 } catch (error) {
 clearTimeout(timeoutId);
 throw error;
 }
}

export default {
 async fetch(request: Request, env: Env): Promise<Response> {
 // CORS preflight
 if (request.method === "OPTIONS") {
 return new Response(null, { headers: CORS_HEADERS });
 }

 if (request.method !== "GET") {
 return jsonResponse({ erro: "Metodo nao permitido" }, 405);
 }

 const url = new URL(request.url);
 const pathParts = url.pathname.split("/").filter(Boolean);

 // Rota: /cpf/:numero
 if (pathParts[0] !== "cpf" || !pathParts[1]) {
 return jsonResponse(
 { erro: "Use /cpf/{numero} para consultar" },
 400
 );
 }

 const cpf = limparCPF(pathParts[1]);
 const erroFormato = validarFormatoCPF(cpf);

 if (erroFormato) {
 return jsonResponse({ erro: erroFormato }, 400);
 }

 // Verificar cache KV
 const cacheKey = `cpf:${cpf}`;
 const cached = await env.CPF_CACHE.get(cacheKey, "json");

 if (cached) {
 return jsonResponse({
 valido: true,
 dados: cached,
 fonte: "cache",
 });
 }

 // Consultar API CPFHub.io
 try {
 const resultado = await consultarCPFHub(cpf, env.CPFHUB_API_KEY);

 if (!resultado.success || !resultado.data) {
 return jsonResponse({ erro: "CPF nao encontrado" }, 404);
 }

 const dados = {
 nome: resultado.data.name,
 cpf: resultado.data.cpf,
 genero: resultado.data.gender,
 dataNascimento: resultado.data.birthDate,
 };

 // Salvar no cache KV
 await env.CPF_CACHE.put(cacheKey, JSON.stringify(dados), {
 expirationTtl: CACHE_TTL_SECONDS,
 });

 return jsonResponse({
 valido: true,
 dados,
 fonte: "api",
 });
 } catch (error) {
 const mensagem =
 error instanceof DOMException && error.name === "AbortError"
 ? "Timeout na consulta de CPF"
 : `Erro: ${(error as Error).message}`;

 return jsonResponse({ erro: mensagem }, 500);
 }
 },
};
```

---

## Cache distribuido com KV

O Cloudflare KV e um armazenamento key-value distribuido globalmente, ideal para cachear resultados de consultas de CPF. Crie o namespace:

```bash
# Criar KV namespace
npx wrangler kv:namespace create CPF_CACHE

# O comando retorna o ID -- adicione ao wrangler.toml
```

Vantagens do KV para cache de CPF:

* **Distribuição global** -- O cache e replicado automaticamente em todos os datacenters.
* **TTL nativo** -- A expiracao e gerenciada pelo Cloudflare, sem necessidade de limpeza manual.
* **Consistência eventual** -- Atualizações propagam em até 60 segundos, aceitavel para dados de CPF.
* **Custo baixo** -- O plano gratuito inclui 100.000 leituras e 1.000 escritas por dia.

---

## Configuração de segredos

Armazene a chave de API como segredo do Worker:

```bash
# Definir segredo
npx wrangler secret put CPFHUB_API_KEY
# O CLI solicita o valor de forma segura

# Para desenvolvimento local, crie .dev.vars
echo "CPFHUB_API_KEY=sua_chave_aqui" > .dev.vars
```

Os segredos são criptografados e acessiveis apenas pelo Worker em tempo de execução, através do objeto `env`.

---

## Deploy e testes

Deploy do Worker:

```bash
# Desenvolvimento local
npx wrangler dev

# Deploy para producao
npx wrangler deploy
```

Teste local:

```bash
curl http://localhost:8787/cpf/12345678901
```

Apos o deploy, o Worker estara disponível em `https://cpf-validator.seu-subdominio.workers.dev/cpf/12345678901`.

---

## Rate limiting com Cloudflare

O Cloudflare oferece rate limiting nativo que pode ser configurado no dashboard ou via API:

```typescript
// Implementacao de rate limiting no proprio Worker
async function verificarRateLimit(
 request: Request,
 env: Env
): Promise<boolean> {
 const ip = request.headers.get("CF-Connecting-IP") ?? "unknown";
 const rateLimitKey = `ratelimit:${ip}`;
 const contagem = parseInt(
 (await env.CPF_CACHE.get(rateLimitKey)) ?? "0"
 );

 if (contagem >= 10) {
 return false; // Limite excedido
 }

 await env.CPF_CACHE.put(rateLimitKey, String(contagem + 1), {
 expirationTtl: 60, // Reset a cada 60 segundos
 });

 return true;
}
```

---

## Performance na edge

A principal vantagem dos Cloudflare Workers para validação de CPF e a latência:

| Metrica | Workers | Lambda (sa-east-1) | Cloud Functions |
|--------------------|----------------|---------------------|-----------------|
| Cold start | < 5ms | 200-800ms | 200-1000ms |
| Latência (Brasil) | ~10ms + API | ~20ms + API | ~15ms + API |
| Latência (Global) | ~10ms + API | Variavel | Variavel |

Como a API da [**CPFHub.io**](https://www.cpfhub.io/)

---

## Perguntas frequentes

### O que é necessário para integrar validação de CPF em Cloudflare Workers?

A integração exige um projeto criado com o Wrangler, um KV namespace para cache e a chave de API da CPFHub.io armazenada como segredo (`wrangler secret put`). O Worker usa o `fetch` nativo do runtime para chamar `GET https://api.cpfhub.io/cpf/{CPF}` com o header `x-api-key`, sem necessidade de bibliotecas HTTP externas.

### Qual é a latência total ao usar CPFHub.io em um Cloudflare Worker?

O Worker em si responde em poucos milissegundos (cold start praticamente irrelevante). A latência total depende da chamada à API CPFHub.io e do caminho de rede até o edge. **Não publicamos um número fixo de latência** — meça no seu ambiente (p95/p99) e use o timeout do `AbortController` com margem. Quando o resultado está no KV, a resposta fica bem mais rápida. Disponibilidade (SLA) por plano: [Preços](/precos) — Free 95%, Pro 99%, Corporate 99,9%.

### A API CPFHub.io bloqueia requisições quando o limite mensal é atingido?

Não. A API não bloqueia nem retorna 429 ao ultrapassar o limite do plano — ela continua respondendo e cobra R$0,15 por consulta adicional. O plano gratuito inclui 50 consultas/mês e o plano Pro oferece 1.000 consultas por R$149/mês. O cache KV com TTL de 24 horas ajuda a reduzir o consumo de cotas para CPFs consultados com frequência.

### Como proteger a chave de API da CPFHub.io em um Cloudflare Worker?

Use o comando `npx wrangler secret put CPFHUB_API_KEY` para armazenar a chave de forma criptografada. Ela fica acessível apenas em tempo de execução via `env.CPFHUB_API_KEY`, sem aparecer no código-fonte, nos logs do dashboard ou nas variáveis de ambiente em texto plano. Nunca inclua a chave diretamente no `wrangler.toml` ou no código versionado.

### Leia também

- [Como validar CPF no frontend com React e API REST](https://cpfhub.io/blog/como-validar-cpf-no-frontend-com-react-e-api-rest)
- [Boas práticas para consumir APIs de CPF de forma segura](https://cpfhub.io/blog/boas-praticas-consumir-apis-cpf-segura)
- [Como integrar validação de CPF em Vercel Edge Functions](https://cpfhub.io/blog/como-integrar-validacao-cpf-vercel-edge-functions-aplicacoes-serverless)
- [Como criar um SDK interno para padronizar consultas de CPF na empresa](https://cpfhub.io/blog/como-criar-sdk-interno-padronizar-consultas-cpf-empresa)

---

## Conclusão

Cloudflare Workers oferecem a menor latência possível para APIs de validação de CPF, com cold starts praticamente inexistentes e distribuição global automática. O KV fornece cache distribuido sem configuração, e os segredos manteem a chave de API protegida. Combinado com a API da [**CPFHub.io**](https://www.cpfhub.io/)

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/)

