UX de verificação de CPF em chatbots e interfaces conversacionais

Aprenda a projetar fluxos de verificação de CPF em chatbots e interfaces conversacionais, com boas práticas de UX e exemplos de código.

Redação CPFHub.io
Redação CPFHub.io
··11 min de leitura
UX de verificação de CPF em chatbots e interfaces conversacionais

Para criar uma boa UX de verificação de CPF em chatbots, extraia os dígitos de qualquer formato de texto livre, confirme o número com mascaramento parcial antes de consultar a API e limite as tentativas a três antes de escalar para atendimento humano — esse fluxo reduz abandono e protege a privacidade do usuário.

Introdução

Chatbots e interfaces conversacionais são cada vez mais utilizados para atendimento ao cliente, vendas e onboarding. No Brasil, onde o CPF é requisito para inúmeras operações, é comum que o chatbot precise solicitar e verificar esse dado durante a conversa.

Coletar um CPF em uma interface conversacional é fundamentalmente diferente de um formulário web. Não há campo de input com máscara, não há validação visual em tempo real e o usuário pode responder de formas imprevisíveis. Projetar bem esse fluxo faz diferença direta na taxa de conclusão do onboarding.


Desafios de coletar CPF em chatbots

Formatos variados de resposta

O usuário pode responder o CPF de diversas formas:

  • 12345678901 (apenas dígitos)
  • 123.456.789-01 (formatado)
  • 123 456 789 01 (com espaços)
  • meu cpf é 123.456.789-01 (com texto)
  • CPF: 123.456.789-01 (com prefixo)

O chatbot precisa extrair os dígitos de qualquer uma dessas variações.

Privacidade em canais públicos

Em plataformas como WhatsApp e Telegram, a conversa pode ser vista por terceiros em dispositivos compartilhados. O chatbot deve tratar o CPF com cuidado, mascarando-o em confirmações.

Fluxo não linear

Diferente de um formulário, o usuário pode mudar de assunto, fazer perguntas ou se confundir no meio do fluxo. O chatbot precisa lidar com interrupções de forma graciosa.


Extração de CPF de texto livre

A primeira função essencial é extrair o CPF de qualquer formato de mensagem.

function extrairCPF(mensagem) {
    // Remover tudo exceto digitos, pontos, tracos e espacos
    const limpo = mensagem.replace(/[^\d.\-\s]/g, '');

    // Tentar extrair 11 digitos consecutivos (com ou sem formatacao)
    const padroes = [
    /(\d{3})[.\s]?(\d{3})[.\s]?(\d{3})[-.\s]?(\d{2})/,
    /(\d{11})/
    ];

    for (const padrao of padroes) {
    const match = limpo.match(padrao);
    if (match) {
    const digits = match[0].replace(/\D/g, '');
    if (digits.length === 11) return digits;
    }
    }

    return null;
}

// Testes:
// extrairCPF('12345678901') => '12345678901'
// extrairCPF('123.456.789-01') => '12345678901'
// extrairCPF('meu cpf e 123.456.789-01') => '12345678901'
// extrairCPF('CPF: 123 456 789 01') => '12345678901'
// extrairCPF('ola, tudo bem?') => null

Máquina de estados do fluxo conversacional

O fluxo de verificação de CPF no chatbot pode ser modelado como uma máquina de estados finitos.

class FluxoCPF {
    constructor(apiKey) {
    this.apiKey = apiKey;
    this.estado = 'AGUARDANDO_CPF';
    this.tentativas = 0;
    this.maxTentativas = 3;
    this.cpfExtraido = null;
    this.dadosCPF = null;
    }

