Cinco acciones del diseñador separan a un flujo de Power Automate de resolver un reCAPTCHA v2 solo: una llamada HTTP que registra el desafío, Analizar JSON, una Condición que corta si algo va mal, un bucle Do until que sondea y un POST final que usa el token. Cero código, cero conectores personalizados, cero Azure Functions.
El único peaje real es de licencia: el conector HTTP es Premium. Si tu tenant ya lo tiene, en una tarde queda montado. Es el mismo esqueleto que montarías en Python con CaptchaAI, solo que dibujado — y con el historial a la vista, se depura más cómodo que un script.
Paso 1: el disparador y sus dos entradas
Crea un flujo de nube instantáneo con desencadenador manual; el programado o el de Power Apps sirven igual.
Añade los parámetros de entrada
El desencadenador necesita dos entradas de texto; parametrizarlas te deja reutilizar el flujo con varios portales en vez de clonarlo:
- sitekey: el sitekey del reCAPTCHA v2 incrustado en la página
- pageurl: la URL exacta donde aparece el desafío
Paso 2: registrar la tarea en CaptchaAI
Añade una acción HTTP (conector Premium):
- Método: GET
- URI:
https://ocr.captchaai.com/in.php
Consultas — los nombres van en inglés porque son los que espera el endpoint in.php, y json=1 no es opcional: sin él la respuesta llega como texto plano y Analizar JSON revienta.
key— tu clave API de CaptchaAImethod—userrecaptchagooglekey—@{triggerBody()['text']}(entrada sitekey)pageurl—@{triggerBody()['text_1']}(entrada pageurl)json—1
Analiza la respuesta: añade Analizar JSON justo después de la acción HTTP.
Esquema:
{
"type": "object",
"properties": {
"status": { "type": "integer" },
"request": { "type": "string" }
}
}
Contenido: @{body('HTTP')}
Paso 3: cortar pronto si el envío falla
Añade una acción Condición. Con la clave mal copiada o el saldo agotado, detiene el flujo con el motivo a la vista en vez de sondear tres minutos una tarea que nunca se creó.
La condición es @{body('Parse_JSON')?['status']} es igual a 1, y cada rama hace una cosa:
| Rama | Acción |
|---|---|
| Si no (el envío falló) | Terminar con estado "Failed" y mensaje Submit error: @{body('Parse_JSON')?['request']} |
| Si sí | Continúa al bucle de sondeo |
Paso 4: el bucle que espera el token
En la rama "Si sí", añade un bucle Do until.
Condición del bucle: @{variables('solveStatus')} no es igual a pending
Antes del bucle, inicializa dos variables:
- solveStatus (Cadena) =
pending - solvedToken (Cadena) = vacío
Dentro del bucle Do until, añade estas acciones en secuencia:
4a. Retraso
Una acción Retraso de 5 segundos abre cada vuelta: el token rara vez llega al primer intento.
4b. HTTP: consultar el resultado
- Método: GET
- URI:
https://ocr.captchaai.com/res.php
Consultas:
key— tu clave API de CaptchaAIaction—getid—@{body('Parse_JSON')?['request']}json—1
4c. Analizar JSON: respuesta de la consulta
Usa el mismo esquema del Paso 2.
4d. Condición: comprobar el estado
La condición es @{body('Parse_JSON_2')?['status']} es igual a 1:
| Rama | Qué estableces |
|---|---|
| Si sí (resuelto) | solvedToken = @{body('Parse_JSON_2')?['request']} y solveStatus = solved |
| Si no | Una condición anidada sobre @{body('Parse_JSON_2')?['request']} no es igual a CAPCHA_NOT_READY |
En la anidada: si es verdadero hay un error real y solveStatus = error; si es falso el token sigue pendiente y no haces nada, que es lo que mantiene el bucle girando.
Fija los dos límites del bucle Do until, que son la red de seguridad del flujo:
- Recuento: 20 (iteraciones máximas)
- Tiempo de espera: PT3M (3 minutos)
Paso 5: dar salida al token
Al salir del bucle, una Condición sobre @{variables('solveStatus')} decide el final:
Si es igual a "solved":
- Usa
@{variables('solvedToken')}en un POST HTTP para enviar el formulario - O reenvíalo por correo o Teams
El campo g-recaptcha-response es el que valida el servidor de destino: renombrarlo rompe el envío sin error claro.
- Método: POST
- URI: la URL del formulario de destino
- Cuerpo:
{"g-recaptcha-response": "@{variables('solvedToken')}", "other_field": "value"}
Si no es "solved":
- Envía una notificación de error por Teams o correo
El flujo completo en el diseñador
Montados los cinco pasos, la forma final es esta:
[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]
Un caso real: la conciliación de cada mañana
Power Automate rinde cuando el proceso ya vive en el ecosistema Microsoft, y se atasca en el último tramo: un portal externo sin API que protege el login con un reCAPTCHA v2.
El caso típico: cada mañana alguien marca la casilla del CAPTCHA del portal de proveedores, descarga el CSV de comprobantes y lo sube a SharePoint para que el flujo lo concilie. Quince minutos diarios haciendo de conector humano. Con este patrón, solo revisa las excepciones.
Antes de automatizar: hazlo solo sobre portales donde tengas cuenta propia o permiso explícito, y revisa los términos de servicio y la normativa de protección de datos aplicable.
Qué cuesta esto al mes
CaptchaAI factura por threads concurrentes, no por CAPTCHA resuelto. Como un flujo instantáneo resuelve de uno en uno, cuentas ejecuciones simultáneas, no resoluciones al mes: BASIC ($15/mes) da 5 threads y cubre un puñado de flujos programados; STANDARD ($30/mes) sube a 15 si varios coinciden; ADVANCE ($90/mes, 50 threads) es para decenas en paralelo.
Para una agencia que factura en moneda local, ese coste fijo en USD se presupuesta una vez y no se mueve aunque el volumen fluctúe mes a mes.
Los cinco tropiezos de la primera tarde
El conector HTTP no aparece en el buscador de acciones
Es Premium y el plan gratuito no lo incluye: sube la licencia o publica un conector propio.
Analizar JSON falla en la primera ejecución
El cuerpo llegó como texto plano: falta json=1 en los parámetros de la acción HTTP.
El bucle no termina nunca
solveStatus no se actualiza: los nombres en Establecer variable deben coincidir exactamente con los de la inicialización.
CaptchaAI responde 403
Clave API incorrecta, o la lista blanca de IP está activa y el rango de salida de Power Automate no figura en ella.
El flujo se corta a los dos minutos
Ese es el límite por acción, no el del flujo (30 días). El PT3M del Do until lo cubre; amplíalo si el portal va lento.
Preguntas frecuentes
¿Cuántas ejecuciones simultáneas aguanta un solo plan?
Tantas como threads tenga el plan: con BASIC ($15/mes, 5 threads) hay cinco resoluciones en vuelo y la sexta espera turno. Si tus flujos coinciden en la misma franja, cuenta threads, no ejecuciones diarias.
¿Sirve el mismo flujo si el portal cambia a Cloudflare Turnstile?
Sí. En el Paso 2 cambias method=turnstile y ajustas sus parámetros; el esqueleto no se toca. Lo que cambia es el nombre del campo del token en el POST final.
¿Dónde guardo la clave API para que no quede escrita en el flujo?
En Variables de entorno de Power Platform o en Azure Key Vault: así la definición viaja entre entornos sin el secreto dentro.
¿Qué tipos de CAPTCHA cubre este mismo patrón?
Cambiando solo method: reCAPTCHA v2 y v3, Cloudflare Turnstile y Cloudflare Challenge, GeeTest v3, e imagen/OCR y grid. CaptchaFox, Friendly Captcha y Lemin están en beta. GeeTest v4 figura como próximamente, así que confirma el tipo del portal antes de montar el flujo.
Sigue por aquí
- resolver el callback de reCAPTCHA v2 desde la API
- convivencia de reCAPTCHA v2 y Turnstile en el mismo sitio
- cómo funciona el mecanismo de callback de reCAPTCHA v2
- Zapier + CaptchaAI: resolución de CAPTCHA sin código
- Make (Integromat) + CaptchaAI
- Retool + CaptchaAI: CAPTCHA en herramientas internas
Siguiente paso
Obtén tu clave API de CaptchaAI y arrastra la primera acción HTTP al diseñador.