Explicaciones Técnicas

CaptchaAI JSON API vs Form API: qué formato usar

La respuesta corta: da igual. La API de CaptchaAI acepta las dos codificaciones —form-encoded y JSON— y devuelve exactamente el mismo resultado con la misma velocidad. No hay un formato "rápido" y otro "lento", ni uno que resuelva mejor. La decisión es puramente de comodidad: qué encaja mejor con tu lenguaje, tu cliente HTTP y el resto de tu código.

Este artículo te da una regla rápida para elegir en diez segundos, la tabla de diferencias reales y ejemplos listos para copiar en Python y Node.js, incluido el caso del CAPTCHA de imagen, donde el formato sí cambia cómo envías el archivo.


Qué formato elegir según tu caso

Si no quieres leer el detalle, usa esta tabla como atajo. Cubre los escenarios más habituales que aparecen en el soporte.

Escenario Recomendado ¿Por qué?
Guiones simples Codificado en formato Más simple, menos dependencias
Integración de API REST JSON Coincide con los patrones típicos de API
Cargas de archivos Formulario de varias partes Carga binaria directa
Imágenes grandes en base64 Codificado en formato Mejor manejo de grandes cargas útiles
TypeScript/modern JS JSON Soporte de objetos nativos
Integración de sistemas heredados Codificado en formato Compatibilidad universal
Migrando desde 2Captcha Codificado en formato Mismo formato que 2Captcha

La regla práctica se reduce a dos casos:

  • Si ya tienes un cliente REST que serializa JSON por defecto (por ejemplo, una integración nueva con Axios o httpx), usa JSON.
  • Si portas un script antiguo o vienes de 2Captcha, quédate con form-encoded y no cambies nada.

Diferencias reales entre los dos formatos

Todo lo que cambia entre una codificación y otra está en esta tabla. Ninguna de estas diferencias afecta a la resolución en sí: solo a cómo construyes la solicitud.

factores Codificado en formato JSON
Tipo de contenido application/x-www-form-urlencoded application/json
estructura de datos Pares clave-valor planos Objetos anidados posibles
datos binarios Utilice multiparte para cargar archivos Codificación Base64 en el campo del cuerpo.
Soporte de matriz Limitado Nativo
Palabra clave de Python data={} json={}
Nodo.js URLSearchParams JSON.stringify()
Legibilidad Simple para parámetros planos. Mejor para datos complejos
Compatibilidad Funciona en todas partes Funciona en todas partes

En la práctica:

  • Para parámetros planos (clave, método, sitekey, URL de un reCAPTCHA v2 o un Turnstile), las dos codificaciones quedan igual de legibles.
  • La diferencia solo se nota con estructuras anidadas o listas, donde JSON resulta más natural.

Errores comunes al elegir el formato

Antes de bajar al código, ten presentes los descuidos que generan casi todos los tickets de soporte. Revísalos antes de abrir una incidencia.

error problema Solución
Usando json={} pero sin json: 1 en los datos La respuesta es texto plano. Incluir "json": 1 en los datos
Mezclando data= y json= en solicitudes de Python Solicitud mal formada Usa uno u otro
Olvidar el encabezado de tipo de contenido El servidor no puede analizar el cuerpo Deje que su biblioteca HTTP lo configure automáticamente
Envío del cuerpo JSON al punto final de la consulta La consulta utiliza parámetros GET Utilice siempre GET con parámetros de consulta para /res.php

Comparación lado a lado

La misma solicitud, escrita en las dos codificaciones. Fíjate en que solo cambia el argumento de requests.post: data= frente a json=.

Codificado en formulario (predeterminado)

import requests

resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "SITE_KEY",
    "pageurl": "https://example.com",
    "json": 1,
})

Tipo de contenido: application/x-www-form-urlencoded

JSON

import requests

resp = requests.post("https://ocr.captchaai.com/in.php", json={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "SITE_KEY",
    "pageurl": "https://example.com",
    "json": 1,
})

Tipo de contenido: application/json


El campo json=1 controla la respuesta, no la solicitud

Aquí está el matiz que más confusión genera en soporte: el formato de la solicitud y el formato de la respuesta son independientes. Añade json=1 en el cuerpo para recibir la respuesta como JSON, sin importar cómo hayas enviado los datos:

# Without json=1 — plain text response
resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "SITE_KEY",
    "pageurl": "https://example.com",
})
# Response: "OK|12345678"

# With json=1 — JSON response
resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "SITE_KEY",
    "pageurl": "https://example.com",
    "json": 1,
})
# Response: {"status": 1, "request": "12345678"}

Recomendación práctica:

  • Incluye siempre json=1: parsear {"status": 1, "request": "12345678"} es más robusto que partir la cadena "OK|12345678" a mano.
  • Así evitas bugs cuando el mensaje de error cambia de forma.

Ejemplos en Python

El flujo completo —enviar la tarea y luego sondear el resultado— en las dos codificaciones. El sondeo es idéntico en ambos casos: siempre un GET a res.php con parámetros de consulta.

