Калейдоскоп
Задачи со сдвигом пазла. Бета.

Перемещайте слайдер
1. Создание задачи, версия 1
https://api.capsola.cloud/createЗапрос
Ключ передаётся в заголовке X-API-Key, тело — JSON.
{
"type": "PazlCaptcha",
"task": "TASK_BASE_64"
}
typestring обязательный Тип задачи — PazlCaptcha.
taskbase64 обязательный Полный HTML-код страницы.
app_idstringИдентификатор приложения разработчика — выдаётся в партнёрском разделе.
Ответ
{
"status": 1,
"response": "9051d4b4-0000-44d3-a4c2-db0215227862"
}
statusnumber1 — задача принята, 0 — ошибка.
responsestringИдентификатор задачи или код ошибки.
1.1. Создание задачи, версия 2
Версия 2 принимает готовое изображение и список перестановок — HTML страницы не нужен.
https://api.capsola.cloud/createЗапрос
{
"type": "PazlCaptchaV2",
"image": "IMAGE_BASE_64",
"task": "[23,12,12,23]"
}
typestring обязательный Тип задачи — PazlCaptchaV2.
imagebase64 обязательный Изображение капчи.
taskstring обязательный Порядковый список перестановок.
app_idstringИдентификатор приложения разработчика — выдаётся в партнёрском разделе.
Ответ
{
"status": 1,
"response": "9051d4b4-0000-44d3-a4c2-db0215227862"
}
statusnumber1 — задача принята, 0 — ошибка.
responsestringИдентификатор задачи или код ошибки.
2. Получение результата
https://api.capsola.cloud/resultЗапрос
{
"id": "9051d4b4-0000-44d3-a4c2-db0215227862"
}
idstring обязательный Идентификатор задачи из ответа на /create.
Ответ
{
"status": 1,
"response": "12"
}
statusnumber1 — задача решена, 0 — ошибка.
responsestringНомер шага, на котором пазл сложен, — цикл кликов начинайте с 1. Либо код ошибки.
Ответ CAPCHA_NOT_READY означает, что задача ещё решается. Опрашивайте так:
- первый запрос — через 1 секунду после
/create: у большинства капч ответ к этому моменту уже готов; - дальше — каждые 2 секунды, пока не придёт ответ или другая ошибка, но не дольше 90 секунд.
Подробнее — про соединение, таймауты и повторы — в разделе «Интеграция».
Примеры использования
Примеры — для версии 2: картинка капчи берётся из файла pazl.png, в task —
список перестановок со страницы. Для версии 1 отличается только тело
/create: {"type": "PazlCaptcha", "task": "<HTML страницы в Base64>"}.
import base64
import time
import requests
API = 'https://api.capsola.cloud'
# Один клиент на все запросы — соединение переиспользуется.
session = requests.Session()
session.headers['X-API-Key'] = 'API_KEY'
def b64(path):
with open(path, 'rb') as f:
return base64.b64encode(f.read()).decode()
created = session.post(f'{API}/create', json={
'type': 'PazlCaptchaV2',
'image': b64('pazl.png'),
'task': '[23,12,12,23]',
}, timeout=15).json()
print(created)
if created['status'] == 1:
# Через 1 с, дальше каждые 2 с — не дольше 90 с.
for delay in [1] + [2] * 45:
time.sleep(delay)
result = session.post(f'{API}/result', json={'id': created['response']}, timeout=10).json()
print(result)
if result['status'] == 1 or result['response'] != 'CAPCHA_NOT_READY':
break
<?php
// Один дескриптор cURL на все запросы — соединение переиспользуется.
$ch = curl_init();
function call($ch, string $path, array $payload): array
{
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.capsola.cloud' . $path,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'X-API-Key: API_KEY'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 15,
]);
return json_decode((string) curl_exec($ch), true);
}
$created = call($ch, '/create', [
'type' => 'PazlCaptchaV2',
'image' => base64_encode(file_get_contents('pazl.png')),
'task' => '[23,12,12,23]',
]);
var_dump($created);
if ($created['status'] === 1) {
// Через 1 с, дальше каждые 2 с — не дольше 90 с.
foreach (array_merge([1], array_fill(0, 45, 2)) as $delay) {
usleep((int) ($delay * 1000000));
$result = call($ch, '/result', ['id' => $created['response']]);
var_dump($result);
if ($result['status'] === 1 || $result['response'] !== 'CAPCHA_NOT_READY') {
break;
}
}
}
// Node 18+: встроенный fetch сам переиспользует соединение.
const API = "https://api.capsola.cloud";
const HEADERS = { "Content-Type": "application/json", "X-API-Key": "API_KEY" };
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function call(path, payload) {
const res = await fetch(API + path, {
method: "POST",
headers: HEADERS,
body: JSON.stringify(payload),
signal: AbortSignal.timeout(15000),
});
return res.json();
}
function b64(path) {
return require("node:fs").readFileSync(path).toString("base64");
}
async function main() {
const created = await call("/create", {
type: "PazlCaptchaV2",
image: b64("pazl.png"),
task: "[23,12,12,23]",
});
console.log(created);
if (created.status !== 1) return;
// Через 1 с, дальше каждые 2 с — не дольше 90 с.
for (const delay of [1000, ...Array(45).fill(2000)]) {
await sleep(delay);
const result = await call("/result", { id: created.response });
console.log(result);
if (result.status === 1 || result.response !== "CAPCHA_NOT_READY") break;
}
}
main().catch(console.error);
// .NET 6+, консольное приложение.
using System.Net.Http.Json;
using System.Text.Json;
const string Api = "https://api.capsola.cloud";
// Один HttpClient на всё приложение — соединение переиспользуется.
var http = new HttpClient { Timeout = TimeSpan.FromSeconds(15) };
http.DefaultRequestHeaders.Add("X-API-Key", "API_KEY");
async Task<JsonElement> Call(string path, object payload)
{
using var res = await http.PostAsJsonAsync(Api + path, payload);
return await res.Content.ReadFromJsonAsync<JsonElement>();
}
string B64(string path) => Convert.ToBase64String(File.ReadAllBytes(path));
var created = await Call("/create", new
{
type = "PazlCaptchaV2",
image = B64("pazl.png"),
task = "[23,12,12,23]",
});
Console.WriteLine(created);
if (created.GetProperty("status").GetInt32() == 1)
{
// Через 1 с, дальше каждые 2 с — не дольше 90 с.
foreach (var delay in new[] { 1000 }.Concat(Enumerable.Repeat(2000, 45)))
{
await Task.Delay(delay);
var result = await Call("/result", new { id = created.GetProperty("response").GetString() });
Console.WriteLine(result);
if (result.GetProperty("status").GetInt32() == 1
|| result.GetProperty("response").GetString() != "CAPCHA_NOT_READY") break;
}
}
package main
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"net/http"
"time"
)
const api = "https://api.capsola.cloud"
// Один клиент на все запросы — соединение переиспользуется.
var client = &http.Client{Timeout: 15 * time.Second}
type answer struct {
Status int `json:"status"`
Response string `json:"response"`
}
func call(path string, payload any) (a answer, err error) {
body, _ := json.Marshal(payload)
req, _ := http.NewRequest(http.MethodPost, api+path, bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "API_KEY")
res, err := client.Do(req)
if err != nil {
return a, err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&a)
return a, err
}
func b64(path string) string {
data, err := os.ReadFile(path)
if err != nil {
panic(err)
}
return base64.StdEncoding.EncodeToString(data)
}
func main() {
created, err := call("/create", map[string]string{
"type": "PazlCaptchaV2",
"image": b64("pazl.png"),
"task": "[23,12,12,23]",
})
fmt.Printf("%+v %v\n", created, err)
if err != nil || created.Status != 1 {
return
}
// Через 1 с, дальше каждые 2 с — не дольше 90 с.
delays := []time.Duration{time.Second}
for i := 0; i < 45; i++ {
delays = append(delays, 2*time.Second)
}
for _, delay := range delays {
time.Sleep(delay)
result, err := call("/result", map[string]string{"id": created.Response})
fmt.Printf("%+v %v\n", result, err)
if err != nil || result.Status == 1 || result.Response != "CAPCHA_NOT_READY" {
break
}
}
}