Power Automate ne propose aucune action native pour les CAPTCHA : dès qu'un formulaire protégé apparaît dans un flux, l'exécution s'arrête et attend une intervention humaine. Trois actions du connecteur HTTP suffisent pourtant — envoyer le défi à CaptchaAI, interroger le résultat dans une boucle Do until, puis injecter le token.
Ce guide le construit pour reCAPTCHA v2 : paramètres exacts de chaque action, attente bornée, erreurs fréquentes en production.
Ce qu'il faut préparer
| Élément | Détail |
|---|---|
| Connecteur HTTP | Action Premium. Sans licence Premium : connecteur personnalisé ou Azure Function |
| Clé API CaptchaAI | Facturation au thread — BASIC ($15/mois, 5 threads) autorise 5 défis simultanés |
| Sitekey et URL | Les deux valeurs de la page protégée par reCAPTCHA v2 |
| Type de défi | reCAPTCHA v2 et v3, Cloudflare Turnstile, Cloudflare Challenge et GeeTest v3 sont pris en charge. hCaptcha et FunCaptcha ne le sont pas, GeeTest v4 est annoncé « à venir », CaptchaFox, Friendly Captcha et Lemin restent en bêta |
| Stockage de la clé | Variable d'environnement Power Platform ou Azure Key Vault, jamais en dur dans le flux |
Un cas concret : rapprochement de factures fournisseurs
Une équipe finance basée à Lyon récupère chaque lundi les relevés d'un portail fournisseur protégé par reCAPTCHA v2. Jusqu'ici, un comptable ouvrait le portail, cliquait la case, exportait le CSV. Le flux reprend cette séquence sans l'attente.
Deux réflexes dès la conception : hébergez l'environnement Power Platform dans une région européenne si vos données le justifient, et n'écrivez ni identifiants ni données personnelles dans les sorties d'actions — l'historique d'exécution les conserve, ce qui touche vos obligations RGPD.
Étape 1 : créer le flux et ses entrées
Créez un flux cloud instantané avec un déclencheur manuel (un déclencheur planifié convient aussi), puis ajoutez-lui deux entrées texte :
| Entrée | Type | Contenu |
|---|---|---|
sitekey |
Texte | La clé de site reCAPTCHA v2 |
pageurl |
Texte | L'URL de la page qui affiche le défi |
Les passer en entrée rend le flux réutilisable pour tous vos portails.
Étape 2 : envoyer le défi à CaptchaAI
L'action HTTP de soumission
Ajoutez une action HTTP. Les noms de paramètres sont sensibles à la casse.
| Champ | Valeur |
|---|---|
| Method | GET |
| URI | https://ocr.captchaai.com/in.php |
Query key |
votre clé API CaptchaAI |
Query method |
userrecaptcha |
Query googlekey |
@{triggerBody()['text']} (entrée sitekey) |
Query pageurl |
@{triggerBody()['text_1']} (entrée pageurl) |
Query json |
1 |
Lire la réponse
Ajoutez une action Analyser JSON juste après, avec ce schéma :
{
"type": "object",
"properties": {
"status": { "type": "integer" },
"request": { "type": "string" }
}
}
Contenu : @{body('HTTP')}
Étape 3 : valider la réponse de soumission
Une action Condition sur @{body('Parse_JSON')?['status']} sépare les deux sorties possibles.
| Résultat | Ce que fait le flux |
|---|---|
status vaut 1 |
request porte l'identifiant de la tâche : enchaînez sur la boucle |
| Toute autre valeur | Action Terminer, statut « Échec », message Submit error: @{body('Parse_JSON')?['request']} |
Étape 4 : construire la boucle d'interrogation
Avant la boucle, initialisez deux variables de type Chaîne : solveStatus à pending et solvedToken vide.
Dans la branche « Si oui », ajoutez une boucle Do until dont la condition est : @{variables('solveStatus')} n'est pas égal à pending. Quatre actions s'y enchaînent :
- Délai de 5 secondes — interroger plus vite n'accélère rien.
- HTTP vers
res.php, qui réclame le résultat. - Analyser JSON, schéma de l'étape 2, nommée
Parse_JSON_2. - Condition sur le statut renvoyé.
La requête d'interrogation se configure ainsi :
| Champ | Valeur |
|---|---|
| Method | GET |
| URI | https://ocr.captchaai.com/res.php |
Query key |
votre clé API CaptchaAI |
Query action |
get |
Query id |
@{body('Parse_JSON')?['request']} |
Query json |
1 |
La condition finale, @{body('Parse_JSON_2')?['status']} est égal à 1, tranche trois cas :
| Cas | Action dans la boucle |
|---|---|
| Résolu | solvedToken = @{body('Parse_JSON_2')?['request']}, puis solveStatus = solved |
request vaut CAPCHA_NOT_READY |
Ne rien faire : la boucle repart |
| Autre valeur | solveStatus = error |
Bornez enfin la boucle dans ses paramètres avancés : 20 itérations maximum, délai d'expiration PT3M (3 minutes). Sans ces bornes, un portail muet fait tourner le flux jusqu'au quota.
Étape 5 : injecter le token résolu
Après la boucle, une Condition sur @{variables('solveStatus')} sépare les deux issues. Si la valeur est solved, poussez le token dans la requête finale, ou transmettez-le à un autre connecteur (Teams, Outlook, Dataverse).
| Champ | Valeur |
|---|---|
| Method | POST |
| URI | URL du formulaire cible |
| Body | {"g-recaptcha-response": "@{variables('solvedToken')}", "other_field": "value"} |
Sinon, notifiez l'échec avec l'identifiant de la tâche. Le token est à usage unique et sa durée de vie est courte : soumettez le formulaire dans la même exécution.
Dépannage
Le flux ne démarre pas
| Problème | Cause | Correctif |
|---|---|---|
| L'action HTTP est absente du sélecteur | Connecteur Premium hors licence | Licence Premium, ou connecteur personnalisé |
| Erreur 403 renvoyée par l'API | Clé incorrecte ou restriction d'IP | Recopiez la clé, vérifiez la liste blanche d'IP |
ERROR_ZERO_BALANCE |
Solde épuisé | Rechargez, puis rejouez l'exécution |
Le flux démarre puis dérape
| Problème | Cause | Correctif |
|---|---|---|
| L'action Analyser JSON échoue | Réponse en texte brut, pas en JSON | Vérifiez que json vaut 1 |
| La boucle ne s'arrête jamais | solveStatus jamais mis à jour |
Contrôlez les noms dans « Définir la variable » |
| Le flux expire dans la boucle | Une action isolée expire à 2 minutes | Le délai PT3M du Do until couvre ce cas |
Dimensionner les threads
Un thread reste occupé de la soumission jusqu'au retour du token : un flux quotidien n'en mobilise qu'un, et BASIC couvre cinq flux simultanés. Si vous parallélisez une liste avec Appliquer à chacun, ne dépassez pas vos threads disponibles — au-delà, les tâches attendent et les boucles épuisent leurs 20 itérations pour rien.
Récapitulatif : le flux complet
[Manual Trigger (sitekey, pageurl)]
↓
[Initialize Variables: solveStatus, solvedToken]
↓
[HTTP: Submit to CaptchaAI /in.php]
↓
[Parse JSON]
↓
[Condition: status = 1?]
↓ Yes
[Do Until: solveStatus ≠ pending]
├── [Delay: 5 seconds]
├── [HTTP: Poll CaptchaAI /res.php]
├── [Parse JSON]
└── [Condition: Solved or Error?]
↓
[Condition: solveStatus = solved?]
↓ Yes
[HTTP: Submit form with token]
↓
[Compose: Success response]
Dupliquez ce squelette pour chaque portail : seules les entrées changent.
Questions fréquentes
Faut-il une licence Power Automate Premium pour ce flux ?
Oui, pour le connecteur HTTP. Deux replis possibles : un connecteur personnalisé, ou une Azure Function appelée depuis le flux.
Combien de threads ce flux consomme-t-il ?
Un seul par CAPTCHA en cours, libéré dès le retour du token. La facturation dépend des résolutions simultanées, pas du temps d'attente.
CaptchaAI prend-il en charge hCaptcha depuis Power Automate ?
Non — hCaptcha n'est pas pris en charge, FunCaptcha non plus. Pour un type pris en charge, changez method : turnstile pour Cloudflare Turnstile, post pour les CAPTCHA d'image.
Que se passe-t-il si la boucle atteint ses 20 itérations sans token ?
Le flux sort avec solveStatus resté à pending et part dans la branche d'échec. Relancez l'exécution plutôt que de rallonger l'attente : le défi expire aussi côté portail.
Où lire le code d'erreur quand une exécution échoue ?
Dans l'historique d'exécution, sur la sortie de l'action HTTP concernée : le champ request y porte le code exact, ERROR_ZERO_BALANCE ou ERROR_WRONG_USER_KEY par exemple.
Pour aller plus loin
Montez ce flux dans votre environnement de test, puis récupérez votre clé API CaptchaAI pour le passer en production.