# UX de verificação de CPF em totens de autoatendimento e quiosques

> Aprenda boas práticas de UX para verificação de CPF em totens de autoatendimento e quiosques, com exemplos de interface e integração via API.

**Publicado:** 04/09/2025
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/ux-de-verificacao-de-cpf-em-totens-de-autoatendimento-e-quiosques

---


Projetar a UX de verificação de CPF em totens exige teclado numérico dedicado, máscara automática e feedback visual em menos de 300ms. Com a CPFHub.io, a resposta chega em ~900ms e o plano gratuito — 50 consultas mensais, sem cartão de crédito — permite prototipar e testar o fluxo completo antes de entrar em produção.

## Introdução

Totens de autoatendimento e quiosques digitais estão cada vez mais presentes em farmácias, aeroportos, clínicas, bancos e lojas de varejo. Esses dispositivos permitem que o cliente realize operações de forma autônoma -- sem depender de um atendente -- e a verificação de CPF é frequentemente o primeiro passo desse fluxo.

No entanto, projetar a experiência de entrada e validação de CPF em um totem é muito diferente de projetar para web ou mobile. A tela é touch, o teclado é virtual, o usuário está de pé e muitas vezes com pressa.

---

## Por que totens exigem uma abordagem diferente de UX

Diferentemente de um smartphone ou computador, totens de autoatendimento apresentam restrições específicas que impactam diretamente o design da interface:

### Contexto de uso

- O usuário está de pé, muitas vezes em um ambiente barulhento.
- Não há teclado físico -- a digitação é feita em teclado virtual na tela touch.
- O tempo de interação deve ser o menor possível para evitar filas.
- O usuário pode ter pouca familiaridade com tecnologia.

### Restrições técnicas

- Telas geralmente são de 15 a 22 polegadas, com resolução limitada.
- A conectividade pode ser via Wi-Fi ou 4G, com latência variável.
- O sistema operacional costuma ser Linux embarcado ou Windows IoT.

Essas particularidades exigem interfaces com botões grandes, feedback visual claro e fluxos extremamente simplificados.

---

## Boas práticas de UX para entrada de CPF em totens

### 1. Teclado numérico dedicado

Nunca exiba um teclado QWERTY completo para entrada de CPF. Utilize um teclado numérico com botões grandes -- no mínimo 60x60 pixels -- para facilitar o toque com o dedo.

### 2. Máscara automática com feedback imediato

Aplique a máscara `000.000.000-00` à medida que o usuário digita. Cada dígito inserido deve gerar um feedback visual imediato -- como o campo mudando de cor ou o dígito aparecendo com uma breve animação.

### 3. Botão de correção visível

Inclua um botão "Apagar" grande e acessível. Muitos totens não possuem tecla backspace intuitiva, e o usuário precisa corrigir erros com facilidade.

### 4. Validação local antes da consulta

Valide o dígito verificador do CPF localmente antes de enviar a requisição à API. Isso evita chamadas desnecessárias e dá feedback instantâneo ao usuário.

### 5. Indicador de progresso durante a consulta

Enquanto a API está processando, exiba um spinner ou barra de progresso com uma mensagem como "Verificando seu CPF...". Nunca deixe a tela sem feedback por mais de 300ms.

---

## Layout de interface para totem

A seguir, um exemplo de layout HTML/CSS otimizado para tela touch de totem. O design prioriza botões grandes, contraste alto e simplicidade.