    async processarMensagem(mensagem) {
    switch (this.estado) {
    case 'AGUARDANDO_CPF':
    return this.handleAguardandoCPF(mensagem);

    case 'CONFIRMANDO_CPF':
    return this.handleConfirmandoCPF(mensagem);

    case 'CONCLUIDO':
    return { texto: 'Seu CPF ja foi verificado. Como posso ajudar?', fim: true };

    case 'FALHA':
    return { texto: 'Nao consegui verificar seu CPF. Deseja tentar novamente?', fim: false };

    default:
    return { texto: 'Desculpe, algo deu errado. Vamos comecar de novo.', fim: false };
    }
    }

    async handleAguardandoCPF(mensagem) {
    const cpf = extrairCPF(mensagem);

    if (!cpf) {
    this.tentativas++;
    if (this.tentativas >= this.maxTentativas) {
    this.estado = 'FALHA';
    return {
    texto: 'Nao consegui identificar um CPF na sua mensagem. ' +
    'Por favor, entre em contato com nosso atendimento humano.',
    fim: true
    };
    }
    return {
    texto: 'Nao encontrei um CPF na sua mensagem. ' +
    'Por favor, envie apenas os 11 digitos do seu CPF.',
    fim: false
    };
    }

    if (!validarDigitosCPF(cpf)) {
    return {
    texto: 'O CPF informado parece estar incorreto. ' +
    'Verifique os numeros e envie novamente.',
    fim: false
    };
    }

    this.cpfExtraido = cpf;
    const mascarado = `${cpf.slice(0, 3)}.***.***-${cpf.slice(9)}`;

    this.estado = 'CONFIRMANDO_CPF';
    return {
    texto: `Identifiquei o CPF ${mascarado}. Esta correto? Responda "sim" ou "nao".`,
    fim: false
    };
    }

    async handleConfirmandoCPF(mensagem) {
    const resposta = mensagem.toLowerCase().trim();

    if (resposta === 'nao' || resposta === 'não' || resposta === 'n') {
    this.estado = 'AGUARDANDO_CPF';
    this.cpfExtraido = null;
    this.tentativas = 0;
    return {
    texto: 'Sem problema. Por favor, envie o CPF correto.',
    fim: false
    };
    }

    if (resposta === 'sim' || resposta === 's' || resposta === 'yes') {
    return this.consultarAPI();
    }

    return {
    texto: 'Nao entendi. O CPF esta correto? Responda "sim" ou "nao".',
    fim: false
    };
    }

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

    try {
    const res = await fetch(`https://api.cpfhub.io/cpf/${this.cpfExtraido}`, {
    headers: {
    'x-api-key': this.apiKey,
    'Accept': 'application/json'
    },
    signal: controller.signal
    });
    clearTimeout(timeoutId);
    const json = await res.json();

    if (json.success) {
    this.dadosCPF = json.data;
    this.estado = 'CONCLUIDO';
    const primeiroNome = json.data.name.split(' ')[0];
    return {
    texto: `CPF verificado com sucesso! Ola, ${primeiroNome}. Como posso ajudar?`,
    dados: json.data,
    fim: true
    };
    } else {
    this.estado = 'AGUARDANDO_CPF';
    return {
    texto: 'O CPF informado nao foi encontrado na base. ' +
    'Verifique os numeros e envie novamente.',
    fim: false
    };
    }
    } catch (err) {
    clearTimeout(timeoutId);
    this.estado = 'AGUARDANDO_CPF';
    return {
    texto: 'Estou com dificuldade para verificar seu CPF no momento. ' +
    'Pode tentar novamente em alguns instantes?',
    fim: false
    };
    }
    }
}

function validarDigitosCPF(cpf) {
    if (cpf.length !== 11 || /^(\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]);
}

Interface de chat com widget de CPF

Para melhorar a experiência, o chatbot pode exibir um widget dedicado de input de CPF em vez de depender apenas de texto livre.

