Integrations

Airtable et CaptchaAI pour déclencher la résolution de CAPTCHA depuis la base

Oui, un enregistrement Airtable peut déclencher une résolution reCAPTCHA v2 de bout en bout : dès qu'une ligne passe au statut pending, une Automation appelle l'API CaptchaAI, récupère le token résolu et le réécrit dans la même table. Vous gardez le statut, l'horodatage, l'erreur et le token réutilisable au même endroit, sans serveur intermédiaire.

Airtable sert déjà de couche d'orchestration légère à beaucoup d'équipes data : collecte d'URL, qualification de leads, files de traitement sans interface lourde. Le maillon qui manque, c'est presque toujours la page protégée par un défi CAPTCHA.

À retenir : l'enregistrement n'est pas qu'un déclencheur, il devient un job complet — statut, token et trace d'erreur sur une seule ligne, rejouable à volonté.


Ce dont vous avez besoin

Trois éléments à réunir avant de câbler l'automatisation :

  • Une clé API CaptchaAI active, dont le solde couvre vos résolutions reCAPTCHA v2.
  • Une base Airtable dont l'offre autorise les Automations avec action « Run a script ».
  • Le sitekey reCAPTCHA de chaque page cible, à stocker dans la table.

Le scénario : d'un enregistrement à un token résolu

Le cas type : vous conservez des URL cibles dans une table, et chaque page affiche un reCAPTCHA v2 avant l'étape suivante. Quand une ligne arrive au statut pending, l'Automation la repère, le script envoie le sitekey et l'URL à l'API CaptchaAI, CaptchaAI résout le défi et renvoie le token, puis le token, le statut et l'horodatage repartent dans l'enregistrement.


Schéma de table pour suivre les jobs

Créez une table CAPTCHA Tasks avec ces champs. Ce schéma minimal suffit à piloter chaque job :

Champ Type Rôle
URL URL Page cible
Sitekey Texte Sitekey reCAPTCHA
Status Single select pending, solving, solved, failed
Token Long text Token CAPTCHA renvoyé
Solved At Date/time Date et heure de résolution
Error Texte Message d'erreur en cas d'échec

Le champ Status porte toute la logique :

  • pending déclenche l'Automation et sert de garde-fou contre les doublons.
  • solving marque un job en cours pour éviter une double soumission.
  • solved et failed clôturent la ligne, avec le token ou l'erreur.

Étape 1 : créer l'Automation et son déclencheur

Ouvrez l'onglet Automations, cliquez sur Create automation et nommez-la, par exemple Solve CAPTCHA on New Record.

Configurer le déclencheur

Choisissez When record matches conditions, pointez la table CAPTCHA Tasks et posez la condition Status égal à pending. Ce déclencheur couvre d'un coup les nouvelles lignes et les relances manuelles : il suffit de repasser un enregistrement en pending pour rejouer la résolution.

Étape 2 : ajouter le script de résolution

Ajoutez une action Run a script :

// Airtable Automation Script — Solve CAPTCHA via CaptchaAI

// Input configuration (set in the left panel):
// - recordId: Record ID from trigger
// - sitekey: Sitekey field from trigger
// - pageurl: URL field from trigger
const config = input.config();
const recordId = config.recordId;
const sitekey = config.sitekey;
const pageurl = config.pageurl;

const API_KEY = 'YOUR_API_KEY'; // Use input.config() for security

// Update status to "solving"
const table = base.getTable('CAPTCHA Tasks');
await table.updateRecordAsync(recordId, {
  'Status': { name: 'solving' },
});

try {
  // Step 1: Submit task to CaptchaAI
  const submitUrl = `https://ocr.captchaai.com/in.php?key=${API_KEY}&method=userrecaptcha&googlekey=${encodeURIComponent(sitekey)}&pageurl=${encodeURIComponent(pageurl)}&json=1`;

  const submitResponse = await fetch(submitUrl);
  const submitResult = await submitResponse.json();

  if (submitResult.status !== 1) {
    throw new Error(`Submit failed: ${submitResult.request}`);
  }

  const taskId = submitResult.request;
  console.log(`Task submitted: ${taskId}`);

  // Step 2: Poll for result (wait 15 seconds first)
  await new Promise(resolve => setTimeout(resolve, 15000));

  let token = null;
  for (let i = 0; i < 20; i++) {
    const pollUrl = `https://ocr.captchaai.com/res.php?key=${API_KEY}&action=get&id=${taskId}&json=1`;
    const pollResponse = await fetch(pollUrl);
    const pollResult = await pollResponse.json();

    if (pollResult.status === 1) {
      token = pollResult.request;
      break;
    }

    if (pollResult.request !== 'CAPCHA_NOT_READY') {
      throw new Error(`Solve failed: ${pollResult.request}`);
    }

    await new Promise(resolve => setTimeout(resolve, 5000));
  }

  if (!token) {
    throw new Error('Polling timeout — CAPTCHA not solved in time');
  }

  // Step 3: Update record with solved token
  await table.updateRecordAsync(recordId, {
    'Status': { name: 'solved' },
    'Token': token,
    'Solved At': new Date().toISOString(),
    'Error': '',
  });

  console.log(`CAPTCHA solved for record ${recordId}`);

} catch (error) {
  // Update record with error
  await table.updateRecordAsync(recordId, {
    'Status': { name: 'failed' },
    'Error': error.message,
  });
  console.error(`Failed: ${error.message}`);
}