```html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
 <meta charset="UTF-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 <title>Verificação de CPF - Totem</title>
 <style>
 * { margin: 0; padding: 0; box-sizing: border-box; }
 body {
 font-family: 'Segoe UI', Arial, sans-serif;
 background: #1a1a2e;
 color: #ffffff;
 display: flex;
 flex-direction: column;
 align-items: center;
 justify-content: center;
 height: 100vh;
 user-select: none;
 -webkit-user-select: none;
 }
 h1 { font-size: 2rem; margin-bottom: 1rem; }
 .cpf-display {
 font-size: 3rem;
 letter-spacing: 4px;
 background: #16213e;
 border: 2px solid #0f3460;
 border-radius: 12px;
 padding: 20px 40px;
 min-width: 460px;
 text-align: center;
 margin-bottom: 2rem;
 min-height: 80px;
 }
 .cpf-display.error {
 border-color: #e74c3c;
 animation: shake 0.3s ease-in-out;
 }
 .cpf-display.success { border-color: #2ecc71; }
 @keyframes shake {
 0%, 100% { transform: translateX(0); }
 25% { transform: translateX(-8px); }
 75% { transform: translateX(8px); }
 }
 .keypad {
 display: grid;
 grid-template-columns: repeat(3, 100px);
 gap: 12px;
 }
 .key {
 width: 100px;
 height: 80px;
 font-size: 2rem;
 border: none;
 border-radius: 12px;
 background: #0f3460;
 color: #ffffff;
 cursor: pointer;
 transition: background 0.15s;
 }
 .key:active { background: #533483; }
 .key.backspace { background: #e74c3c; font-size: 1.4rem; }
 .key.backspace:active { background: #c0392b; }
 .key.confirm {
 background: #2ecc71;
 grid-column: span 2;
 width: 212px;
 font-size: 1.4rem;
 font-weight: bold;
 }
 .key.confirm:active { background: #27ae60; }
 .key.confirm:disabled {
 background: #555;
 cursor: not-allowed;
 }
 .status {
 margin-top: 1.5rem;
 font-size: 1.3rem;
 min-height: 40px;
 }
 .spinner {
 display: inline-block;
 width: 24px; height: 24px;
 border: 3px solid #fff;
 border-top-color: transparent;
 border-radius: 50%;
 animation: spin 0.8s linear infinite;
 vertical-align: middle;
 margin-right: 8px;
 }
 @keyframes spin {
 to { transform: rotate(360deg); }
 }
 </style>
</head>
<body>
 <h1>Digite seu CPF</h1>
 <div class="cpf-display" id="display">___.___.___-__</div>

 <div class="keypad">
 <button class="key" onclick="addDigit('1')">1</button>
 <button class="key" onclick="addDigit('2')">2</button>
 <button class="key" onclick="addDigit('3')">3</button>
 <button class="key" onclick="addDigit('4')">4</button>
 <button class="key" onclick="addDigit('5')">5</button>
 <button class="key" onclick="addDigit('6')">6</button>
 <button class="key" onclick="addDigit('7')">7</button>
 <button class="key" onclick="addDigit('8')">8</button>
 <button class="key" onclick="addDigit('9')">9</button>
 <button class="key backspace" onclick="removeDigit()">Apagar</button>
 <button class="key" onclick="addDigit('0')">0</button>
 <button class="key confirm" id="btnConfirm" onclick="verificarCPF()" disabled>
 Confirmar
 </button>
 </div>

 <div class="status" id="status"></div>

 <script>
 let digits = '';
 const display = document.getElementById('display');
 const status = document.getElementById('status');
 const btnConfirm = document.getElementById('btnConfirm');

 function formatCPF(d) {
 const mask = '___.___.___-__';
 let result = '';
 let idx = 0;
 for (let i = 0; i < mask.length; i++) {
 if (mask[i] === '_') {
 result += idx < d.length ? d[idx++] : '_';
 } else {
 result += mask[i];
 }
 }
 return result;
 }

 function addDigit(d) {
 if (digits.length >= 11) return;
 digits += d;
 display.textContent = formatCPF(digits);
 display.className = 'cpf-display';
 btnConfirm.disabled = digits.length < 11;
 }

 function removeDigit() {
 digits = digits.slice(0, -1);
 display.textContent = formatCPF(digits);
 display.className = 'cpf-display';
 btnConfirm.disabled = digits.length < 11;
 status.textContent = '';
 }

 function validarDigitos(cpf) {
 if (/^(\d)\1{10}$/.test(cpf)) return false;
 let soma = 0;
 for (let i = 0; i < 9; i++) soma += parseInt(cpf[i]) * (10 - i);
 let resto = (soma * 10) % 11;
 if (resto === 10) resto = 0;
 if (resto !== parseInt(cpf[9])) return false;
 soma = 0;
 for (let i = 0; i < 10; i++) soma += parseInt(cpf[i]) * (11 - i);
 resto = (soma * 10) % 11;
 if (resto === 10) resto = 0;
 return resto === parseInt(cpf[10]);
 }

 async function verificarCPF() {
 if (!validarDigitos(digits)) {
 display.className = 'cpf-display error';
 status.textContent = 'CPF invalido. Verifique os digitos.';
 return;
 }

 status.innerHTML = '<span class="spinner"></span> Verificando seu CPF...';
 btnConfirm.disabled = true;

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

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

 if (data.success) {
 display.className = 'cpf-display success';
 status.textContent = `Bem-vindo(a), ${data.data.name}!`;
 } else {
 display.className = 'cpf-display error';
 status.textContent = 'CPF nao encontrado. Procure um atendente.';
 }
 } catch (err) {
 clearTimeout(timeoutId);
 display.className = 'cpf-display error';
 status.textContent = err.name === 'AbortError'
 ? 'Tempo esgotado. Tente novamente.'
 : 'Erro de conexao. Tente novamente.';
 } finally {
 btnConfirm.disabled = false;
 }
 }
 </script>
</body>
</html>
```

