# Como consumir API de CPF em Astro com endpoints de servidor

> Aprenda a consumir a API de consulta de CPF da CPFHub.io em Astro usando server endpoints para validação segura no backend.

**Publicado:** 17/04/2026
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/como-consumir-api-de-cpf-em-astro-com-endpoints-de-servidor

---


O **Astro** permite criar server endpoints que executam exclusivamente no backend, o que torna a integração com a API da CPFHub.io segura por design: a chave de API nunca chega ao navegador. Com o adapter de servidor configurado, você cria um arquivo em `src/pages/api/` e o Astro expõe uma rota HTTP que seu frontend chama normalmente. A latência da API gira em torno de ~900ms, então configure sempre um timeout adequado nas suas requisições.

---

## 1. Pré-requisitos

* **Astro 4+** configurado com `npm create astro@latest`.

* Um **adapter de servidor** instalado (Node.js, Vercel, Netlify ou Cloudflare).

* Uma conta na [**CPFHub.io**](https://www.cpfhub.io/)

---

## 2. Configure o adapter e variáveis de ambiente

Instale o adapter para Node.js (ou outro de sua escolha):

```bash
npx astro add node
```

Crie o arquivo `.env` na raiz do projeto:

```
CPFHUB_API_KEY=SUA_CHAVE_DE_API
```

No arquivo `astro.config.mjs`, confirme que o output é `server` ou `hybrid`:

```javascript
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
 output: 'server',
 adapter: node({
 mode: 'standalone'
 })
});
```

---

## 3. Crie o server endpoint

Crie o arquivo `src/pages/api/cpf/[cpf].ts`:

```typescript
import type { APIRoute } from 'astro';

export const GET: APIRoute = async ({ params }) => {
 const cpf = params.cpf?.replace(/\D/g, '');

 if (!cpf || cpf.length !== 11) {
 return new Response(
 JSON.stringify({ error: 'CPF deve conter 11 dígitos' }),
 { status: 400, headers: { 'Content-Type': 'application/json' } }
 );
 }

 const controller = new AbortController();
 const timeoutId = setTimeout(() => controller.abort(), 5000);

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

 clearTimeout(timeoutId);

 if (!response.ok) {
 return new Response(
 JSON.stringify({ error: `API retornou HTTP ${response.status}` }),
 { status: response.status, headers: { 'Content-Type': 'application/json' } }
 );
 }

 const data = await response.json();
 return new Response(JSON.stringify(data), {
 status: 200,
 headers: { 'Content-Type': 'application/json' }
 });
 } catch (error) {
 clearTimeout(timeoutId);
 return new Response(
 JSON.stringify({ error: 'Timeout ou falha na consulta' }),
 { status: 502, headers: { 'Content-Type': 'application/json' } }
 );
 }
};
```

O endpoint fica acessível em `GET /api/cpf/{cpf}` e a chave de API permanece exclusivamente no servidor.

---

## 4. Página com formulário de validação

Crie `src/pages/validar-cpf.astro` com renderização no servidor:

```astro
---
// src/pages/validar-cpf.astro
let resultado = null;
let erro = null;

if (Astro.request.method === 'POST') {
 const formData = await Astro.request.formData();
 const cpf = (formData.get('cpf') as string)?.replace(/\D/g, '');

 if (!cpf || cpf.length !== 11) {
 erro = 'CPF deve conter 11 dígitos';
 } else {
 const controller = new AbortController();
 const timeoutId = setTimeout(() => controller.abort(), 5000);

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

 clearTimeout(timeoutId);

 if (response.ok) {
 resultado = await response.json();
 } else {
 erro = `Erro na consulta: HTTP ${response.status}`;
 }
 } catch (e) {
 clearTimeout(timeoutId);
 erro = 'Timeout ou falha na conexão';
 }
 }
}
---

<html lang="pt-BR">
<head>
 <meta charset="UTF-8" />
 <title>Validar CPF</title>
</head>
<body>
 <h1>Validar CPF</h1>

 <form method="POST">
 <label for="cpf">CPF:</label>
 <input type="text" id="cpf" name="cpf" placeholder="Somente números" maxlength="14" required />
 <button type="submit">Validar</button>
 </form>

 {erro && <p style="color: red;">{erro}</p>}

 {resultado?.success && (
 <div>
 <h2>Resultado</h2>
 <p><strong>Nome:</strong> {resultado.data.name}</p>
 <p><strong>CPF:</strong> {resultado.data.cpf}</p>
 <p><strong>Gênero:</strong> {resultado.data.gender === 'M' ? 'Masculino' : 'Feminino'}</p>
 <p><strong>Data de Nascimento:</strong> {resultado.data.birthDate}</p>
 </div>
 )}
</body>
</html>
```

---

## 5. Teste com cURL

Teste o server endpoint diretamente:

```bash
curl -X GET http://localhost:4321/api/cpf/12345678900 \
 -H "Accept: application/json"
```

Resposta esperada:

```json
{
 "success": true,
 "data": {
 "cpf": "12345678900",
 "name": "João da Silva",
 "nameUpper": "JOÃO DA SILVA",
 "gender": "M",
 "birthDate": "15/06/1990",
 "day": 15,
 "month": 6,
 "year": 1990
 }
}
```

---

## 6. Chamada via JavaScript no cliente

Para uma experiência interativa sem recarregar a página, chame o endpoint via fetch no cliente:

```astro
---
// src/pages/consulta-interativa.astro
---

<html lang="pt-BR">
<head>
 <meta charset="UTF-8" />
 <title>Consulta de CPF</title>
</head>
<body>
 <h1>Consulta de CPF</h1>
 <input type="text" id="cpfInput" placeholder="Digite o CPF" maxlength="14" />
 <button id="btnConsultar">Consultar</button>
 <pre id="resultado"></pre>

 <script>
 document.getElementById('btnConsultar').addEventListener('click', async () => {
 const cpf = document.getElementById('cpfInput').value.replace(/\D/g, '');
 const resultadoEl = document.getElementById('resultado');

 if (cpf.length !== 11) {
 resultadoEl.textContent = 'CPF deve conter 11 dígitos';
 return;
 }

 resultadoEl.textContent = 'Consultando...';

 try {
 const response = await fetch(`/api/cpf/${cpf}`);
 const data = await response.json();
 resultadoEl.textContent = JSON.stringify(data, null, 2);
 } catch (error) {
 resultadoEl.textContent = 'Erro na consulta';
 }
 });
 </script>
</body>
</html>
```

Nesse modelo, o navegador chama `/api/cpf/{cpf}` e o server endpoint faz a chamada segura à CPFHub.io.

---

## 7. Boas práticas

* **Server-only** -- A chave de API é acessada via `import.meta.env.CPFHUB_API_KEY` e nunca exposta ao cliente.

* **Timeout** -- Todos os exemplos usam `AbortController` com 5 segundos de timeout.

* **Validação local** -- Verifique o formato do CPF (11 dígitos) antes de chamar a API para economizar consultas.

* **Adapter** -- Escolha o adapter adequado ao seu deploy: Node.js para servidores tradicionais, Vercel/Netlify para serverless.

* **Rate limit** -- O plano Gratuito oferece 50 consultas/mês. Para produção, o plano Pro inclui 1.000 consultas por R$ 149/mês.

---

## Perguntas frequentes

### O que é necessário para implementar validação de CPF no Astro?

Para integrar a API da CPFHub.io no Astro você precisa de: Astro 4+ com um adapter de servidor ativo (Node.js, Vercel ou Netlify), uma variável de ambiente `CPFHUB_API_KEY` configurada no `.env`, e um arquivo de endpoint em `src/pages/api/`. O adapter é o ponto crítico — sem ele o Astro roda no modo estático e os server endpoints não funcionam.

### Como garantir que a chave de API não vaze para o navegador?

No Astro, variáveis de ambiente sem o prefixo `PUBLIC_` ficam disponíveis somente no servidor. Use `import.meta.env.CPFHUB_API_KEY` dentro do arquivo de endpoint (`.ts`) e nunca em componentes `.astro` que sejam hidratados no cliente. Dessa forma, a chave trafega apenas entre o seu servidor e a API da CPFHub.io.

### Como garantir conformidade com a LGPD ao usar uma API de CPF no Astro?

Use o CPF apenas para a finalidade declarada ao titular, não armazene o dado cru em logs de servidor se um identificador interno bastar, e implemente controle de acesso às rotas de consulta. A [ANPD](https://www.gov.br/anpd) orienta que dados de identificação devem ser tratados com o princípio da necessidade — isso inclui APIs de terceiros que processam CPFs em seu nome.

### Quanto custa usar a API CPFHub.io além do limite do plano?

O plano Gratuito cobre 50 consultas por mês sem cartão de crédito. Se o limite for ultrapassado, a API não interrompe o serviço: cada consulta adicional é cobrada a R$ 0,15. Para volumes maiores, o plano Pro oferece 1.000 consultas mensais por R$ 149, com o mesmo modelo de excedente.

### Qual timeout é recomendado para chamadas à API CPFHub.io no Astro?

Configure pelo menos 5 segundos de timeout via `AbortController`, como mostrado nos exemplos deste artigo. A latência da API é de ~900ms em condições normais, mas picos de rede ou concorrência podem aumentar esse tempo. Um timeout muito curto gera erros 502 desnecessários no seu endpoint; um timeout muito longo trava requisições na fila do servidor.

### Leia também

- [LGPD: CPF é dado pessoal sensível ou não? Entenda a classificação correta](https://cpfhub.io/blog/lgpd-cpf-e-dado-pessoal-sensivel-ou-nao-entenda-a-classificacao-correta)
- [Como implementar data minimization ao consultar CPFs via API](https://cpfhub.io/blog/como-implementar-data-minimization-ao-consultar-cpfs-via-api)
- [Como garantir que sua API de CPF seja compatível com a LGPD](https://cpfhub.io/blog/garantir-api-cpf-compativel-lgpd)
- [Como armazenar respostas de APIs de CPF com privacidade](https://cpfhub.io/blog/armazenar-respostas-apis-cpf-privacidade)

---

## Conclusão

O Astro com server endpoints é uma excelente opção para consumir a API da [**CPFHub.io**](https://www.cpfhub.io/)

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

