En production · 99,9 % uptime v2.0

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.

100 % self-hosted Zéro cookie Zéro tracking Sans limites
demo.html — Essayez en direct
Cochez la case. Zéro CPU jusque-là.
0
Challenges issued today
0
Verified
0
Tokens consumed
0€
Cost per use
Comment ça marche

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.

01

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.

02

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.

03

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.

Comparaison

Même objectif.
Meilleures conséquences.

Tout ce que reCAPTCHA fait pour vous, mCaptcha le fait aussi. Ce que reCAPTCHA fait à vos utilisateurs, non.

Google reCAPTCHA
mCaptcha Recommandé
Sans inscription ni clés API
Zéro tracking utilisateur
Zéro cookie tiers
Zéro CPU jusqu'à la première interaction
100 % self-hosted (sans dépendance externe)
Compatible avec le code reCAPTCHA existant
Vérifications illimitées et gratuites
Configuration CSP simple
Complexe
Minimale
Poids du widget (gzippé)
~150 Ko
~6 Ko
Installation

Deux lignes. Terminé.

Pas de npm install. Aucun dashboard où s'inscrire. Aucune clé à copier. Collez le snippet, déployez, fermez le ticket.

HTML
<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>
Zéro impact sur le premier rendu Le script se charge en async defer. Rien ne s'exécute avant que l'utilisateur coche. Vos Core Web Vitals vous remercient.
Clair, sombre ou automatique Suit par défaut prefers-color-scheme du navigateur. Forcez avec data-theme="dark|light" sur le div du widget.
Drop-in pour le code reCAPTCHA Accepte class="g-recaptcha" et remplit g-recaptcha-response. Migrez sans toucher une seule ligne de votre backend.
Mobile et tactile natifs Le puzzle à glisser répond aux doigts comme un contrôle natif. Pas de sélecteurs de vélos obscurs sur écrans de 4 pouces.
Vérification

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;
API

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.

Compatibilité

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;
FAQ

Questions honnêtes, réponses honnêtes

Quand apparaît le puzzle à glisser ?
Uniquement si votre IP a déclenché plus de 30 vérifications dans la dernière heure. Pour 99 % de vos utilisateurs, le flux se termine en un seul clic.
Est-ce gratuit pour toujours ?
Oui. Pas de carte, pas de plan, pas d'upsell. Le service est financé par les rate-limits par IP (100/h) et par domaine (5000/h). Besoin de plus ? Écrivez-nous, on monte la limite.
Fonctionne-t-il sans JavaScript ?
Non. mCaptcha a besoin de JS pour résoudre le Proof-of-Work ou glisser le slider. Si vous attendez du trafic sans JS, gardez un honeypot HTML en fallback.
Trackez-vous mes utilisateurs ?
Non. Zéro cookie, zéro fingerprinting, zéro analytics. Nous gardons l'IP 24 h pour le rate-limit, puis suppression automatique.
Pourquoi un slider plutôt que « sélectionnez les feux » ?
Les CAPTCHAs en grille d'images nécessitent un dataset énorme labellisé et du ML par-dessus. Un slider est visuellement équivalent, ne demande aucune banque de photos et marche sur n'importe quel appareil — même le plus ancien.
Et si Medel Captcha tombe ?
Le widget affiche une erreur et bloque l'envoi par défaut. En tant qu'intégrateur vous pouvez décider du bypass si verify timeout (5 secondes suffisent). 99,9 % d'uptime, mais le plan B est à vous.
Compatible reCAPTCHA ?
Oui. Le widget remplit automatiquement g-recaptcha-response et accepte class="g-recaptcha". Migrer = changer le src du script et l'URL de verify. Zéro refactor.
Comment l'auto-héberger ?
C'est du PHP 8.2+ avec MySQL. Le code sera sur GitHub sous MIT dès que je l'aurai nettoyé. En attendant, écrivez-moi et je vous l'envoie.

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.