Em produção · 99,9% uptime v2.0

Bloqueie os bots.
Sem que seus
usuários percebam.

Um checkbox. Zero chaves API. Zero tracking. Seus usuários marcam e seguem. Os bots batem em um muro criptográfico que seu servidor valida em uma única linha de código.

100% self-hosted Zero cookies Zero rastreamento Sem limites
demo.html — Teste agora
Marque o checkbox. Zero CPU até fazê-lo.
0
Challenges issued today
0
Verified
0
Tokens consumed
0€
Cost per use
Como funciona

Invisível para humanos.
Impossível para bots.

Três passos. Nem um a mais. Sem bibliotecas pré-carregadas, sem scripts de terceiros, sem chaves para rotacionar.

01

O usuário marca um checkbox

Até esse clique, o mCaptcha dorme. Nenhum fetch, ciclo de CPU ou requisição DNS. Seu Lighthouse nem sabe que ele existe.

02

Desafio criptográfico em ~50 ms

O navegador resolve um Proof-of-Work SHA-256. Se o IP disparou >30 desafios em uma hora, passamos a um puzzle deslizante que nenhum bot atravessa sem tempo humano real.

03

Seu backend recebe um token

Um GET para /api/captcha/verify com o token. Se ok=true, é humano e você processa o form. Uso único, validade 2 min. Uma linha em qualquer linguagem.

Comparação

Mesmo objetivo.
Melhores consequências.

Tudo o que o reCAPTCHA faz por você, o mCaptcha também faz. O que o reCAPTCHA faz aos seus usuários, não.

Google reCAPTCHA
mCaptcha Recomendado
Sem cadastro nem chaves API
Zero rastreamento do usuário
Zero cookies de terceiros
Zero CPU até a primeira interação
100% self-hosted (sem dependência externa)
Compatível com código reCAPTCHA existente
Verificações ilimitadas e grátis
Configuração CSP simples
Complexa
Mínima
Tamanho do widget (gzipped)
~150 KB
~6 KB
Instalação

Duas linhas. Pronto.

Sem npm install. Sem dashboard para se cadastrar. Sem chaves para copiar. Cole o snippet, faça deploy, feche o ticket.

HTML
<form action="/contact" method="POST">
    <input name="email" required>
    <textarea name="message" required></textarea>

    <div class="mcaptcha"></div>

    <button type="submit">Enviar</button>
</form>

<script src="https://medel.es/captcha.js" async defer></script>
Zero impacto na primeira pintura O script carrega com async defer. Nada executa até o usuário marcar. Seus Core Web Vitals agradecem.
Claro, escuro ou automático Segue por padrão o prefers-color-scheme do navegador. Force com data-theme="dark|light" no div do widget.
Drop-in para código reCAPTCHA Aceita class="g-recaptcha" e preenche g-recaptcha-response. Migre sem tocar uma única linha do seu backend.
Mobile e touch nativos O slider puzzle responde a dedos como controle nativo. Sem seletores obscuros de bicicletas em telas de 4 polegadas.
Verificação

Antes de processar o formulário,
valide o token.

Seu backend recebe mcaptcha_token. Faz um GET, verifica se ok=true e segue. Cinco linguagens, mesmo fluxo, zero bibliotecas para instalar.

<?php
function mcaptcha($token) {
    $url = 'https://medel.es/api/captcha/verify?token=' . urlencode($token);
    $response = json_decode(file_get_contents($url));
    return $response->ok ?? false;
}

// Uso:
$token = $_POST['mcaptcha_token'] ?? '';

if (!mcaptcha($token)) {
    http_response_code(400);
    exit('Captcha falhou');
}

// ✅ Captcha verificado. Processe o formulário.
// Validação no cliente — útil em SPAs antes de enviar ao backend.
// Para proteção real, verifique SEMPRE também no servidor.
async function mcaptcha(token) {
    const url = 'https://medel.es/api/captcha/verify?token=' + encodeURIComponent(token);
    const data = await fetch(url).then(r => r.json());
    return data.ok === true;
}

// Uso em um formulário:
document.querySelector('form').addEventListener('submit', async (e) => {
    e.preventDefault();
    const fd = new FormData(e.target);
    const token = fd.get('mcaptcha_token');

    if (!(await mcaptcha(token))) {
        alert('Captcha falhou');
        return;
    }

    // ✅ Captcha verificado. Envie ao backend.
    await fetch('/api/contact', { method: 'POST', body: fd });
});
async function mcaptcha(token) {
    const url = 'https://medel.es/api/captcha/verify?token=' + encodeURIComponent(token);
    const data = await fetch(url).then(r => r.json());
    return data.ok === true;
}

// Uso (Express):
const token = req.body.mcaptcha_token;

