Интеграция

Как подключить API, чтобы ответы приходили быстро, а интеграция не ломалась на ошибках.

На этой странице — правила, от которых зависит скорость и надёжность: когда опрашивать результат, как держать соединение, что делать с каждой ошибкой. Если интеграцию пишет ИИ-ассистент, дайте ему эту страницу целиком — в конце есть готовое задание для него.

Как проходит задача

  1. POST /create принимает капчу и сразу возвращает идентификатор задачи.
  2. POST /result по этому идентификатору возвращает ответ или CAPCHA_NOT_READY, если задача ещё решается.

Сколько ждать ответа, зависит от капчи:

КапчаКогда готов ответ
Большинствоменьше чем за секунду
Сложныенесколько секунд

Поэтому главное правило — первый опрос через 1 секунду после /create: к этому моменту ответ обычно уже готов, а пауза длиннее — потеря времени на каждой задаче.

Что отправлять

Тело /create — JSON с полем type и полями своего типа капчи. Остальное — опрос, соединение, ошибки — у всех типов одинаковое.

КапчаtypeПоля /createОтвет /result
СилуэтыSmartCaptchaclick, task — картинкикоординаты точек в порядке клика: coordinates:x=..,y=..;...
Калейдоскоп, версия 1PazlCaptchatask — HTML страницыномер шага, на котором пазл сложен
Калейдоскоп, версия 2PazlCaptchaV2image — картинка, task — список перестановокномер шага, на котором пазл сложен
ТекстоваяTextCaptchatask — картинкатекст с картинки

Картинки и HTML передаются в Base64. У всех типов есть необязательное поле app_id — идентификатор приложения разработчика.

График опроса

ШагКогдаЗачем
1через 1 с после ответа /createзабрать ответ — обычно он уже готов
2дальше каждые 2 сдождаться решения сложной капчи
—после 90 с без ответапрекратить опрос, взять у сайта новую капчу

Опрашивать чаще, чем раз в 2 секунды, не нужно: сложные капчи решаются секундами, и частый опрос их не ускорит. Опрос заканчивается, как только пришёл status: 1 или любой ответ, кроме CAPCHA_NOT_READY.

Каждую принятую задачу опрашивайте до конца — не бросайте её на середине.

Соединение

  • Одно соединение на все запросы. Создайте HTTP-клиент один раз и переиспользуйте его: requests.Session в Python, общий fetch или agent в Node, один дескриптор cURL в PHP, один HttpClient в C#, один http.Client в Go. Новое TLS-соединение на каждый запрос — это лишние десятки миллисекунд на каждом шаге опроса.
  • HTTP/2 поддерживается — можно отправлять много запросов параллельно по одному соединению.
  • Сервер закрывает простаивающее соединение примерно через 10 секунд. Клиент должен уметь открыть его заново: почти все HTTP-библиотеки делают это сами, если не держать сокет вручную.
  • Таймауты: подключение — 5 с, ответ на /create — 15 с, на /result — 10 с. Без таймаутов зависший запрос остановит всю очередь задач.

Запрос

  • Ключ — только в заголовке X-API-Key.
  • Тело — JSON с заголовком Content-Type: application/json.
  • Картинки — исходные байты в Base64, без префикса data:image/.... Не пересжимайте и не перерисовывайте их: пересжатие теряет детали, и капча решается дольше и хуже.
  • Форматы — PNG или JPEG, до 2 МБ на картинку. Если JPEG отвергается с ERROR_IMAGE_TYPE_NOT_SUPPORTED, отправьте его в PNG.

Ошибки и повторы

ОтветЧто делать
CAPCHA_NOT_READYпродолжить опрос по графику
CAPCHA_NOT_AVAILABLE на /resultкапча не решена — взять новую и создать новую задачу
ERROR_NO_SUCH_TASK_IDзадачи нет или она устарела — создать новую
TOO_MANY_REQUESTS, SERVER_ERROR, ERROR_SERVER, ERROR_NO_ACTIVE_SERVER на /create, обрыв сети, таймаутповторить тот же запрос через 1, 2, 4 с; после трёх неудач — остановиться
ERROR_TASK_LOOP_DETECTEDперестать отправлять эту капчу — взять у сайта новую
ERROR_ZERO_BALANCEостановить отправку до пополнения баланса
ERROR_KEY_DOES_NOT_EXIST, ERROR_IP_NOT_ALLOWED, ERROR_USER_DISABLEDостановиться: это настройка, а не сбой
ошибки картинок (ERROR_IMAGE_…, ERROR_BODY_…, ERROR_EMPTY_BODY, ERROR_DUPLICATE_DATA)исправить запрос, повторять без изменений бессмысленно

Полный список — в кодах ошибок.

Повтор /result после обрыва сети безопасен: для одной задачи он всегда возвращает один и тот же ответ.

Не отправляйте одну и ту же капчу по кругу. Если сайт не принял ответ, возьмите у него новую капчу. Десять одинаковых задач подряд с одного адреса без успешного результата блокируют эту капчу на 15 минут (ERROR_TASK_LOOP_DETECTED). А если ответ оказался неверным — отметьте задачу кнопкой «Неверный ответ» в личном кабинете, на странице «Задачи за сегодня»: так капча быстрее перестанет решаться неправильно.

