Para consumir a API de CPF da CPFHub.io em um app React Native, o caminho correto é nunca chamar a API diretamente do dispositivo — a chave de API ficaria exposta no bundle. O padrão recomendado é criar um backend intermediário (Node.js, por exemplo) que recebe o CPF do app, consulta https://api.cpfhub.io/cpf/{CPF} com o header x-api-key e devolve apenas os dados necessários. A documentação oficial do React Native detalha as opções de rede disponíveis, incluindo fetch e XMLHttpRequest, que funcionam tanto em iOS quanto em Android.
Arquitetura segura para apps mobile
Em aplicações mobile, a chave de API nunca deve ser incluida no código do app. A arquitetura recomendada e:
- O app React Native envia o CPF para seu backend.
- O backend consulta a API da CPFHub.io com a chave de API.
- O backend retorna o resultado ao app.
Essa camada intermediaria protege a chave de API e permite adicionar rate limiting, cache e logs no servidor.
Backend intermediario (Node.js/Express)
Crie um endpoint simples que recebe o CPF do app e consulta a API:
// backend/server.js
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3001;
const CPFHUB_API_KEY = process.env.CPFHUB_API_KEY;
app.get("/api/validar-cpf/:cpf", async (req, res) => {
const cpf = req.params.cpf.replace(/\D/g, "");
if (cpf.length !== 11) {
return res.status(400).json({ erro: "CPF deve ter 11 digitos" });
}
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000);
try {
const response = await fetch(
`https://api.cpfhub.io/cpf/${cpf}`,
{
method: "GET",
headers: {
"x-api-key": CPFHUB_API_KEY,
"Accept": "application/json",
},
signal: controller.signal,
}
);
clearTimeout(timeoutId);
const dados = await response.json();
if (!dados.success) {
return res.status(404).json({ erro: "CPF nao encontrado" });
}
res.json({
valido: true,
dados: {
nome: dados.data.name,
genero: dados.data.gender,
dataNascimento: dados.data.birthDate,
},
});
} catch (error) {
clearTimeout(timeoutId);
const mensagem = error.name === "AbortError"
? "Timeout na consulta"
: error.message;
res.status(500).json({ erro: mensagem });
}
});
app.listen(PORT, () => console.log(`Backend rodando na porta ${PORT}`));
Serviço de API no React Native
Crie um módulo que encapsula as chamadas ao backend:
// src/services/cpfService.ts
import { Platform } from "react-native";
const API_BASE_URL = __DEV__
? Platform.OS === "android"
? "http://10.0.2.2:3001"
: "http://localhost:3001"
: "https://api.meuapp.com.br";
const TIMEOUT_MS = 15000;
interface CPFResult {
valido: boolean;
dados?: {
nome: string;
genero: string;
dataNascimento: string;
};
erro?: string;
}
export async function validarCPF(cpf: string): Promise<CPFResult> {
const cpfLimpo = cpf.replace(/\D/g, "");
if (cpfLimpo.length !== 11) {
return { valido: false, erro: "CPF deve ter 11 digitos" };
}
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
try {
const response = await fetch(
`${API_BASE_URL}/api/validar-cpf/${cpfLimpo}`,
{
method: "GET",
headers: { "Accept": "application/json" },
signal: controller.signal,
}
);
clearTimeout(timeoutId);
const dados = await response.json();
if (!response.ok) {
return { valido: false, erro: dados.erro || "Erro na consulta" };
}
return dados;
} catch (error) {
clearTimeout(timeoutId);
if ((error as Error).name === "AbortError") {
return { valido: false, erro: "Tempo limite excedido. Verifique sua conexao." };
}
return { valido: false, erro: "Sem conexao com o servidor" };
}
}
Note a diferenciacao de URL para Android (que usa 10.0.2.2 para acessar o localhost do host) e iOS.
Componente de validação de CPF
O componente principal com mascara de input, feedback visual e tratamento de estados:
// src/screens/ValidarCPFScreen.tsx
import React, { useState, useCallback } from "react";
import {
View,
Text,
TextInput,
TouchableOpacity,
ActivityIndicator,
StyleSheet,
Alert,
KeyboardAvoidingView,
Platform,
} from "react-native";
import { validarCPF } from "../services/cpfService";
function formatarCPF(texto: string): string {
const digitos = texto.replace(/\D/g, "").slice(0, 11);
if (digitos.length <= 3) return digitos;
if (digitos.length <= 6) return `${digitos.slice(0, 3)}.${digitos.slice(3)}`;
if (digitos.length <= 9)
return `${digitos.slice(0, 3)}.${digitos.slice(3, 6)}.${digitos.slice(6)}`;
return `${digitos.slice(0, 3)}.${digitos.slice(3, 6)}.${digitos.slice(6, 9)}-${digitos.slice(9)}`;
}
export default function ValidarCPFScreen() {
const [cpf, setCpf] = useState("");
const [carregando, setCarregando] = useState(false);
const [resultado, setResultado] = useState<{
nome?: string;
genero?: string;
dataNascimento?: string;
} | null>(null);
const [erro, setErro] = useState<string | null>(null);
const handleChangeCPF = useCallback((texto: string) => {
setCpf(formatarCPF(texto));
setResultado(null);
setErro(null);
}, []);
const handleConsultar = useCallback(async () => {
const cpfLimpo = cpf.replace(/\D/g, "");
if (cpfLimpo.length !== 11) {
setErro("Informe um CPF completo com 11 digitos.");
return;
}
setCarregando(true);
setErro(null);
setResultado(null);
try {
const res = await validarCPF(cpfLimpo);
if (res.valido && res.dados) {
setResultado(res.dados);
} else {
setErro(res.erro ?? "CPF nao encontrado.");
}
} catch {
Alert.alert("Erro", "Falha ao consultar CPF. Tente novamente.");
} finally {
setCarregando(false);
}
}, [cpf]);
return (
<KeyboardAvoidingView
style={styles.container}
behavior={Platform.OS === "ios" ? "padding" : "height"}
>
<Text style={styles.titulo}>Validar CPF</Text>
<TextInput
style={styles.input}
value={cpf}
onChangeText={handleChangeCPF}
placeholder="000.000.000-00"
keyboardType="number-pad"
maxLength={14}
returnKeyType="done"
/>
<TouchableOpacity
style={[styles.botao, carregando && styles.botaoDesabilitado]}
onPress={handleConsultar}
disabled={carregando}
activeOpacity={0.7}
>
{carregando ? (
<ActivityIndicator color="#ffffff" />
) : (
<Text style={styles.botaoTexto}>Consultar</Text>
)}
</TouchableOpacity>
{erro && (
<View style={styles.erroContainer}>
<Text style={styles.erroTexto}>{erro}</Text>
</View>
)}
{resultado && (
<View style={styles.resultadoContainer}>
<Text style={styles.resultadoLabel}>Nome</Text>
<Text style={styles.resultadoValor}>{resultado.nome}</Text>
<Text style={styles.resultadoLabel}>Genero</Text>
<Text style={styles.resultadoValor}>
{resultado.genero === "M" ? "Masculino" : "Feminino"}
</Text>
<Text style={styles.resultadoLabel}>Data de nascimento</Text>
<Text style={styles.resultadoValor}>{resultado.dataNascimento}</Text>
</View>
)}
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 24,
backgroundColor: "#f8f9fa",
},
titulo: {
fontSize: 24,
fontWeight: "700",
marginBottom: 24,
color: "#1a1a2e",
},
input: {
backgroundColor: "#ffffff",
borderRadius: 8,
padding: 16,
fontSize: 18,
borderWidth: 1,
borderColor: "#dee2e6",
marginBottom: 16,
},
botao: {
backgroundColor: "#4361ee",
borderRadius: 8,
padding: 16,
alignItems: "center",
},
botaoDesabilitado: {
opacity: 0.6,
},
botaoTexto: {
color: "#ffffff",
fontSize: 16,
fontWeight: "600",
},
erroContainer: {
backgroundColor: "#fee2e2",
borderRadius: 8,
padding: 12,
marginTop: 16,
},
erroTexto: {
color: "#dc2626",
fontSize: 14,
},
resultadoContainer: {
backgroundColor: "#ffffff",
borderRadius: 8,
padding: 16,
marginTop: 16,
borderWidth: 1,
borderColor: "#d1fae5",
},
resultadoLabel: {
fontSize: 12,
color: "#6b7280",
marginTop: 8,
},
resultadoValor: {
fontSize: 16,
color: "#1a1a2e",
fontWeight: "500",
},
});
Tratamento de conectividade
Apps mobile enfrentam desafios de conectividade que aplicações web não tem. Use o módulo @react-native-community/netinfo para verificar a conexão antes de consultar:
import NetInfo from "@react-native-community/netinfo";
async function verificarConexao(): Promise<boolean> {
const state = await NetInfo.fetch();
return state.isConnected ?? false;
}
// Antes de consultar
if (!(await verificarConexao())) {
setErro("Sem conexao com a internet. Verifique sua rede.");
return;
}
Boas práticas para mobile
- Nunca armazene a chave de API no app -- Use sempre um backend intermediario.
- Timeout generoso -- Conexões mobile são mais lentas; use 15 segundos em vez de 10.
- Feedback visual -- Sempre mostre indicadores de carregamento; usuários mobile são impacientes.
- Teclado numerico -- Use
keyboardType="number-pad"para facilitar a digitacao do CPF. - Mascara de input -- Formate o CPF automaticamente para reduzir erros.
Perguntas frequentes
Por que não posso chamar a API de CPF diretamente do app React Native?
Chamadas diretas do app exporiam a chave de API no bundle JavaScript, que pode ser inspecionado com ferramentas como react-native-decompiler ou simplesmente monitorando o tráfego de rede. Com a chave comprometida, qualquer pessoa poderia consumir sua cota ou gerar cobranças. O backend intermediário é a única forma segura de guardar credenciais em aplicações mobile.
Como o timeout de 15 segundos afeta a experiência do usuário?
Em redes móveis — especialmente 3G ou conexões instáveis — a latência pode ser significativamente maior do que em desktop. O timeout de 15 segundos no lado do app dá margem suficiente para o backend consultar a API (latência típica de ~900ms) e retornar, mesmo com alguma degradação de rede. Se estourar, exiba uma mensagem clara pedindo ao usuário para tentar novamente.
A API CPFHub.io retorna erro quando o limite de consultas é atingido?
Não. Ao ultrapassar o limite do plano — 50 consultas no gratuito ou 1.000 no Pro (R$149/mês) — a API continua respondendo normalmente e cobra R$0,15 por consulta adicional. Não há interrupção do serviço nem código de erro específico por limite excedido. O controle de custos é feito pelo painel em app.cpfhub.io/settings/billing.
Como adaptar o componente para Expo Go durante o desenvolvimento?
Em projetos Expo, a URL do emulador Android muda para http://10.0.2.2:PORT, enquanto dispositivos físicos precisam do IP da máquina na rede local. O serviço já trata isso via Platform.OS. Para produção, substitua a URL pelo domínio real do seu backend. Consulte a documentação de rede do React Native para mais detalhes.
Conclusão
A integração da API de CPF da CPFHub.io
Cadastre-se em cpfhub.io
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