Codificado en formato

import requests

# Submit
resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "SITE_KEY",
    "pageurl": "https://example.com",
    "json": 1,
})
task_id = resp.json()["request"]

# Poll (always GET with query params)
resp = requests.get("https://ocr.captchaai.com/res.php", params={
    "key": "YOUR_API_KEY",
    "action": "get",
    "id": task_id,
    "json": 1,
})

Cuerpo JSON

import requests

# Submit with JSON
resp = requests.post("https://ocr.captchaai.com/in.php", json={
    "key": "YOUR_API_KEY",
    "method": "userrecaptcha",
    "googlekey": "SITE_KEY",
    "pageurl": "https://example.com",
    "json": 1,
})
task_id = resp.json()["request"]

# Poll (same as form-encoded — GET with params)
resp = requests.get("https://ocr.captchaai.com/res.php", params={
    "key": "YOUR_API_KEY",
    "action": "get",
    "id": task_id,
    "json": 1,
})

Ejemplos en Node.js

En Node el detalle importante es la serialización del cuerpo. Con form-encoded pasas la cadena por querystring; con JSON dejas que Axios serialice el objeto directamente.

Codificado en formato

const axios = require('axios');
const qs = require('querystring');

// Submit
const resp = await axios.post(
  'https://ocr.captchaai.com/in.php',
  qs.stringify({
    key: 'YOUR_API_KEY',
    method: 'userrecaptcha',
    googlekey: 'SITE_KEY',
    pageurl: 'https://example.com',
    json: 1,
  })
);
const taskId = resp.data.request;

Cuerpo JSON

const axios = require('axios');

// Submit with JSON
const resp = await axios.post(
  'https://ocr.captchaai.com/in.php',
  {
    key: 'YOUR_API_KEY',
    method: 'userrecaptcha',
    googlekey: 'SITE_KEY',
    pageurl: 'https://example.com',
    json: 1,
  }
);
const taskId = resp.data.request;

CAPTCHA de imagen: aquí sí importa el formato

Para reCAPTCHA, Turnstile o GeeTest v3 la elección es indiferente. El único punto donde el formato cambia algo real es el CAPTCHA de imagen, porque tienes que mover bytes: o subes el archivo como multipart, o lo codificas en Base64 dentro del cuerpo.

Formulario con carga de archivo (varias partes)

# File upload — form-encoded with multipart
resp = requests.post("https://ocr.captchaai.com/in.php",
    data={
        "key": "YOUR_API_KEY",
        "method": "post",
        "json": 1,
    },
    files={
        "file": open("captcha.png", "rb"),
    },
)

JSON con Base64

import base64

# Base64 in JSON body
with open("captcha.png", "rb") as f:
    body = base64.b64encode(f.read()).decode()

resp = requests.post("https://ocr.captchaai.com/in.php", json={
    "key": "YOUR_API_KEY",
    "method": "base64",
    "body": body,
    "json": 1,
})

Formulario con Base64

# Base64 in form data
resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": "YOUR_API_KEY",
    "method": "base64",
    "body": body,
    "json": 1,
})

Notas para imágenes grandes:

  • El Base64 infla el cuerpo alrededor de un tercio, así que en volúmenes altos ese peso extra se nota.
  • Para una agencia en México o Argentina que automatiza el QA de formularios en varios portales, form-encoded con Base64 suele manejar esas cargas útiles con menos sobrecarga que empaquetarlas en JSON.

Preguntas frecuentes

¿Es obligatorio incluir json=1 en la solicitud?

No, pero conviene. Sin json=1 recibes una respuesta en texto plano del tipo OK|12345678; con él recibes un objeto JSON fácil de parsear. Funciona igual con las dos codificaciones de la solicitud.

Vengo de 2Captcha, ¿qué formato me conviene?

Form-encoded. La API original de 2Captcha usa esa codificación y CaptchaAI la mantiene compatible, así que tu código existente funciona sin tocar nada. El soporte JSON es un extra que puedes adoptar más adelante si te interesa.

¿Puedo enviar el CAPTCHA de imagen en Base64 sin multipart?

Sí. Usa method=base64 y pasa la imagen codificada en el campo body, tanto en JSON como en form-encoded. El multipart con files={} es solo una alternativa cuando prefieres subir el archivo tal cual.

¿Necesito fijar el encabezado Content-Type a mano?

No. Tanto requests en Python como Axios en Node.js ajustan el Content-Type según pases data=, json= o files=. Fijarlo manualmente es la causa más habitual de un cuerpo que el servidor no consigue analizar.

¿El endpoint de sondeo cambia según el formato de envío?

No. El sondeo a res.php es siempre un GET con parámetros de consulta, hayas enviado la tarea como JSON o como formulario. Cada solicitud es independiente, así que puedes mezclar codificaciones dentro del mismo proyecto sin problema.


Guías relacionadas

  • Referencia de códigos de error de la API

Elige la codificación que mejor encaje en tu stack. Prueba la API de CaptchaAI hoy.

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