---

## Acessibilidade em totens

A acessibilidade em totens de autoatendimento merece atenção especial, pois os dispositivos são utilizados por um público diverso.

### Contraste e legibilidade

- Utilize contraste mínimo de 4.5:1 entre texto e fundo (WCAG AA).
- Fontes com no mínimo 24px para textos principais e 18px para secundários.
- Evite fontes serifadas -- sans-serif como Arial ou Segoe UI funcionam melhor em telas touch.

### Acessibilidade para deficientes visuais

- Implemente suporte a leitor de tela via `aria-label` nos botões.
- Considere feedback sonoro a cada dígito inserido.
- Se possível, ofereça entrada por voz como alternativa.

### Altura e alcance

- Posicione os elementos interativos na zona de alcance confortável -- entre 90cm e 130cm do chão.
- Botões críticos devem estar na parte inferior da tela, não no topo.

---

## Tratamento de cenários de erro

Em um totem, o tratamento de erros precisa ser ainda mais cuidadoso do que em uma aplicação web convencional. O usuário não pode abrir o DevTools para investigar o problema.

### Cenários comuns e como tratar

| Cenário | Mensagem sugerida | Ação |
|---|---|---|
| CPF com dígito inválido | "CPF inválido. Verifique os números digitados." | Permitir correção imediata |
| Timeout da API | "A verificação demorou mais que o esperado. Tente novamente." | Botão "Tentar novamente" |
| Erro de rede | "Sem conexão. Procure um atendente." | Exibir código de atendimento |
| CPF não encontrado | "CPF não localizado. Procure um atendente." | Exibir código de atendimento |

### Fallback para atendimento humano

Sempre ofereça uma saída para o atendimento humano. Após duas tentativas falhas, exiba uma mensagem como: "Não foi possível verificar seu CPF. Dirija-se ao balcão de atendimento com o código **T-4821**."

---

## Segurança e privacidade no totem

Totens são dispositivos compartilhados, o que traz preocupações adicionais de segurança.

### Limpeza automática de dados

Após cada sessão, todos os dados do CPF devem ser apagados da memória e da tela. Implemente um timeout de inatividade -- por exemplo, 60 segundos -- que limpa a sessão e retorna à tela inicial.

```javascript
let inactivityTimer;

function resetInactivityTimer() {
 clearTimeout(inactivityTimer);
 inactivityTimer = setTimeout(() => {
 digits = '';
 display.textContent = formatCPF('');
 status.textContent = '';
 btnConfirm.disabled = true;
 // Redirecionar para tela inicial
 window.location.reload();
 }, 60000); // 60 segundos de inatividade
}

// Resetar timer a cada interação
document.addEventListener('click', resetInactivityTimer);
document.addEventListener('touchstart', resetInactivityTimer);
resetInactivityTimer();
```

### Mascaramento parcial

