API Tutorials

Résoudre le CAPTCHA d'image avec Node.js et CaptchaAI

Deux appels HTTP suffisent : vous envoyez l'image à l'API OCR de CaptchaAI, puis vous interrogez le résultat jusqu'à récupérer le texte attendu par le formulaire. Une trentaine de lignes avec axios, aucun modèle à entraîner, aucun prétraitement d'image obligatoire.

Au programme : les deux méthodes d'envoi, la boucle d'interrogation, les paramètres qui améliorent la reconnaissance, un script complet avec Puppeteer et les erreurs rencontrées en production.


Ce dont vous avez besoin avant de commencer

Élément Valeur
Clé API CaptchaAI Depuis captchaai.com
Node.js 14+
Bibliothèques axios, fs
Format des images JPG, PNG ou GIF (100 octets – 100 Ko)

Gardez la clé API hors du dépôt : une variable d'environnement, jamais une chaîne en dur — YOUR_API_KEY n'est ici qu'un repère.


Où ces CAPTCHA en texte déformé apparaissent encore

Le CAPTCHA d'image classique — quelques caractères tordus sur un fond bruité — a quitté les grands sites, mais il reste partout où le logiciel a dix ans : portails administratifs, extranets métier, back-offices de facturation, plateformes B2B régionales, ou les portails de rendez-vous BLS que beaucoup de lecteurs au Maghreb consultent pour leurs propres démarches.

Le point commun de ces surfaces : ni widget moderne, ni token JavaScript à récupérer, seulement une balise <img> et un champ texte. Votre script capture donc l'image, la fait lire, puis saisit le résultat comme le ferait une personne. C'est le rôle de l'endpoint OCR.

Côté conformité : une capture prise sur une page authentifiée peut contenir des données personnelles. Cadrez-la sur le seul défi CAPTCHA, purgez les fichiers temporaires et traitez ce point dans vos obligations RGPD.


Étape 1 : envoyez l'image encodée en base64

La voie la plus directe quand l'image est déjà en mémoire, après un screenshot() Puppeteer par exemple. Vous encodez le fichier et vous postez sur in.php avec method=base64. La réponse JSON porte l'identifiant de tâche dans request quand status vaut 1 ; sinon, request contient le code d'erreur.

const axios = require('axios');
const fs = require('fs');

const API_KEY = 'YOUR_API_KEY';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

// Read and encode the image
const imageB64 = fs.readFileSync('captcha.png').toString('base64');

// Submit to CaptchaAI
const { data: submitData } = await axios.post('https://ocr.captchaai.com/in.php', null, {
  params: {
    key: API_KEY,
    method: 'base64',
    body: imageB64,
    json: 1,
  },
});

if (submitData.status !== 1) throw new Error(submitData.request);
const taskId = submitData.request;
console.log(`Task submitted: ${taskId}`);

Conservez cet identifiant : c'est la seule clé qui permet d'aller chercher le texte à l'étape suivante, et de signaler plus tard une lecture incorrecte.


Étape 2 (variante) : envoyez le fichier tel quel

Si l'image arrive d'un téléchargement ou d'un dossier surveillé, l'envoi multipart évite un aller-retour d'encodage. Le principe reste identique, seul le transport change : method=post, un FormData et le flux de lecture du fichier.

const FormData = require('form-data');

const form = new FormData();
form.append('key', API_KEY);
form.append('method', 'post');
form.append('json', '1');
form.append('file', fs.createReadStream('captcha.png'));

const { data: submitData } = await axios.post('https://ocr.captchaai.com/in.php', form, {
  headers: form.getHeaders(),
});

const taskId = submitData.request;

Les deux méthodes alimentent la même file d'attente de résolution. Choisissez selon l'endroit d'où vient l'image, pas selon une hypothèse de vitesse.


Étape 3 : interrogez le résultat jusqu'au texte final

L'API est asynchrone. Après l'envoi, laissez passer cinq secondes, puis interrogez res.php à intervalle régulier. Tant que le travail est en cours, la réponse vaut CAPCHA_NOT_READY : c'est un état normal, pas une erreur. Toute autre valeur inattendue doit interrompre la boucle immédiatement, sinon vous occupez un thread pour rien pendant deux minutes et demie.

await sleep(5000);

let captchaText;
for (let i = 0; i < 30; i++) {
  const { data: pollData } = await axios.get('https://ocr.captchaai.com/res.php', {
    params: { key: API_KEY, action: 'get', id: taskId, json: 1 },
  });

  if (pollData.status === 1) {
    captchaText = pollData.request;
    console.log(`CAPTCHA text: ${captchaText}`);
    break;
  }
  if (pollData.request !== 'CAPCHA_NOT_READY') {
    throw new Error(pollData.request);
  }
  await sleep(5000);
}

Un intervalle de 5 secondes sur trente tentatives est un bon point de départ. Interroger toutes les secondes n'accélère rien et multiplie les requêtes inutiles.


Étape 4 : cadrez la reconnaissance avec les paramètres de précision

La plupart des lectures ratées ne viennent pas de l'image mais du manque de contexte. Si vous savez que le formulaire attend six chiffres, dites-le : le moteur écarte alors les hypothèses impossibles.

