Explainers

API CaptchaAI JSON против API форм: какой формат использовать

Формат тела запроса на результат решения CAPTCHA не влияет: API CaptchaAI одинаково принимает application/x-www-form-urlencoded и application/json, обрабатывает оба на одном и том же бэкенде и возвращает один и тот же токен. Разница — только в синтаксисе на вашей стороне, а не в скорости или точности решения. Ниже разбираем, где синтаксис реально расходится, когда держаться привычного querystring, а когда переходить на JSON, и на что обратить внимание при загрузке изображений.


Form-encoded и JSON рядом: один и тот же запрос, разный синтаксис

Form-encoded (формат по умолчанию)

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,
})

Content-Type: 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,
})

Content-Type: application/json

Обратите внимание: параметры и их названия не меняются — меняется только то, как библиотека сериализует тело запроса. requests в Python делает это сам, если вы передали data= или json= — вручную выставлять заголовок Content-Type не нужно.


Что реально отличается

  • Content-Type: form-encoded уходит как application/x-www-form-urlencoded, JSON — как application/json.
  • Структура данных: form-encoded умеет только плоские пары «ключ-значение»; JSON допускает вложенные объекты.
  • Двоичные данные: файл CAPTCHA грузится через multipart-форму; в JSON бинарные данные кодируются Base64 прямо в теле.
  • Массивы: form-encoded поддерживает их ограниченно, JSON — нативно.
  • Синтаксис в Python: data={} против json={} в requests.
  • Синтаксис в Node.js: qs.stringify() для form-encoded против передачи обычного объекта для JSON.
  • Совместимость: оба формата одинаково стабильны на любом клиенте — ни один не считается устаревшим или основным.

Ни один из форматов не даёт преимущества в очереди на решение — балансировка задач на стороне CaptchaAI не смотрит на Content-Type входящего запроса.


Что выбрать: чек-лист по сценарию

  1. Пишете короткий одноразовый скрипт без лишних зависимостей — берите form-encoded, кода меньше.
  2. Встраиваете вызов в существующий REST-сервис с JSON-контрактом — берите JSON, он ложится в общий стиль остальных эндпоинтов.
  3. Загружаете файл CAPTCHA как есть — используйте multipart-форму, это самый прямой путь без раздувания размера запроса.
  4. Пакетно отправляете много Base64-изображений — form-encoded по умолчанию даёт чуть меньше накладных расходов на сериализацию.
  5. Работаете в TypeScript или другом типизированном JS-стеке — JSON удобнее: тело описывается обычным интерфейсом.
  6. Интегрируетесь со старой системой или унаследованным скриптом — form-encoded безопаснее: меньше риска несовместимости.
  7. Мигрируете с 2Captcha и хотите минимальный дифф — оставляйте form-encoded, синтаксис запроса совпадает с тем, что уже работает.

Показательный пример: агентство, которое ведёт парсинг для нескольких клиентов и раньше работало через 2Captcha, обычно переносит существующие form-encoded скрипты почти без изменений — меняется только key и базовый URL. А когда та же команда добавляет отдельный Node.js-микросервис под новую интеграцию, для него куда естественнее сразу писать JSON-тело: он ложится в общий REST-контракт остального бэкенда и не требует ручной сборки query string. Держать оба варианта в одном проекте — нормальная практика, а не компромисс.


Как получить JSON-ответ независимо от формата запроса

Формат тела запроса и формат ответа — разные вещи. Добавьте параметр json=1, и вы получите структурированный JSON-ответ, даже если сам запрос отправлен как form-encoded:

# 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"}

Без json=1 сервер вернёт строку вида OK|12345678, которую придётся разбирать через split("|") — лишний повод получить IndexError на нестандартном ответе (например, при ошибке). С json=1 вы работаете с обычным словарём и проверяете status и request напрямую. Ставьте json=1 по умолчанию во всех интеграциях, независимо от формата тела запроса.


Пример на Python: отправка и опрос результата