Чек-лист

  • Ключ в заголовке X-API-Key, тело — JSON.
  • Картинки отправляются исходными байтами, без пересжатия.
  • Первый /result — через 1 с после /create.
  • Дальше — каждые 2 с, не дольше 90 с.
  • Один HTTP-клиент на все запросы, с таймаутами.
  • Сетевые ошибки и TOO_MANY_REQUESTS повторяются с паузой, остальные ошибки — по таблице.
  • Одна и та же капча не отправляется по кругу.

Пример

import base64
import time

import requests

API = 'https://api.capsola.cloud'

# Один клиент на все запросы: соединение переиспользуется.
session = requests.Session()
session.headers['X-API-Key'] = 'API_KEY'

# Опрос: через 1 с, дальше каждые 2 с — всего около 90 с.
POLL_DELAYS = [1] + [2] * 45
RETRYABLE = {'TOO_MANY_REQUESTS', 'SERVER_ERROR', 'ERROR_SERVER'}
# ERROR_NO_ACTIVE_SERVER на /create — все решатели заняты, повторяем, как SERVER_ERROR.
# На /result он значит «капча не решена», и повтор не поможет.
RETRYABLE_CREATE = RETRYABLE | {'ERROR_NO_ACTIVE_SERVER'}


def call(path, payload, timeout):
    """Запрос с повтором при сетевых сбоях: паузы 1, 2, 4 с."""
    retryable = RETRYABLE_CREATE if path == '/create' else RETRYABLE
    for pause in (1, 2, 4, None):
        try:
            answer = session.post(f'{API}{path}', json=payload, timeout=(5, timeout)).json()
            if answer.get('response') not in retryable:
                return answer
        except requests.RequestException:
            pass
        if pause is None:
            raise RuntimeError(f'{path}: сервис не отвечает')
        time.sleep(pause)


def solve(payload):
    created = call('/create', payload, 15)
    if created['status'] != 1:
        raise RuntimeError(created['response'])

    for delay in POLL_DELAYS:
        time.sleep(delay)
        result = call('/result', {'id': created['response']}, 10)
        if result['status'] == 1:
            return result['response']
        if result['response'] != 'CAPCHA_NOT_READY':
            raise RuntimeError(result['response'])
    raise TimeoutError('нет ответа за 90 секунд')


def b64(url):
    return base64.b64encode(requests.get(url, timeout=15).content).decode()


# Тело /create зависит от типа капчи — см. «Что отправлять».
print(solve({
    'type': 'SmartCaptcha',
    'click': b64('https://capsola.cloud/examples/smart/click.png'),
    'task': b64('https://capsola.cloud/examples/smart/task.png'),
}))

Задание для ИИ-ассистента

Если интеграцию пишет ИИ, скопируйте ему этот текст — вместе со ссылкой на документацию одним файлом: /llms-full.txt.

text
Подключи Capsola API для решения капчи. Документация целиком:
https://front.capsola.space/llms-full.txt

Прежде чем писать код, спроси меня, какую капчу нужно решать, если я
не указал это сам:
- SmartCaptcha — Силуэты, клик по иконкам;
- PazlCaptcha или PazlCaptchaV2 — Калейдоскоп, сдвиг слайдера;
- TextCaptcha — Текстовая, текст с картинки.
Поля запроса и формат ответа возьми со страницы этого типа.

Обязательные правила:
1. POST https://api.capsola.cloud/create, тело JSON с полем "type" и
   полями выбранного типа, ключ — в заголовке X-API-Key. Картинки —
   исходные байты в Base64, без пересжатия и без префикса data:.
2. Первый POST /result {"id": "<id>"} — через 1 с после /create.
   Если CAPCHA_NOT_READY — дальше каждые 2 с,
   не дольше 90 с. Чаще раза в 2 секунды не опрашивать.
3. Один HTTP-клиент на все запросы (keep-alive), таймауты: подключение 5 с,
   /create 15 с, /result 10 с. Клиент должен переоткрывать соединение,
   закрытое сервером после ~10 с простоя.
4. TOO_MANY_REQUESTS, SERVER_ERROR, ERROR_SERVER, ERROR_NO_ACTIVE_SERVER
   на /create, сетевые ошибки — повтор того же запроса через 1, 2, 4 с,
   потом остановка.
   CAPCHA_NOT_AVAILABLE на /result — новая капча и новая задача.
   ERROR_TASK_LOOP_DETECTED — не отправлять эту капчу снова.
   Ошибки ключа, IP, баланса и картинок — не повторять.
5. Ответ /result зависит от типа: SmartCaptcha — строка
   "coordinates:x=..,y=..;..." (точки в порядке клика), PazlCaptcha и
   PazlCaptchaV2 — номер шага, TextCaptcha — текст с картинки.
6. Логировать id задачи, время /create и время получения ответа.