Ao exibir o CPF na tela de confirmação, mascare os dígitos centrais: `123.***.***-45`. Isso protege o dado caso alguém esteja observando a tela por cima do ombro do usuário.

### Comunicação segura

Todas as chamadas à API da [**CPFHub.io**](https://www.cpfhub.io/) trafegam exclusivamente via HTTPS, garantindo que o CPF nunca seja transmitido em texto claro. Certifique-se de que o totem não aceita certificados autoassinados e que a chave de API é armazenada de forma segura no dispositivo, preferencialmente em variável de ambiente ou cofre de segredos.

---

## Testes de usabilidade em totens

Antes de colocar o totem em produção, realize testes de usabilidade com usuários reais. Alguns pontos a observar:

- **Tempo médio de conclusão** -- o fluxo completo de digitação e verificação de CPF deve levar no máximo 15 segundos.
- **Taxa de erro** -- quantos usuários erram a digitação na primeira tentativa.
- **Taxa de abandono** -- quantos usuários desistem antes de completar a verificação.
- **Feedback qualitativo** -- pergunte ao usuário se a interface foi clara e fácil de usar.

Utilize ferramentas de analytics embarcadas para coletar essas métricas de forma contínua após o lançamento.

---

## Perguntas frequentes

### O que é necessário para implementar validação de CPF neste contexto?
A validação de CPF exige uma chamada à API com o número do documento e a chave de autenticação. A CPFHub.io retorna o status do CPF, nome do titular e data de nascimento, permitindo a verificação em tempo real durante o cadastro ou transação.

### A API CPFHub.io funciona para todos os volumes de consulta?
Sim. O plano gratuito oferece 50 consultas por mês sem cartão de crédito — ideal para testes e projetos pequenos. Para volumes maiores, o plano Pro inclui 1.000 consultas mensais por R$149. Se o limite for ultrapassado, a API não bloqueia: cobra R$0,15 por consulta adicional.

### Como garantir conformidade com a LGPD ao usar uma API de CPF?
Use o CPF apenas para a finalidade declarada ao titular, armazene apenas o necessário (não guarde o CPF cru se um token bastar), implemente controle de acesso aos logs de consulta e documente a base legal para o tratamento. A [ANPD](https://www.gov.br/anpd/) orienta que dados de identificação devem ser tratados com o princípio da necessidade.

### Quanto tempo leva para integrar a API CPFHub.io?
A integração básica leva menos de 30 minutos: crie uma conta em cpfhub.io, gere a API key no painel e faça uma chamada GET para `https://api.cpfhub.io/cpf/{CPF}` com o header `x-api-key`. A documentação inclui exemplos em Python, Node.js, PHP, Java e outras linguagens.

### Leia também

- [Como pedir CPF no checkout sem espantar o cliente](https://cpfhub.io/blog/como-pedir-cpf-no-checkout-sem-espantar-o-cliente)
- [APIs de validação de CPF melhoram a experiência do usuário](https://cpfhub.io/blog/apis-validacao-cpf-experiencia-usuario)
- [Diferença entre validação de CPF e consulta de CPF: quando usar cada uma](https://cpfhub.io/blog/diferenca-entre-validacao-de-cpf-e-consulta-de-cpf-quando-usar-cada-uma)
- [Onboarding digital em fintechs: como validar CPF em menos de 30 segundos](https://cpfhub.io/blog/onboarding-digital-em-fintechs-como-validar-cpf-em-menos-de-30-segundos)

---

## Conclusão

Projetar a experiência de verificação de CPF em totens de autoatendimento exige atenção a detalhes que não existem no desenvolvimento web tradicional: teclado virtual, tela touch, ambiente público, usuários com diferentes níveis de familiaridade tecnológica. Um bom design nesse contexto prioriza botões grandes, feedback imediato, fluxos curtos e tratamento robusto de erros.

A API da [**CPFHub.io**](https://www.cpfhub.io/) complementa esse design com resposta em ~900ms, alta disponibilidade e integração direta via chamada HTTP — sem dependência de SDKs ou bibliotecas adicionais.

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/) — 50 consultas mensais gratuitas, sem cartão de crédito — e comece hoje mesmo.