<div class="chat-container" id="chatContainer">
    <div class="chat-messages" id="chatMessages"></div>

    <div class="chat-input-area" id="inputArea">
    <input type="text" id="chatInput" placeholder="Digite sua mensagem..." />
    <button onclick="enviarMensagem()">Enviar</button>
    </div>

    <div class="cpf-widget" id="cpfWidget" style="display: none;">
    <p>Digite seu CPF:</p>
    <input
    type="text"
    id="cpfWidgetInput"
    inputmode="numeric"
    placeholder="000.000.000-00"
    maxlength="14"
    />
    <button onclick="enviarCPFWidget()">Verificar</button>
    <button class="btn-secondary" onclick="fecharWidget()">Digitar no chat</button>
    </div>
</div>

<style>
    .chat-container {
    max-width: 420px;
    margin: 20px auto;
    border: 1px solid #ddd;
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    height: 600px;
    }
    .chat-messages {
    flex: 1;
    padding: 16px;
    overflow-y: auto;
    background: #f8f9fa;
    }
    .msg {
    max-width: 80%;
    padding: 10px 14px;
    border-radius: 12px;
    margin-bottom: 8px;
    font-size: 0.95rem;
    line-height: 1.4;
    }
    .msg-bot {
    background: #fff;
    border: 1px solid #e0e0e0;
    align-self: flex-start;
    }
    .msg-user {
    background: #3498db;
    color: #fff;
    margin-left: auto;
    }
    .chat-input-area {
    display: flex;
    padding: 12px;
    border-top: 1px solid #ddd;
    gap: 8px;
    }
    .chat-input-area input {
    flex: 1;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 8px;
    outline: none;
    }
    .chat-input-area button {
    padding: 10px 16px;
    background: #3498db;
    color: #fff;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    }
    .cpf-widget {
    padding: 16px;
    background: #eef6ff;
    border-top: 1px solid #b3d4fc;
    text-align: center;
    }
    .cpf-widget input {
    display: block;
    width: 100%;
    padding: 12px;
    font-size: 1.2rem;
    text-align: center;
    letter-spacing: 2px;
    border: 2px solid #3498db;
    border-radius: 8px;
    margin: 8px 0;
    outline: none;
    }
    .cpf-widget button {
    padding: 10px 20px;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    margin: 4px;
    }
    .cpf-widget button:first-of-type {
    background: #3498db;
    color: #fff;
    }
    .btn-secondary {
    background: transparent;
    color: #666;
    text-decoration: underline;
    }
</style>

Boas práticas de UX conversacional para CPF

1. Solicite o CPF com contexto

Em vez de simplesmente perguntar "Qual é o seu CPF?", explique por que precisa do dado:

  • "Para localizar seu pedido, preciso do seu CPF. Pode me informar?"
  • "Vou verificar seu cadastro. Qual o CPF do titular?"

2. Confirme antes de consultar

Sempre confirme o CPF com o usuário antes de fazer a consulta na API. Exiba o CPF parcialmente mascarado para proteger a privacidade.

3. Limite as tentativas

Após 3 tentativas falhas, direcione para atendimento humano. Insistir além disso gera frustração e aumenta o abandono do fluxo.

4. Aceite voz em chatbots de voz

Para interfaces de voz (IVR, Alexa, Google Assistant), aceite o CPF dígito por dígito e repita para confirmação: "Entendi 1-2-3-4-5-6-7-8-9-0-1. Está correto?"

5. Não armazene no histórico

Em plataformas como WhatsApp Business, o CPF fica visível no histórico de conversas. Oriente o usuário a apagar a mensagem após a verificação ou use input widgets que não ficam no histórico. As diretrizes de privacidade da ANPD recomendam minimizar a exposição de dados pessoais em canais de comunicação.


Integração com WhatsApp Business API

Um exemplo simplificado de webhook para processar mensagens do WhatsApp com verificação de CPF.

// webhook-whatsapp.js (Node.js/Express)
const express = require('express');
const app = express();
app.use(express.json());

const sessoes = new Map();

app.post('/webhook', async (req, res) => {
    const { from, body } = req.body.message;

    if (!sessoes.has(from)) {
    sessoes.set(from, new FluxoCPF(process.env.CPFHUB_API_KEY));
    }

    const fluxo = sessoes.get(from);
    const resultado = await fluxo.processarMensagem(body);

    // Enviar resposta via WhatsApp API
    await enviarMensagemWhatsApp(from, resultado.texto);

    if (resultado.fim) {
    // Limpar sessao apos 5 minutos
    setTimeout(() => sessoes.delete(from), 5 * 60 * 1000);
    }

    res.sendStatus(200);
});

async function enviarMensagemWhatsApp(para, texto) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 10000);

    try {
    await fetch('https://graph.facebook.com/v18.0/PHONE_ID/messages', {
    method: 'POST',
    headers: {
    'Authorization': `Bearer ${process.env.WHATSAPP_TOKEN}`,
    'Content-Type': 'application/json'
    },
    body: JSON.stringify({
    messaging_product: 'whatsapp',
    to: para,
    text: { body: texto }
    }),
    signal: controller.signal
    });
    clearTimeout(timeoutId);
    } catch (err) {
    clearTimeout(timeoutId);
    console.error('Erro ao enviar mensagem:', err);
    }
}