Mapper les variables d'entrée

Dans le panneau de gauche de l'action, reliez recordId au Record ID du trigger, sitekey au champ Sitekey et pageurl au champ URL. En production, ne laissez jamais la clé API en dur : passez-la via input.config() ou une variable secrète.

Étape 3 : traiter les enregistrements par lot

Pour rattraper une file de plusieurs enregistrements en une passe, utilisez la Scripting extension d'Airtable (panneau Apps) :

// Batch CAPTCHA Solver — Airtable Scripting Extension
const API_KEY = 'YOUR_API_KEY';
const table = base.getTable('CAPTCHA Tasks');

// Get all pending records
const query = await table.selectRecordsAsync({
  fields: ['URL', 'Sitekey', 'Status'],
});

const pendingRecords = query.records.filter(
  r => r.getCellValueAsString('Status') === 'pending'
);

output.text(`Found ${pendingRecords.length} pending CAPTCHAs`);

for (const record of pendingRecords) {
  const sitekey = record.getCellValueAsString('Sitekey');
  const pageurl = record.getCellValueAsString('URL');

  if (!sitekey || !pageurl) {
    output.text(`Skipping ${record.id} — missing sitekey or URL`);
    continue;
  }

  output.text(`Solving for: ${pageurl}`);

  await table.updateRecordAsync(record.id, {
    'Status': { name: 'solving' },
  });

  try {
    // Submit
    const submitResp = await fetch(
      `https://ocr.captchaai.com/in.php?key=${API_KEY}&method=userrecaptcha&googlekey=${encodeURIComponent(sitekey)}&pageurl=${encodeURIComponent(pageurl)}&json=1`
    );
    const submitData = await submitResp.json();

    if (submitData.status !== 1) throw new Error(submitData.request);

    // Poll
    await new Promise(r => setTimeout(r, 15000));
    let token = null;

    for (let i = 0; i < 20; i++) {
      const pollResp = await fetch(
        `https://ocr.captchaai.com/res.php?key=${API_KEY}&action=get&id=${submitData.request}&json=1`
      );
      const pollData = await pollResp.json();

      if (pollData.status === 1) { token = pollData.request; break; }
      if (pollData.request !== 'CAPCHA_NOT_READY') throw new Error(pollData.request);
      await new Promise(r => setTimeout(r, 5000));
    }

    if (!token) throw new Error('Timeout');

    await table.updateRecordAsync(record.id, {
      'Status': { name: 'solved' },
      'Token': token,
      'Solved At': new Date().toISOString(),
    });
    output.text(`✓ Solved: ${pageurl}`);

  } catch (e) {
    await table.updateRecordAsync(record.id, {
      'Status': { name: 'failed' },
      'Error': e.message,
    });
    output.text(`✗ Failed: ${e.message}`);
  }
}

output.text('Batch processing complete');

Périmètre et conformité RGPD

Une base qui pilote des résolutions stocke des URL et des tokens : traitez-la comme un système de données. Quelques réflexes RGPD pour les équipes concernées :

  • Minimisez les données : gardez l'URL, le sitekey et le résultat technique, rien sur les utilisateurs finaux.
  • Purgez les tokens une fois consommés — leur durée de vie est courte.
  • Gardez la clé API hors de la base et limitez qui peut ouvrir le script.

Restez dans votre périmètre : n'automatisez que des démarches et des environnements que vous êtes autorisé à traiter.


Dépannage

Problème Cause probable Correctif
L'Automation ne se déclenche pas La ligne n'est pas exactement au statut pending Contrôlez la valeur du champ Status, espaces compris
fetch is not defined Certains contextes Airtable exposent remoteFetchAsync Remplacez fetch par remoteFetchAsync
Le script expire avant la fin La fenêtre d'exécution des Automations est courte Augmentez le délai initial, réduisez le nombre d'itérations
La réécriture de l'enregistrement échoue Noms de champs qui ne correspondent pas Alignez les libellés sur ceux passés à updateRecordAsync
La clé API apparaît en clair Clé codée en dur dans le script Utilisez input.config() avec une variable secrète

Questions fréquentes

Faut-il un abonnement Airtable payant pour lancer un script depuis une Automation ?

L'action « Run a script » et la Scripting extension dépendent des offres qui incluent les Automations avancées ; vérifiez votre plan avant de compter dessus en production.

Combien de temps le token reCAPTCHA v2 reste-t-il valide ?

Quelques minutes seulement après sa résolution. Consommez-le vite côté page cible : le stocker longtemps dans Airtable n'a aucun intérêt, et c'est à ça que sert le champ Solved At.

Combien de threads CaptchaAI faut-il prévoir pour un traitement par lot ?

Un thread correspond à un CAPTCHA en cours. L'offre BASIC ($15/mois, 5 threads) suffit pour une file modeste ; montez en gamme pour de gros lots en simultané.


Articles connexes

Prochaines étapes

Si Airtable pilote déjà vos opérations data, créez votre clé API CaptchaAI et faites de chaque enregistrement critique une tâche de résolution reCAPTCHA v2 traçable et rejouable.

Guides associés :

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