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.