// Digits only, 4-6 characters
const { data } = await axios.post('https://ocr.captchaai.com/in.php', null, {
  params: {
    key: API_KEY,
    method: 'base64',
    body: imageB64,
    numeric: 1,      // digits only
    min_len: 4,       // minimum length
    max_len: 6,       // maximum length
    json: 1,
  },
});
Paramètre Valeur Objectif
numeric 1 = chiffres, 2 = lettres Limite les caractères
min_len / max_len Entier Contraintes de longueur
calc 1 Calcule une expression mathématique
regsense 1 Sensible à la casse

calc sert aux vieux formulaires affichant « 7 + 4 = ? » en image : vous recevez le résultat calculé. Quand une lecture est fausse, signalez-la via res.php?key=KEY&action=reportbad&id=TASK_ID.


Exemple complet en Node.js : de la capture Puppeteer au formulaire soumis

Ce script enchaîne les quatre étapes précédentes : ouverture de la page, capture de l'élément #captcha-image, envoi, interrogation, saisie et soumission.

const axios = require('axios');
const puppeteer = require('puppeteer');
const fs = require('fs');

const API_KEY = 'YOUR_API_KEY';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function solveImageCaptcha() {
  // 1. Load page and screenshot CAPTCHA
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com/register');

  const captchaEl = await page.$('#captcha-image');
  await captchaEl.screenshot({ path: 'captcha.png' });

  // 2. Encode and submit
  const imageB64 = fs.readFileSync('captcha.png').toString('base64');
  const { data: submit } = await axios.post('https://ocr.captchaai.com/in.php', null, {
    params: { key: API_KEY, method: 'base64', body: imageB64, json: 1 },
  });
  const taskId = submit.request;

  // 3. Poll for text
  await sleep(5000);
  let text;
  for (let i = 0; i < 30; i++) {
    const { data: poll } = await axios.get('https://ocr.captchaai.com/res.php', {
      params: { key: API_KEY, action: 'get', id: taskId, json: 1 },
    });
    if (poll.status === 1) { text = poll.request; break; }
    if (poll.request !== 'CAPCHA_NOT_READY') throw new Error(poll.request);
    await sleep(5000);
  }

  // 4. Type and submit
  await page.type('#captcha-input', text);
  await page.click('form [type="submit"]');
  console.log(`Solved: ${text}`);
  await browser.close();
}

solveImageCaptcha().catch(console.error);

Résultat attendu :

Solved: ABC123

Encadrez cette fonction d'un try/finally qui ferme toujours le navigateur, et prévoyez une nouvelle tentative si le formulaire refuse le texte : la deuxième image est souvent plus lisible.


Erreurs fréquentes et correctifs

Erreur Cause Correctif
ERROR_WRONG_FILE_EXTENSION Format non pris en charge Utilisez JPG, PNG ou GIF
ERROR_TOO_BIG_CAPTCHA_FILESIZE Image supérieure à 100 Ko Compressez avant l'envoi
ERROR_ZERO_CAPTCHA_FILESIZE Image inférieure à 100 octets Vérifiez le sélecteur de capture
CAPCHA_NOT_READY Résolution encore en cours Interrogez toutes les 5 secondes

Les deux erreurs de taille se règlent dans le sélecteur : une capture prise sur le conteneur parent gonfle le fichier, une capture prise sur un élément encore masqué produit un fichier vide.


Passer en production : threads, coût et hébergement

La facturation CaptchaAI se fait au thread simultané, pas à la résolution : chaque plan inclut un nombre illimité de résolutions par thread. Un thread correspond à une image en cours de lecture ; dès qu'elle est rendue, il reprend la suivante.

Pour du monitoring de formulaires, BASIC ($15/mois, 5 threads) suffit. Un pipeline de scraping multi-domaines est plus à l'aise sur STANDARD ($30/mois, 15 threads), voire ADVANCE ($90/mois, 50 threads). Facturation en dollars US.

Côté exécution, hébergez le worker près des sites visés : une instance OVHcloud ou Scaleway, ou une région AWS eu-west-3 (Paris), réduit la latence sur des portails européens. Le temps de résolution, lui, dépend de l'image.

Journalisez enfin trois valeurs par tâche : l'identifiant, le nombre d'interrogations et le texte renvoyé. C'est le minimum pour distinguer un problème de lecture d'un problème de formulaire.


FAQ

Quels formats et quelles tailles d'image l'API accepte-t-elle ?

JPG, PNG et GIF, entre 100 octets et 100 Ko. Au-delà, recompressez ou resserrez la capture sur le seul défi CAPTCHA.

Comment améliorer la précision sur des images très bruitées ?

Décrivez ce que vous attendez avec numeric, min_len, max_len et regsense. Une longueur exacte change souvent plus le résultat qu'un prétraitement d'image.

Combien de threads faut-il pour lire plusieurs images en parallèle ?

Autant que d'images traitées simultanément. Cinq threads (BASIC, $15/mois) couvrent cinq lectures en même temps, sans limite de volume mensuel sur ces threads.

Que faire si la boucle atteint ses trente tentatives sans réponse ?

Abandonnez la tâche, recapturez une image et repartez sur un envoi neuf : une tâche anormalement longue ne se débloque pas en étant interrogée davantage.

CaptchaAI prend-il en charge hCaptcha ou FunCaptcha ?

Non — ces deux types ne sont pas pris en charge. L'offre couvre reCAPTCHA v2 et v3, Cloudflare Turnstile, Cloudflare Challenge, GeeTest v3, ainsi que les CAPTCHA image/OCR et les grilles d'images traités ici.


Guides associés


Ouvrez votre compte CaptchaAI et lisez votre première image →

Les commentaires sont désactivés pour cet article.