if (!(await mcaptcha(token))) {
    return res.status(400).send('Captcha falhou');
}

// ✅ Captcha verificado. Processe o formulário.
import urllib.request, urllib.parse, json

def mcaptcha(token):
    url = 'https://medel.es/api/captcha/verify?' + urllib.parse.urlencode({'token': token})
    with urllib.request.urlopen(url, timeout=5) as r:
        return json.loads(r.read()).get('ok') is True

# Uso (Flask):
token = request.form.get('mcaptcha_token', '')

if not mcaptcha(token):
    abort(400, 'Captcha falhou')

# ✅ Captcha verificado. Processe o formulário.
# Você só precisa de um GET com o token como query param:
curl 'https://medel.es/api/captcha/verify?token=YOUR_TOKEN'

# OK:   {"ok":true,"verified_at":"2026-06-22 12:24:56"}
# FALHA: {"ok":false,"error":"already_used"}
Migrando do Google reCAPTCHA?

O widget também preenche g-recaptcha-response e aceita class="g-recaptcha". Se seu backend já lê, mude apenas a URL de verify:

// Antes:
$url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret . '&response=' . $token;

// Depois (sem secret):
$url = 'https://medel.es/api/captcha/verify?response=' . $token;
API

Endpoints

Quatro endpoints REST. Sem SDK. Sem auth. Sem versionamento. Apenas o que você precisa — o widget chama os demais.

GET https://medel.es/api/captcha/verify?token=… Você chama

Verifica o token. Uso único: invalidado após o primeiro verify bem-sucedido, impossível replay.

200 OK:
{"ok": true, "verified_at": "2026-06-22 12:24:56"}
400 KO:
{"ok": false, "error": "already_used"}

Códigos: missing_token · unknown_token · already_used · expired · origin_mismatch

GET https://medel.es/api/captcha/challenge Chamado pelo widget

Emite um desafio (PoW por padrão, slider puzzle se o IP for suspeito). O widget chama sozinho.

POST https://medel.es/api/captcha/solve Chamado pelo widget

O widget envia a solução (nonce do PoW ou posição X do slider) e recebe o token verificável.

GET https://medel.es/api/captcha/stats Público

Estatísticas agregadas do dia. Zero dados pessoais, zero IPs, zero tracking.

Compatibilidade

Funciona em 98%
sem configurar nada.

Funciona automaticamente em

  • Sites HTTPS
  • Chrome / Edge / Firefox / Safari (2017+)
  • localhost em desenvolvimento
  • SPA (React / Vue / Svelte)
  • Formulários server-rendered

Se você tem CSP estrita

Adicione o domínio a 3 diretivas:

script-src  'self' https://medel.es;
connect-src 'self' https://medel.es;
style-src   'self' https://medel.es;
FAQ

Perguntas honestas, respostas honestas

Quando aparece o slider puzzle?
Só se o seu IP disparou mais de 30 verificações na última hora. Para 99% dos seus usuários, o fluxo termina em um único clique.
É grátis para sempre?
Sim. Sem cartão, sem plano, sem upsell. O serviço se sustenta com rate-limit por IP (100/h) e por domínio (5000/h). Precisa de mais? Escreva e a gente aumenta.
Funciona sem JavaScript?
Não. O mCaptcha precisa de JS para resolver o Proof-of-Work ou arrastar o slider. Se espera tráfego sem JS, deixe um honeypot HTML como fallback.
Faz tracking dos meus usuários?
Não. Zero cookies, zero fingerprinting, zero analytics. Só guardamos o IP por 24h para rate-limit, depois apaga sozinho.
Por que slider em vez de "selecione os semáforos"?
CAPTCHAs de grade de imagens precisam de um dataset enorme rotulado e ML por cima. Um slider é visualmente equivalente, não precisa de banco de fotos e funciona em qualquer dispositivo — até no celular mais antigo.
E se o Medel Captcha cair?
O widget mostra erro e bloqueia o envio por padrão. Como integrador, você pode decidir bypass se o verify der timeout (5 segundos sobra). 99,9% de uptime, mas o plano B é seu.
É compatível com reCAPTCHA?
Sim. O widget preenche automaticamente g-recaptcha-response e aceita class="g-recaptcha". Migrar é trocar o src do script e a URL de verify. Zero refactor.
Como faço self-host?
É PHP 8.2+ com MySQL. O código vai pro GitHub com licença MIT assim que eu limpar. Por enquanto, escreva e te envio.

Cole o snippet.
Esqueça os bots.

Integre em 30 segundos. Sem cartão. Sem chaves. Sem contratos. Sem letras miúdas. Quando um bot tentar entrar, vira problema dele, não seu.