Полный цикл — отправить задачу и опросить результат — выглядит так в form-encoded варианте:

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,
})

А так — тот же самый цикл, но с 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,
})

Опрос результата (/res.php) всегда идёт через GET с параметрами запроса — независимо от того, каким был первый запрос. Это единственное место, где формат не выбирается: опрос JSON-телом технически невозможен, потому что эндпоинт читает данные из query string.


Пример на Node.js: тот же паттерн

Form-encoded вариант на axios:

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;

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;

В axios разница сводится к одной строке: qs.stringify() против передачи обычного объекта — сама библиотека проставляет нужный Content-Type автоматически. Для TypeScript-проекта JSON-вариант обычно удобнее: объект тела можно типизировать интерфейсом, а не собирать строку вручную.


Загрузка изображений CAPTCHA: здесь формат уже имеет значение

Для текстовых и графических CAPTCHA (тип post / base64) выбор формата — это не только стиль кода, а ещё и вопрос размера полезной нагрузки. Прямая загрузка файла через multipart-форму выглядит так:

# 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 целиком, картинку кодируют в Base64 и кладут строкой в поле body:

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,
})

Тот же Base64 работает и в form-encoded теле — метод 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,
})

Multipart-загрузка файла — самый прямой путь: файл идёт как есть, без раздувания размера. Base64, наоборот, увеличивает объём полезной нагрузки примерно на треть — не критично для отдельной картинки CAPTCHA, но заметно при пакетной обработке сотен изображений в очереди.


Частые ошибки при переключении формата

  • Передан json={}, но в теле нет "json": 1 — ответ приходит обычной строкой, а не JSON. Добавьте "json": 1 в тело запроса.
  • В одном запросе смешаны data= и json= (Python) — тело собирается некорректно. Используйте только один из параметров.
  • Content-Type выставлен вручную и не совпадает с телом — сервер не может разобрать запрос. Не трогайте заголовок, HTTP-библиотека выставит его сама.
  • JSON-тело отправлено на /res.php — опрос ожидает параметры в query string, а не тело. Всегда опрашивайте /res.php через GET с параметрами.

Частые вопросы

Влияет ли формат запроса на скорость или точность решения?

Нет. Оба формата обрабатываются одним и тем же бэкендом и дают идентичный результат — разница только в том, как клиент сериализует данные перед отправкой.

Как понять, какой Content-Type реально уходит с запросом?

Проще всего перехватить трафик прокси вроде Charles Proxy или Fiddler, либо временно залогировать заголовки запроса в самом HTTP-клиенте. Если вы передаёте data= в requests, библиотека сама поставит application/x-www-form-urlencoded; для json=application/json. Ручная установка заголовка нужна редко и чаще создаёт рассинхрон, чем решает проблему.

Обязательно ли переписывать рабочие form-encoded скрипты на JSON при миграции с 2Captcha?

Нет. Формат запроса — это не часть совместимости с 2Captcha, а отдельная настройка API CaptchaAI. Форма прекрасно продолжает работать; переходить на JSON стоит только тогда, когда это упрощает интеграцию именно на вашей стороне (например, вписывается в общий REST-слой сервиса).

Что делать, если сервер вернул строку OK|12345678 вместо ожидаемого JSON?

Значит, в запросе не было "json": 1 — добавьте этот параметр в тело, и ответ станет структурированным словарём с полями status и request, который не нужно разбирать вручную через split("|").

Можно ли отправить изображение CAPTCHA в JSON без Base64?

Нет, JSON не умеет передавать бинарные данные напрямую — изображение нужно закодировать в Base64 и положить строку в поле body. Если важно не раздувать объём запроса, используйте multipart-загрузку через form-encoded вместо этого.


Связанные материалы


Формат — это деталь реализации, а не компромисс по качеству: попробуйте API CaptchaAI с тем синтаксисом, который удобнее вашему стеку.

Комментарии для этой статьи отключены.