Формат тела запроса на результат решения 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 входящего запроса.
Что выбрать: чек-лист по сценарию
- Пишете короткий одноразовый скрипт без лишних зависимостей — берите form-encoded, кода меньше.
- Встраиваете вызов в существующий REST-сервис с JSON-контрактом — берите JSON, он ложится в общий стиль остальных эндпоинтов.
- Загружаете файл CAPTCHA как есть — используйте multipart-форму, это самый прямой путь без раздувания размера запроса.
- Пакетно отправляете много Base64-изображений — form-encoded по умолчанию даёт чуть меньше накладных расходов на сериализацию.
- Работаете в TypeScript или другом типизированном JS-стеке — JSON удобнее: тело описывается обычным интерфейсом.
- Интегрируетесь со старой системой или унаследованным скриптом — form-encoded безопаснее: меньше риска несовместимости.
- Мигрируете с 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 с тем синтаксисом, который удобнее вашему стеку.