Honeypots Ainda Funcionam: 3 Formas de Parar Spam em Cadastros Sem CAPTCHAs
Semana passada, notei algo suspeito nos cadastros da minha lista de espera do SEO Friend. Dezenas de enderecos de email de dominios descartaveis, todos enviados em milissegundos um do outro, originando de enderecos IP na Russia e Holanda. Comportamento classico de bot farm.
A solucao obvia? Colocar um CAPTCHA no formulario. Mas CAPTCHAs sao irritantes. Eles frustram usuarios reais, prejudicam taxas de conversao e honestamente—bots modernos estao ficando bem bons em resolve-los de qualquer forma. Eu queria algo invisivel para humanos mas mortal para bots.
Entre o honeypot.
O Que e um Honeypot?
Um honeypot e uma armadilha projetada para capturar sistemas automatizados explorando seu comportamento previsivel. Em seguranca web, um honeypot de formulario funciona em um principio simples: bots preenchem automaticamente todos os campos de formulario que encontram, enquanto humanos so preenchem os campos que podem ver.
Se voce adicionar um campo oculto que humanos nao podem ver, e esse campo for preenchido—voce pegou um bot.
E uma tecnica antiga, mas ainda funciona notavelmente bem em 2025. Combinada com verificacoes de timing, voce pode parar a vasta maioria de cadastros spam sem nenhuma friccao para o usuario.
O Problema: Cadastros de Bot Farm
Antes de implementar meu honeypot, aqui esta o que eu estava enfrentando. IPs de data centers na Russia, Holanda e Alemanha estavam atingindo meu formulario de lista de espera. Os envios vinham em velocidade inumana—0.2 a 0.5 segundos apos a pagina carregar. Os enderecos de email eram todos de dominios descartaveis como tempmail e guerrillamail. E eles estavam preenchendo todos os campos de formulario que podiam encontrar, o que seria sua ruina.
Por que bots fazem isso? Eles estao colhendo sistemas de email—enviando formularios para ver se emails de confirmacao voltam, validando que seu pipeline de email funciona. Eles estao poluindo bancos de dados com dados lixo para desperdicar seu tempo e cota de email. Eles estao testando enderecos de email para ataques de credential stuffing depois. As vezes e sabotagem de concorrentes—inflando suas metricas com dados lixo para que voce nao possa confiar nos seus numeros.
Os bots vinham dos mesmos blocos de IP /24, enviando em fracoes de segundo e usando emails descartaveis obvios. Candidatos perfeitos para deteccao honeypot.
Exemplo 1: A Armadilha de Campo Oculto
Esta e a tecnica classica de honeypot que tem parado bots desde o inicio dos anos 2000. O conceito e lindamente simples: adicione um campo de formulario que e invisivel para humanos mas visivel para bots. Quando um bot preenche automaticamente todos os campos na pagina (o que eles sempre fazem), eles preencherao seu campo oculto tambem—e voce os pegou.
Aqui esta o HTML que voce adicionara ao seu formulario, junto com seu campo de email real:
<form id="waitlist-form" action="/api/signup" method="POST">
<!-- O campo real que humanos preenchem -->
<label for="email">Endereco de Email</label>
<input type="email" id="email" name="email" required>
<!-- O campo honeypot - completamente invisivel para humanos -->
<input
type="text"
name="website"
style="position:absolute;left:-9999px"
tabindex="-1"
autocomplete="off"
aria-hidden="true"
>
<button type="submit">Entrar na Lista</button>
</form>Cada atributo naquele campo honeypot serve um proposito especifico. O type="text" faz parecer um campo de texto normal para qualquer bot parseando seu HTML. O name="website" e deliberadamente inofensivo—bots sao programados para preencher campos comuns como "website", "url", "company" e "phone", entao usar um desses nomes garante que eles mordam a isca. Evite nomes obvios como "honeypot" ou "trap" porque alguns bots sofisticados procuram esses padroes.
O style="position:absolute;left:-9999px" e a chave para a invisibilidade. Posicionando o elemento 9999 pixels para fora do lado esquerdo da tela, nenhum humano jamais o vera, mas bots parseando o DOM o encontrarao numa boa. O tabindex="-1" impede usuarios de teclado de acidentalmente navegar para o campo ao percorrer seu formulario. O autocomplete="off" para o preenchimento automatico do navegador de toca-lo—voce nao quer o Chrome preenchendo seu honeypot com dados salvos de um usuario legitimo. Finalmente, aria-hidden="true" diz aos leitores de tela para ignorar este campo completamente, mantendo acessibilidade para usuarios com deficiencia visual.
No servidor, a verificacao e trivial. Se o campo website contem qualquer valor, voce pegou um bot:
app.post('/api/signup', async (c) => {
const { email, website } = await c.req.parseBody();
// Se o campo honeypot tem qualquer valor, um bot preencheu
if (website) {
console.log('Bot detectado via honeypot:', email);
// Retorna sucesso falso - o bot acha que funcionou
return c.json({
success: true,
message: 'Obrigado por se cadastrar!'
});
}
// Humano real - processa normalmente
await saveToDatabase(email);
return c.json({ success: true, message: 'Bem-vindo!' });
});O detalhe critico aqui: retorne uma resposta de sucesso falso em vez de um erro. Se voce retornar uma mensagem de erro, bots sofisticados podem detectar que foram pegos e tentar abordagens diferentes—talvez pulando campos, talvez usando um IP diferente. Retornando sucesso, o operador do bot ve checkmarks verdes nos logs e segue para alvos mais faceis. Seu banco de dados fica limpo, e eles nunca sabem o que os atingiu.
Exemplo 2: A Verificacao de Timing
Humanos levam tempo para ler uma pagina e preencher um formulario. Ate o digitador mais rapido precisa de varios segundos para escanear o formulario, clicar no campo de email, digitar seu endereco e clicar em enviar. Uma pessoa real simplesmente nao pode carregar uma pagina e enviar um formulario em 300 milissegundos.
Bots podem. E fazem, constantemente.
Esta tecnica honeypot mede o tempo entre carregamento da pagina e envio do formulario. Qualquer coisa abaixo de 3 segundos e quase certamente automatizado.
Primeiro, adicione um campo oculto ao seu formulario que armazenara o timestamp de carregamento da pagina:
<form id="waitlist-form" action="/api/signup" method="POST">
<label for="email">Endereco de Email</label>
<input type="email" id="email" name="email" required>
<!-- Campo de verificacao de timing - captura quando a pagina carregou -->
<input type="hidden" name="loadedAt" id="loadedAtField">
<button type="submit">Entrar na Lista</button>
</form>
<script>
// Assim que a pagina carrega, registra o timestamp
document.getElementById('loadedAtField').value = Date.now();
</script>Quando a pagina carrega, JavaScript imediatamente define o valor do campo oculto para o timestamp Unix atual em milissegundos. Este valor e enviado junto com o resto dos dados do formulario. O usuario nunca o ve, nunca interage com ele—e completamente invisivel.
No servidor, voce compara o tempo de envio com o tempo de carregamento:
app.post('/api/signup', async (c) => {
const { email, loadedAt } = await c.req.parseBody();
// Calcula quanto tempo o usuario levou para enviar
if (loadedAt) {
const elapsed = Date.now() - parseInt(loadedAt, 10);
// Menos de 3 segundos? Nenhum humano digita tao rapido.
if (elapsed < 3000) {
console.log(`Bot detectado: enviou em ${elapsed}ms`);
// Retorna erro de rate limit - um pouco mais plausivel
return c.json({
error: 'Por favor espere um momento antes de enviar.'
}, 429);
}
}
// Levou um tempo razoavel - provavelmente humano
await saveToDatabase(email);
return c.json({ success: true, message: 'Bem-vindo!' });
});Uso 3 segundos (3000 milissegundos) como limite. Em testes, descobri que mesmo usuarios rapidos com preenchimento automatico habilitado levam pelo menos 4-5 segundos para enviar. Os bots mais lentos que peguei estavam em torno de 800 milissegundos. Tres segundos da margem confortavel para ambos.
Exemplo 3: O Sistema Completo de Duas Partes
Na pratica, voce quer ambas as tecnicas funcionando juntas. O campo oculto pega bots que preenchem formularios automaticamente. A verificacao de timing pega bots que tentam ser espertos e pulam campos ocultos. Juntos, formam uma barreira quase impenetravel contra envios automatizados.
Aqui esta a implementacao completa que estou rodando no SEO Friend:
<!DOCTYPE html>
<html lang="pt">
<head>
<meta charset="UTF-8">
<title>Entre na Lista de Espera</title>
</head>
<body>
<form id="waitlist-form">
<div class="form-group">
<label for="email">Endereco de Email</label>
<input
type="email"
id="email"
name="email"
required
placeholder="voce@exemplo.com"
>
</div>
<!-- HONEYPOT 1: Armadilha de campo oculto -->
<!-- Bots preenchem isso automaticamente; humanos nunca veem -->
<input
type="text"
name="website"
style="position:absolute;left:-9999px"
tabindex="-1"
autocomplete="off"
aria-hidden="true"
>
<!-- HONEYPOT 2: Verificacao de timing -->
<!-- Registra tempo de carregamento da pagina para validacao de velocidade -->
<input type="hidden" name="loadedAt" id="loadedAt">
<button type="submit">Entrar na Lista</button>
</form>
<script>
// Define o timestamp assim que a pagina carrega
document.getElementById('loadedAt').value = Date.now();
document.getElementById('waitlist-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const response = await fetch('/api/signup', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.success) {
alert('Obrigado por entrar na lista de espera!');
} else {
alert(result.error || 'Algo deu errado.');
}
});
</script>
</body>
</html>Resultados
Apos implementar este sistema honeypot de duas partes, cadastros spam cairam de 20-50 por dia para essencialmente zero. Os bots ainda estao tentando—eu os vejo nos logs do servidor—mas todos sao pegos e alimentados com respostas de sucesso falso. Eles acham que estao vencendo. Meu banco de dados fica limpo.
Usuarios reais nao notaram nada. Nao ha CAPTCHA para resolver, nenhuma friccao adicionada ao fluxo de cadastro. Eles preenchem o email, clicam em enviar e pronto. As verificacoes honeypot acontecem invisivelmente em segundo plano.
A implementacao levou cerca de 30 minutos—a maior parte foi configurando o logging para que eu pudesse monitorar o que estava sendo bloqueado. Nao ha manutencao continua, nenhuma taxa mensal para servicos anti-spam, nenhuma chave de API para gerenciar.
As vezes as solucoes mais simples sao as melhores. Honeypots existem ha decadas porque funcionam. Em uma era de IA e machine learning cada vez mais sofisticados, ha algo satisfatorio em parar bots com um campo de texto oculto e um timestamp.
Perguntas Frequentes
Honeypots funcionam contra todos os bots?
Nao. Bots sofisticados projetados especificamente para contornar honeypots podem pular campos ocultos ou adicionar delays artificiais. Porem, esses sao raros. A vasta maioria dos bots sao scrapers simples que preenchem tudo automaticamente e enviam imediatamente. Honeypots pegam 95%+ do spam automatizado, o que geralmente e suficiente para tornar seu problema de spam gerenciavel.
Isso vai quebrar acessibilidade?
Nao se implementado corretamente. O atributo aria-hidden="true" diz aos leitores de tela para ignorar o campo honeypot completamente, entao usuarios com deficiencia visual nao serao confundidos por um campo com o qual nao podem interagir. O tabindex="-1" impede usuarios de teclado de navegar para ele. Usuarios navegando com tecnologia assistiva vao experimentar o formulario exatamente como pretendido.
E se um usuario legitimo de alguma forma preencher o honeypot?
Isso e quase impossivel com implementacao adequada. O campo esta posicionado 9999 pixels para fora da borda esquerda da tela—usuarios literalmente nao podem ve-lo ou clicar nele. Preenchimento automatico do navegador esta desabilitado com autocomplete="off". Em duas semanas de uso em producao com milhares de visitantes, tive zero falsos positivos.
Devo usar CAPTCHA em vez disso?
CAPTCHAs adicionam friccao. Estudos mostram que podem reduzir taxas de conversao em 3-8%. Usuarios odeiam—eu odeio. Honeypots sao invisiveis; usuarios nem sabem que existem. Comece com honeypots. So adicione CAPTCHAs se voce ainda estiver recebendo spam significativo apos implementar protecao honeypot adequada, o que e improvavel para a maioria dos sites.
Fred
AUTHORFull-stack developer with 10+ years building production applications. I've built frontends that users actually enjoy using (and that don't break in IE).
Need a developer who gets it?
POC builds, vibe-coded fixes, and real engineering. Let's talk.
Hire Me →
