Bloquez les bots.
Sans que vos
utilisateurs s'en aperçoivent.
Une case. Zéro clé API. Zéro tracking. Vos utilisateurs cochent et continuent. Les bots se heurtent à un mur cryptographique que votre serveur valide en une seule ligne de code.
Invisible pour les humains.
Impossible pour les bots.
Trois étapes. Pas une de plus. Aucune librairie chargée à l'avance, aucun script tiers, aucune clé à renouveler.
L'utilisateur coche une case
Jusqu'à ce clic, mCaptcha dort. Pas un seul fetch, ni un cycle CPU, ni une requête DNS. Votre Lighthouse ne sait même pas qu'il existe.
Défi cryptographique en ~50 ms
Le navigateur résout un Proof-of-Work SHA-256. Si l'IP a déclenché >30 défis en une heure, on passe à un puzzle à glisser qu'aucun bot ne franchit sans temps humain réel.
Votre backend reçoit un token
Un GET vers /api/captcha/verify avec le token. Si ok=true, c'est un humain et vous traitez le formulaire. Usage unique, durée 2 min. Une ligne dans n'importe quel langage.
Même objectif.
Meilleures conséquences.
Tout ce que reCAPTCHA fait pour vous, mCaptcha le fait aussi. Ce que reCAPTCHA fait à vos utilisateurs, non.
Deux lignes. Terminé.
Pas de npm install. Aucun dashboard où s'inscrire. Aucune clé à copier. Collez le snippet, déployez, fermez le ticket.
<form action="/contact" method="POST">
<input name="email" required>
<textarea name="message" required></textarea>
<div class="mcaptcha"></div>
<button type="submit">Envoyer</button>
</form>
<script src="https://medel.es/captcha.js" async defer></script>
Avant de traiter le formulaire,
validez le token.
Votre backend reçoit mcaptcha_token. Il fait un GET, vérifie ok=true et continue. Cinq langages, un seul flux, zéro librairie à installer.
<?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;
}
// Utilisation :
$token = $_POST['mcaptcha_token'] ?? '';
if (!mcaptcha($token)) {
http_response_code(400);
exit('Captcha échoué');
}
// ✅ Captcha vérifié. Traitez le formulaire.
// Validation côté client — utile dans les SPA avant l'envoi au backend.
// Pour une vraie protection, vérifiez TOUJOURS aussi côté serveur.
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;
}
// Utilisation dans un formulaire :
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 échoué');
return;
}
// ✅ Captcha vérifié. Envoyez au 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;
}
// Utilisation (Express) :
const token = req.body.mcaptcha_token;
if (!(await mcaptcha(token))) {
return res.status(400).send('Captcha échoué');
}
// ✅ Captcha vérifié. Traitez le formulaire.
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
# Utilisation (Flask) :
token = request.form.get('mcaptcha_token', '')
if not mcaptcha(token):
abort(400, 'Captcha échoué')
# ✅ Captcha vérifié. Traitez le formulaire.
# Il suffit d'un GET avec le token en paramètre :
curl 'https://medel.es/api/captcha/verify?token=YOUR_TOKEN'
# OK : {"ok":true,"verified_at":"2026-06-22 12:24:56"}
# ÉCHEC : {"ok":false,"error":"already_used"}
Vous migrez depuis Google reCAPTCHA ?
Le widget remplit aussi g-recaptcha-response et accepte class="g-recaptcha". Si votre backend le lit déjà, changez juste l'URL de verify :
// Avant : $url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret . '&response=' . $token; // Après (sans secret) : $url = 'https://medel.es/api/captcha/verify?response=' . $token;
Endpoints
Quatre endpoints REST. Pas de SDK. Pas d'auth. Pas de versioning. Seulement celui dont vous avez besoin — le widget appelle les autres.
GET
https://medel.es/api/captcha/verify?token=…
Vous l'appelez
Vérifie le token. Usage unique : invalidé après le premier verify réussi, impossible de rejouer.
200 OK:{"ok": true, "verified_at": "2026-06-22 12:24:56"}
400 KO:
{"ok": false, "error": "already_used"}
Codes : missing_token · unknown_token · already_used · expired · origin_mismatch
GET
https://medel.es/api/captcha/challenge
Appelé par le widget
Émet un défi (PoW par défaut, puzzle si l'IP est suspecte). Le widget l'appelle automatiquement.
POST
https://medel.es/api/captcha/solve
Appelé par le widget
Le widget envoie la solution (nonce du PoW ou position X du slider) et reçoit le token vérifiable.
GET
https://medel.es/api/captcha/stats
Public
Statistiques agrégées du jour. Zéro donnée personnelle, zéro IP, zéro tracking.
Fonctionne sur 98 %
sans rien configurer.
Fonctionne automatiquement sur
- Sites HTTPS
- Chrome / Edge / Firefox / Safari (2017+)
- localhost en développement
- SPA (React / Vue / Svelte)
- Formulaires server-rendered
Si vous avez une CSP stricte
Ajoutez le domaine à 3 directives :
script-src 'self' https://medel.es; connect-src 'self' https://medel.es; style-src 'self' https://medel.es;
Questions honnêtes, réponses honnêtes
Quand apparaît le puzzle à glisser ?
Est-ce gratuit pour toujours ?
Fonctionne-t-il sans JavaScript ?
Trackez-vous mes utilisateurs ?
Pourquoi un slider plutôt que « sélectionnez les feux » ?
Et si Medel Captcha tombe ?
Compatible reCAPTCHA ?
Comment l'auto-héberger ?
Collez le snippet.
Oubliez les bots.
Intégrez en 30 secondes. Sans carte. Sans clés. Sans contrats. Sans petits caractères. Quand un bot tentera d'entrer, ce sera son problème — plus le vôtre.