DevOps & Scaling

Funciones de Azure + CaptchaAI: Integración en la nube

Azure Functions proporciona resolución CAPTCHA sin servidor con una estrecha integración en el ecosistema de Azure: Key Vault para secretos, Queue Storage para distribución de tareas y Application Insights para monitoreo.


Función activada por HTTP

# function_app.py
import json
import time
import os
import logging
import urllib.request
import urllib.parse
import azure.functions as func

app = func.FunctionApp()


@app.route(route="solve", methods=["POST"])
def solve_captcha(req: func.HttpRequest) -> func.HttpResponse:
    """HTTP trigger for CAPTCHA solving."""
    try:
        body = req.get_json()
    except ValueError:
        return func.HttpResponse(
            json.dumps({"error": "JSON body required"}),
            status_code=400,
            mimetype="application/json",
        )

    method = body.get("method", "userrecaptcha")
    params = body.get("params", {})
    api_key = os.environ["CAPTCHAAI_KEY"]

    try:
        token = solve(api_key, method, params)
        return func.HttpResponse(
            json.dumps({"token": token}),
            mimetype="application/json",
        )
    except Exception as e:
        logging.error(f"Solve failed: {e}")
        return func.HttpResponse(
            json.dumps({"error": str(e)}),
            status_code=500,
            mimetype="application/json",
        )


def solve(api_key, method, params, timeout=90):
    """Solve CAPTCHA via CaptchaAI API."""
    submit_data = urllib.parse.urlencode({
        "key": api_key,
        "method": method,
        "json": 1,
        **params,
    }).encode()

    req = urllib.request.Request(
        "https://ocr.captchaai.com/in.php",
        data=submit_data,
    )
    with urllib.request.urlopen(req, timeout=30) as resp:
        result = json.loads(resp.read())

    if result.get("status") != 1:
        raise RuntimeError(f"Submit error: {result.get('request')}")

    task_id = result["request"]

    start = time.time()
    while time.time() - start < timeout:
        time.sleep(5)
        poll_url = (
            f"https://ocr.captchaai.com/res.php"
            f"?key={api_key}&action=get&id={task_id}&json=1"
        )
        with urllib.request.urlopen(poll_url, timeout=15) as resp:
            data = json.loads(resp.read())

        if data["request"] != "CAPCHA_NOT_READY":
            if data.get("status") == 1:
                return data["request"]
            raise RuntimeError(f"Solve error: {data['request']}")

    raise TimeoutError("Solve timeout")

Integración de bóveda de claves

Almacene la clave API en Azure Key Vault:

# Create Key Vault
az keyvault create \
  --name captchaai-vault \
  --resource-group myResourceGroup

# Store secret
az keyvault secret set \
  --vault-name captchaai-vault \
  --name CaptchaAIKey \
  --value "YOUR_API_KEY"

# Grant function access
az webapp identity assign \
  --name my-captcha-function \
  --resource-group myResourceGroup

az keyvault set-policy \
  --name captchaai-vault \
  --object-id <principal-id> \
  --secret-permissions get

Referencia en la configuración de la aplicación:

CAPTCHAAI_KEY=@Microsoft.KeyVault(SecretUri=https://captchaai-vault.vault.azure.net/secrets/CaptchaAIKey/)

Procesamiento por lotes activado por cola

Procese tareas CAPTCHA desde Azure Queue Storage:

@app.queue_trigger(
    arg_name="msg",
    queue_name="captcha-tasks",
    connection="AzureWebJobsStorage",
)
def process_queue_task(msg: func.QueueMessage):
    """Process CAPTCHA task from queue."""
    task = json.loads(msg.get_body().decode())
    api_key = os.environ["CAPTCHAAI_KEY"]

    try:
        token = solve(api_key, task["method"], task["params"])
        logging.info(f"Task {task['id']} solved")

        # Store result in Table Storage or return queue
        _store_result(task["id"], "success", token)

    except Exception as e:
        logging.error(f"Task {task['id']} failed: {e}")
        _store_result(task["id"], "error", str(e))


def _store_result(task_id, status, value):
    """Store result (simplified — use Table Storage in production)."""
    logging.info(f"Result: {task_id} = {status}")

Estructura del proyecto

captcha-function/
├── function_app.py
├── requirements.txt
├── host.json
└── local.settings.json

requirements.txt:

azure-functions

host.json:

{
  "version": "2.0",
  "functionTimeout": "00:02:00",
  "logging": {
    "logLevel": {
      "default": "Information"
    }
  }
}

local.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "CAPTCHAAI_KEY": "YOUR_API_KEY_FOR_LOCAL_DEV"
  }
}