app.listen(3000);

Métricas para chatbots com verificação de CPF

Monitore as seguintes métricas para avaliar a eficácia do fluxo:

  • Taxa de extração bem-sucedida — percentual de mensagens em que o CPF foi identificado corretamente na primeira tentativa.
  • Número médio de turnos — quantas mensagens são trocadas até a verificação ser concluída. O ideal é 3 (pedido + resposta + confirmação).
  • Taxa de fallback para atendimento humano — quantos usuários não conseguem completar o fluxo e são encaminhados a um atendente.
  • Tempo total do fluxo — desde a solicitação do CPF até a verificação concluída.

Perguntas frequentes

Como extrair o CPF de mensagens em formato livre no chatbot?

Use uma função que remove tudo exceto dígitos, pontos, traços e espaços da mensagem, depois tenta casar os 11 dígitos com um padrão regex. Isso cobre formatos com e sem pontuação, com prefixos como "CPF:" e até com texto ao redor. Se a extração falhar após 3 tentativas, escale para atendimento humano.

Qual o impacto da latência da API na experiência conversacional?

A API CPFHub.io responde em aproximadamente 900ms. Para chatbots, isso é confortável: o bot pode exibir uma mensagem de "aguarde" enquanto a consulta é processada. Configure o timeout do seu servidor para 10 segundos — suficiente para acomodar variações de rede sem travar a sessão do usuário.

Como lidar com o CPF do usuário em canais públicos como WhatsApp?

Exiba o CPF parcialmente mascarado na confirmação (ex: 123.***.***-01), nunca repita o número completo em texto. Oriente o usuário a apagar a mensagem após a verificação. Para máxima privacidade, use widgets de input dedicados que não ficam no histórico de chat, quando a plataforma suportar.

A verificação de CPF em chatbots é compatível com a LGPD?

Sim, desde que você informe ao usuário a finalidade da coleta antes de pedir o CPF, não armazene o dado além do necessário para a operação, e documente a base legal para o tratamento. O consentimento pode ser obtido no início do fluxo conversacional com uma mensagem clara antes de solicitar o número.


Conclusão

A verificação de CPF em chatbots exige uma abordagem diferente da web tradicional. A extração de CPF de texto livre, a confirmação com mascaramento, o limite de tentativas e a escalação para atendimento humano são elementos essenciais para uma boa experiência conversacional — e para manter as taxas de conclusão do fluxo em níveis saudáveis.

A API da CPFHub.io se encaixa diretamente nesse fluxo: responde em ~900ms, retorna nome e data de nascimento do titular e não bloqueia ao atingir o limite do plano — cobra apenas R$0,15 por consulta extra. Comece com 50 consultas gratuitas por mês, sem cartão de crédito, 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.

Redação CPFHub.io

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.

WhatsAppFale conosco via WhatsApp