# Como integrar validação de CPF em Streamlit para dashboards de dados

> Aprenda a integrar validação de CPF em dashboards Streamlit usando a API da CPFHub.io com exemplos visuais e interativos.

**Publicado:** 22/06/2026
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/como-integrar-validacao-de-cpf-em-streamlit-para-dashboards-de-dados

---


Para integrar validação de CPF em um dashboard Streamlit, você precisa chamar a API da CPFHub.io com `GET https://api.cpfhub.io/cpf/{CPF}` usando o header `x-api-key` e exibir o retorno diretamente na interface. O [Streamlit](https://docs.streamlit.io) torna esse processo direto: com poucas linhas de código é possível construir um formulário interativo que consulta dados cadastrais em tempo real. Quando o dashboard envolve dados de pessoas físicas, a validação de CPF garante a qualidade dos dados desde a entrada.

---

## 1. Pré-requisitos

* **Python 3.9+** instalado.

* Pacotes necessários: `pip install streamlit requests pandas`.

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

---

## 2. Configure a chave de API

Crie um arquivo `.streamlit/secrets.toml` na raiz do projeto para armazenar a chave de forma segura:

```toml
[cpfhub]
api_key = "SUA_CHAVE_DE_API"
base_url = "https://api.cpfhub.io"
timeout = 5
```

O Streamlit carrega automaticamente os secrets desse arquivo, acessíveis via `st.secrets`.

---

## 3. Crie o módulo de serviço

Crie o arquivo `cpf_service.py` para encapsular a comunicação com a API:

```python
# cpf_service.py
import re
import requests
import streamlit as st

def consultar_cpf(cpf: str) -> dict:
 """
 Consulta dados de um CPF na API da CPFHub.io.
 Retorna dict com dados ou lança exceção.
 """
 cpf_limpo = re.sub(r"\D", "", cpf)

 if len(cpf_limpo) != 11:
 raise ValueError("CPF deve conter exatamente 11 dígitos.")

 url = f"{st.secrets.cpfhub.base_url}/cpf/{cpf_limpo}"
 headers = {
 "x-api-key": st.secrets.cpfhub.api_key,
 "Accept": "application/json",
 }

 try:
 response = requests.get(
 url,
 headers=headers,
 timeout=st.secrets.cpfhub.timeout,
 )
 except requests.exceptions.Timeout:
 raise ConnectionError("Timeout ao consultar a API. Tente novamente.")
 except requests.exceptions.RequestException as e:
 raise ConnectionError(f"Erro de conexão: {str(e)}")

 if response.status_code == 200:
 data = response.json()
 if data.get("success"):
 return data["data"]
 raise ValueError("Resposta inesperada da API.")
 elif response.status_code == 401:
 raise PermissionError("Chave de API inválida.")
 elif response.status_code == 404:
 raise LookupError("CPF não encontrado na base de dados.")
 else:
 raise RuntimeError(f"Erro HTTP {response.status_code}")
```

---

## 4. Crie o dashboard principal

Crie o arquivo `app.py` com a interface do dashboard:

```python
# app.py
import streamlit as st
import pandas as pd
from cpf_service import consultar_cpf

st.set_page_config(
 page_title="Dashboard de Validação de CPF",
 page_icon="",
 layout="wide",
)

st.title("Dashboard de Validacao de CPF")
st.markdown("Consulta de dados cadastrais via API da **CPFHub.io**")

st.markdown("---")

# -- Seção 1: Consulta individual --
st.header("Consulta Individual")

col1, col2 = st.columns([1, 2])

with col1:
 cpf_input = st.text_input(
 "Digite o CPF",
 placeholder="000.000.000-00",
 max_chars=14,
 )
 consultar_btn = st.button("Consultar CPF", type="primary")

with col2:
 if consultar_btn and cpf_input:
 with st.spinner("Consultando API da CPFHub.io..."):
 try:
 dados = consultar_cpf(cpf_input)
 st.success("CPF encontrado com sucesso!")

 metric_col1, metric_col2, metric_col3 = st.columns(3)
 metric_col1.metric("Nome", dados.get("name", "N/A"))
 metric_col2.metric("Genero", dados.get("gender", "N/A"))
 metric_col3.metric("Data de Nascimento", dados.get("birthDate", "N/A"))

 with st.expander("Ver dados completos"):
 st.json(dados)

 except ValueError as e:
 st.error(f"Erro de validacao: {str(e)}")
 except LookupError as e:
 st.warning(str(e))
 except (ConnectionError, RuntimeError, PermissionError) as e:
 st.error(str(e))

 elif consultar_btn:
 st.warning("Por favor, digite um CPF.")
```

---

## 5. Adicione consulta em lote

Expanda o dashboard para permitir consultas em lote a partir de um arquivo CSV:

```python
# Continuação do app.py

st.markdown("---")

# -- Seção 2: Consulta em lote --
st.header("Consulta em Lote")

uploaded_file = st.file_uploader(
 "Envie um CSV com coluna 'cpf'",
 type=["csv"],
)

if uploaded_file is not None:
 df = pd.read_csv(uploaded_file, dtype=str)

 if "cpf" not in df.columns:
 st.error("O arquivo CSV deve conter uma coluna chamada 'cpf'.")
 else:
 st.dataframe(df.head(), use_container_width=True)
 total = len(df)
 st.info(f"Total de CPFs no arquivo: {total}")

 if st.button("Iniciar consulta em lote"):
 resultados = []
 progress_bar = st.progress(0)
 status_text = st.empty()

 for idx, row in df.iterrows():
 cpf = str(row["cpf"])
 status_text.text(f"Consultando {idx + 1}/{total}: {cpf}")

 try:
 dados = consultar_cpf(cpf)
 resultados.append({
 "cpf": cpf,
 "nome": dados.get("name"),
 "genero": dados.get("gender"),
 "nascimento": dados.get("birthDate"),
 "status": "Encontrado",
 })
 except Exception as e:
 resultados.append({
 "cpf": cpf,
 "nome": None,
 "genero": None,
 "nascimento": None,
 "status": str(e),
 })

 progress_bar.progress((idx + 1) / total)

 status_text.text("Consulta finalizada!")
 df_resultado = pd.DataFrame(resultados)
 st.dataframe(df_resultado, use_container_width=True)

 # Métricas de resumo
 encontrados = len(df_resultado[df_resultado["status"] == "Encontrado"])
 erros = total - encontrados

 col_m1, col_m2, col_m3 = st.columns(3)
 col_m1.metric("Total consultado", total)
 col_m2.metric("Encontrados", encontrados)
 col_m3.metric("Erros", erros)

 # Download do resultado
 csv_result = df_resultado.to_csv(index=False)
 st.download_button(
 "Baixar resultado (CSV)",
 csv_result,
 "resultado_cpf.csv",
 "text/csv",
 )
```

---

## 6. Adicione cache para evitar consultas duplicadas

Use o decorador `@st.cache_data` para armazenar resultados em cache:

```python
# cpf_service.py (versão com cache)
import re
import requests
import streamlit as st

@st.cache_data(ttl=3600, show_spinner=False)
def consultar_cpf_cached(cpf: str) -> dict:
 """
 Consulta CPF com cache de 1 hora para evitar chamadas duplicadas.
 """
 cpf_limpo = re.sub(r"\D", "", cpf)

 if len(cpf_limpo) != 11:
 raise ValueError("CPF deve conter exatamente 11 dígitos.")

 url = f"{st.secrets.cpfhub.base_url}/cpf/{cpf_limpo}"
 headers = {
 "x-api-key": st.secrets.cpfhub.api_key,
 "Accept": "application/json",
 }

 response = requests.get(url, headers=headers, timeout=st.secrets.cpfhub.timeout)

 if response.status_code == 200:
 data = response.json()
 if data.get("success"):
 return data["data"]
 raise RuntimeError(f"Erro: HTTP {response.status_code}")
```

---

## 7. Execute o dashboard

Inicie a aplicação com o comando:

```bash
streamlit run app.py --server.port 8501
```

Acesse `http://localhost:8501` no navegador para interagir com o dashboard.

---

## 8. Boas práticas

* **Secrets** -- Use `.streamlit/secrets.toml` para desenvolvimento local e o gerenciador de secrets do Streamlit Cloud para deploy.

* **Cache** -- O `@st.cache_data` evita consultas duplicadas e economiza sua cota mensal de consultas.

* **Feedback visual** -- Use `st.spinner`, `st.progress` e `st.status` para informar o usuário sobre o andamento das consultas.

* **Consultas em lote** -- Para consultas em lote, considere adicionar um `time.sleep(0.5)` entre requisições. O plano gratuito oferece 50 consultas/mês; consultas extras custam R$0,15 cada — a API não bloqueia, apenas cobra o excedente.

* **Timeout** -- O timeout de 5 segundos nas requisições evita que o dashboard trave aguardando respostas. A latência típica da API é de ~900ms.

* **LGPD** -- A API da CPFHub.io opera em total conformidade com a LGPD. Ao exibir dados pessoais no dashboard, considere mascarar informações sensíveis e restringir o acesso.

---

## Perguntas frequentes

### Como a API CPFHub.io é autenticada em um dashboard Streamlit?

A autenticação é feita via header `x-api-key` em cada requisição GET para `https://api.cpfhub.io/cpf/{CPF}`. No Streamlit, a prática recomendada é armazenar a chave em `.streamlit/secrets.toml` e acessá-la via `st.secrets`, evitando expor credenciais no código-fonte ou em repositórios públicos.

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

Não. Quando o limite de consultas do plano é atingido, a API não retorna erro nem bloqueia as requisições — ela simplesmente cobra R$0,15 por cada consulta adicional. O plano gratuito inclui 50 consultas/mês e o plano Pro inclui 1.000 consultas por R$149/mês.

### Qual é a latência esperada ao consultar CPFs no Streamlit?

A API da CPFHub.io tem latência média de ~900ms por consulta. Para dashboards com consultas em lote, implemente `@st.cache_data` para evitar chamadas repetidas ao mesmo CPF e adicione `time.sleep(0.5)` entre requisições sequenciais para distribuir a carga de forma adequada.

### Como garantir conformidade com a LGPD ao exibir dados de CPF em dashboards?

Use o CPF apenas para a finalidade declarada ao titular, armazene apenas o necessário e restrinja o acesso ao dashboard com autenticação. A [ANPD](https://www.gov.br/anpd) orienta que dados de identificação devem ser tratados com o princípio da necessidade — considere mascarar campos sensíveis na visualização para usuários sem permissão de leitura completa.

### 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 consumir API de CPF em Python com FastAPI](https://cpfhub.io/blog/como-consumir-api-de-cpf-em-python-com-fastapi)
- [Como consumir API de CPF em Jupyter Notebook para análise exploratória](https://cpfhub.io/blog/como-consumir-api-de-cpf-em-jupyter-notebook-para-analise-exploratoria)

---

## Conclusão

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

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