Implementar

# Create function app
az functionapp create \
  --resource-group myResourceGroup \
  --consumption-plan-location westus2 \
  --runtime python \
  --runtime-version 3.11 \
  --functions-version 4 \
  --name my-captcha-solver \
  --storage-account mystorageaccount

# Deploy
func azure functionapp publish my-captcha-solver

# Test
curl -X POST https://my-captcha-solver.azurewebsites.net/api/solve \
  -H "Content-Type: application/json" \
  -d '{
    "method": "userrecaptcha",
    "params": {
      "googlekey": "SITE_KEY",
      "pageurl": "https://example.com"
    }
  }'

Enviar tareas a la cola

from azure.storage.queue import QueueClient
import json

queue = QueueClient.from_connection_string(
    conn_str="YOUR_STORAGE_CONNECTION_STRING",
    queue_name="captcha-tasks",
)

# Submit batch
for i in range(10):
    task = {
        "id": f"task-{i}",
        "method": "userrecaptcha",
        "params": {
            "googlekey": "SITE_KEY",
            "pageurl": f"https://example.com/page{i}",
        },
    }
    queue.send_message(json.dumps(task))
    print(f"Queued task-{i}")

Solución de problemas

Problema causa Solución
La función se agota a los 5 min. Tiempo de espera predeterminado Establecer functionTimeout en host.json
La referencia de Key Vault devuelve vacía Falta identidad/policy Asignar identidad administrada y política de Key Vault
Los mensajes en cola se reintentan sin cesar La función lanza una excepción Manejar errores conocidos, registrar y devolver
Arranque en frío > 10 segundos Inicio del tiempo de ejecución de Python Utilice el plan Premium o configure FUNCTIONS_WORKER_PROCESS_COUNT

Preguntas frecuentes

¿Plan Consumo vs Premium?

Utilice Consumo para bajo volumen (< 100/day). Utilice Premium para cargas de trabajo consistentes: mantiene las instancias activas, elimina los inicios en frío y admite la integración VNET.

¿Cómo se comparan los precios de Azure Functions con los de AWS Lambda?

Muy similar para cargas de trabajo CAPTCHA. Ambos cobran ~$0,0001 por invocación en 256MB/60s. Azure incluye 1 millón de invocaciones gratuitas/month.

¿Puedo utilizar Durable Functions para flujos de trabajo complejos?

Sí. Durable Functions admite patrones de distribución /fan-in: envíe 10 CAPTCHA en paralelo y luego recopile todos los resultados. Excelente para el procesamiento por lotes.


Guías relacionadas

  • AWS Lambda + CaptchaAI
  • Funciones de Google Cloud + CaptchaAI

Despliega en Azure: obtén tu API key de CaptchaAI hoy.

Los comentarios están deshabilitados para este artículo.

Publicaciones relacionadas

DevOps & Scaling Trabajadores de resolución de CAPTCHA de escala automática
Cómo implementar autoescalado de trabajadores que resuelven CAPTCHA con Captcha AI: escalado basado en cola, subprocesos vs.

Cómo implementar autoescalado de trabajadores que resuelven CAPTCHA con Captcha AI: escalado basado en cola, s...

May 01, 2026
Explainers Impacto de la resolución DNS en el rendimiento de la API CAPTCHA
Cómo afecta la resolución DNS al rendimiento de la API CAPTCHA: cuándo es un cuello de botella, cómo optimizarla con keep-alive, caché y pre-resolución.

Cómo afecta la resolución DNS al rendimiento de la API CAPTCHA: cuándo es un cuello de botella, cómo optimizar...

Apr 24, 2026
Explainers Gestión de user-agent en QA propia con CaptchaAI
Cómo gestionar el user-agent en pruebas QA propias para reproducir escenarios reales sin recurrir a anti-detección.

Cómo gestionar el user-agent en pruebas QA propias para reproducir escenarios reales sin recurrir a anti-detec...

May 01, 2026