Node.js SDK
Официальная библиотека CaptchaSonic для Node.js и TypeScript — современная, на основе Promise, с несколькими транспортами (gRPC / ConnectRPC / HTTP).
CaptchaSonic Node.js SDK (captchasonic) — современная, основанная на Promise и ориентированная на TypeScript библиотека для решения CAPTCHA в больших объёмах. Каждый метод возвращает Promise, поставляется с полными определениями типов и работает через три взаимозаменяемых транспорта: нативный gRPC (самый быстрый, только Node.js), ConnectRPC (работает в Node.js и в браузерах) и обычный HTTP/JSON. Временные ошибки повторяются автоматически с экспоненциальной задержкой.
Работает в Node.js ≥ 18 и в современных браузерах, совместима с Express, Fastify, Next.js, React, Vue и Vite.
Установка
npm install captchasonic
# или
yarn add captchasonic
# или
pnpm add captchasonic
Требования
| Требование | Примечания |
|---|---|
| Node.js | ≥ 18.0.0 (необходимо для транспорта grpc) |
| Формат модуля | ES Module — пакет содержит "type": "module" |
| Браузер | Любой современный браузер с fetch; используйте транспорт connect или http |
Пакет публикуется только как ESM. В ESM-проекте ("type": "module" в package.json или файл .mjs) импортируйте напрямую:
import { CaptchaSonic } from "captchasonic";
Из файла CommonJS загружайте его через динамический import():
// CommonJS (.cjs / "type": "commonjs")
const { CaptchaSonic } = await import("captchasonic");
TIP
Если вы используете TypeScript, установите "module": "NodeNext" (или "ESNext") и "moduleResolution": "NodeNext" в tsconfig.json, чтобы встроенные определения типов корректно разрешались.
Аутентификация
Создайте API-ключ в панели CaptchaSonic и передайте его первым аргументом конструктора:
import { CaptchaSonic } from "captchasonic";
const solver = new CaptchaSonic("YOUR_API_KEY");
Никогда не храните ключи в системе контроля версий. Считывайте ключ из окружения:
import { CaptchaSonic } from "captchasonic";
const solver = new CaptchaSonic(process.env.CAPTCHASONIC_API_KEY);
Быстрый старт
У каждого типа captcha есть отдельный помощник solve*, который отправляет задачу и возвращает результат. Для задач с изображениями отдельного шага опроса не требуется — SDK делает это за вас.
import { CaptchaSonic } from "captchasonic";
const solver = new CaptchaSonic(process.env.CAPTCHASONIC_API_KEY);
const result = await solver.solveRecaptchaV2({
images: tiles, // Uint8Array[] | Buffer[] | file-path[]
question: "traffic lights",
});
// Выбор по сетке возвращается как индексы плиток
console.log(result.typedSolution?.grid?.objects); // напр. [2, 4, 7]
Возвращает: методы для изображений возвращают результат, ответ которого находится в
typedSolution(здесьtypedSolution.grid.objects— индексы выбранных плиток); методы на основе токена возвращают токен в картеsolution.
TIP
Методы на основе токена (Turnstile, Cloudflare, токен reCAPTCHA v2/v3, токен popular-captcha) отправляют задачу автоматизации браузера и опрашивают результат внутри, пока токен не будет готов — по умолчанию до 120 секунд.
Поддерживаемые типы captcha
Все методы для изображений принимают единый типизированный объект параметров. Изображения могут быть Uint8Array, Node Buffer или строкой с путём к файлу (пути к файлам поддерживаются только в Node.js).
reCAPTCHA v2 (изображение)
await solver.solveRecaptchaV2({
images: tiles, // обычно 9 плиток для сетки 3×3
question: "traffic lights", // обычный текст или код класса Google, напр. "/m/015qff"
});
// → result.typedSolution.grid.objects (number[] — индексы выбранных плиток)
PopularCaptcha (изображение в стиле hCaptcha)
await solver.solvePopularCaptcha({
images: tiles, // 1–64 плитки
question: "Click each image with a cat",
questionType: "objectClassify", // "objectClassify" | "grid" | "objectClick" | "objectDrag"
examples, // необязательные эталонные изображения для objectClick
websiteURL: "https://example.com",
});
// objectClassify/grid → typedSolution.grid.objects
// objectClick → typedSolution.click
// objectDrag → typedSolution.drag
GeeTest
// сетка из девяти (требуются question и images)
await solver.solveGeetest({ type: "nine", question: "Select all bicycles", images: tiles });
// click / icon (требуются question и images)
await solver.solveGeetest({ type: "click", question: "the bear", images: tiles });
// слайд-пазл (фрагмент + фон)
await solver.solveGeetest({ type: "slide", images: [piece], examples: [background] });
// пазлы с перестановкой
await solver.solveGeetest({ type: "match" });
await solver.solveGeetest({ type: "winlinze" });
Возвращает: типы grid/click попадают в typedSolution.grid.objects (или typedSolution.click); slide возвращает typedSolution.slide.x.
Допустимые псевдонимы type:
| Каноническое | Псевдонимы |
|---|---|
| nine-grid | "nine", "geetest_nine", "9" |
| click / icon | "click", "geetest_click", "icon" |
| slide | "slide", "geetest_slide" |
| match | "match", "geetest_match" |
| winlinze | "winlinze", "geetest_winlinze" |
OCR / изображение-в-текст
await solver.solveOcr({ images: [img] }); // общий OCR
await solver.solveOcr({ images: [img], module: "mtcaptcha", maxLength: 4 });
await solver.solveOcr({ images: imgs, module: "bls", numeric: true, maxLength: 3 });
// → result.typedSolution.text.texts[0]
| Параметр | Тип | Примечания |
|---|---|---|
module | "common" | "mtcaptcha" | "bls" | "morocco" | По умолчанию "common" |
numeric | boolean | Только цифры (автоматически для "bls") |
caseSensitive | boolean | Сохранять регистр букв |
minLength / maxLength | number | Границы длины |
TikTok
await solver.solveTikTok({ type: "click", question: "Select the shape", images });
await solver.solveTikTok({ type: "whirl", question: "Rotate to match", images, examples }); // examples обязательны
await solver.solveTikTok({ type: "slide", question: "Slide to fit", images, examples }); // examples обязательны
Возвращает: click попадает в typedSolution.click; whirl/slide возвращают typedSolution.slide.x.
type принимает "click"/"tiktok_click", "whirl"/"tiktok_whirl", "slide"/"tiktok_slide".
Binance
await solver.solveBinance({ type: "grid", question: "Select the bicycle", images });
await solver.solveBinance({ type: "slide", images: [puzzle], examples: [background] });
Возвращает: grid попадает в typedSolution.grid.objects; slide возвращает typedSolution.slide.x.
type принимает "grid"/"binance_grid" и "slide"/"binance_slide".
AWS WAF
solveAwsWaf принимает позиционные аргументы. question форматируется как "type:category:target".
await solver.solveAwsWaf(tiles, "grid:vehicles:cars");
Возвращает: индексы выбранных плиток в typedSolution.grid.objects.
Слайд-изображение (локально, без ИИ)
Определяет смещение слайда локально с помощью обнаружения контуров. Принимает одно объединённое изображение или [background, piece].
const r = await solver.solveSlideImage({ images: ["slide_bg.png", "piece.png"] });
console.log(r.typedSolution?.slide?.x); // смещение в пикселях, напр. 142
Возвращает: смещение слайда в пикселях в typedSolution.slide.x.
Методы на основе токена (автоматизация браузера)
Эти методы отправляют задачу и опрашивают результат внутри, пока не будет получен токен (до таймаута опроса, по умолчанию 120 с).
await solver.solveTurnstile({ websiteURL, websiteKey, proxy }); // proxy необязателен
await solver.solveRecaptchaV2Token({ websiteURL, websiteKey, proxy }); // proxy необязателен
await solver.solveRecaptchaV3Token({ websiteURL, websiteKey, proxy }); // proxy необязателен
await solver.solvePopularCaptchaToken({ websiteURL, websiteKey, proxy, metadata }); // proxy необязателен
await solver.solveCloudflare({ websiteURL, websiteKey, proxy }); // proxy ОБЯЗАТЕЛЕН
Возвращает: токен в карте solution ответа (например, result.solution.token или result.solution.gRecaptchaResponse, в зависимости от captcha).
Использование с TypeScript
SDK экспортирует типы для каждого объекта параметров и для ответов. Импортируйте их через import type.
import { CaptchaSonic } from "captchasonic";
import type { SolveGeetestOptions, GetTaskResultResponse } from "captchasonic";
const solver = new CaptchaSonic(process.env.CAPTCHASONIC_API_KEY!);
const opts: SolveGeetestOptions = {
type: "nine",
question: "Select all bicycles",
images: tiles,
};
const result = await solver.solveGeetest(opts);
console.log(result.typedSolution?.grid?.objects);
Экспортируемые типы
import type {
CaptchaSonicOptions,
ImageInput,
SolvePopularCaptchaOptions,
SolveRecaptchaV2Options,
SolveGeetestOptions,
SolveOcrOptions,
SolveTikTokOptions,
SolveBinanceOptions,
SolveTurnstileOptions,
SolvePopularCaptchaTokenOptions,
SolveRecaptchaV2TokenOptions,
SolveRecaptchaV3TokenOptions,
SolveCloudflareOptions,
SolveSlideImageOptions,
GeetestSubtype,
TikTokSubtype,
BinanceSubtype,
Task,
CreateTaskResponse,
GetTaskResultResponse,
} from "captchasonic";
ImageInput — это Uint8Array | Buffer | string.
Поддержка прокси
Методы на основе токена / автоматизации браузера принимают необязательную строку proxy в формате http://user:pass@host:port:
await solver.solveTurnstile({
websiteURL: "https://example.com",
websiteKey: "0x4AAAAAAA...",
proxy: "http://user:[email protected]:8080",
});
WARNING
solveCloudflare всегда требует прокси — поле proxy для этого метода обязательно. Остальные методы на основе токена работают без прокси, если proxy опущен.
Для корпоративного hCaptcha можно также передать metadata (rqdata, rqtoken, fingerprint) в solvePopularCaptchaToken.
Конфигурация
Передайте объект параметров вторым аргументом конструктора. Поддерживаются только перечисленные ниже параметры.
const solver = new CaptchaSonic("YOUR_API_KEY", {
transport: "connect", // "grpc" (по умолчанию) | "connect" | "http"
timeout: 180_000, // макс. время ожидания опроса в мс (псевдоним: timeoutMs); по умолчанию на вызов 30000
pollingInterval: 5_000, // частота опроса в мс (по умолчанию 2000)
baseUrl: "https://api.captchasonic.com", // переопределение endpoint (псевдоним: url)
});
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
transport | "grpc" | "connect" | "http" | "grpc" | Сетевой протокол (см. таблицу ниже) |
timeout / timeoutMs | number | 30000 на вызов | Таймаут запроса; timeout также ограничивает время ожидания опроса |
pollingInterval | number | 2000 | Как часто опрашиваются задачи с токеном |
url / baseUrl | string | зависит от транспорта | Переопределение endpoint API |
Транспорты
| Транспорт | Окружения | Протокол |
|---|---|---|
grpc | Только Node.js | Бинарный gRPC поверх HTTP/2 — наименьшая задержка, отправляет изображения как сырые бинарные данные |
connect | Node.js и браузеры | ConnectRPC поверх fetch |
http | Node.js и браузеры | Обычный REST/JSON поверх fetch |
TIP
В браузере используйте connect (рекомендуется) или http. Нативный gRPC требует Node.js. С connect/http изображения автоматически кодируются в base64 перед отправкой; с grpc они отправляются как сырые бинарные данные без накладных расходов.
Обработка ошибок
Все сбои на уровне API выбрасывают SonicError, расширяющий встроенный Error. Он содержит числовой errorId и устанавливает name в соответствующее имя ошибки.
import { CaptchaSonic, SonicError } from "captchasonic";
try {
const result = await solver.solveGeetest({ type: "nine", question: "bicycles", images });
} catch (err) {
if (err instanceof SonicError) {
console.error(err.errorId); // 1–6
console.error(err.name); // напр. "InvalidApiKeyError"
console.error(err.message);
} else {
throw err; // сеть / непредвиденная
}
}
errorId | name | Причина | Действие |
|---|---|---|---|
| 1 | InvalidApiKeyError | API-ключ отсутствует или недействителен | Проверьте ключ в панели управления |
| 2 | InsufficientBalanceError | Недостаточно кредитов | Пополните баланс |
| 3 | DailyLimitExceededError | Превышена дневная квота | Дождитесь сброса или повысьте тариф |
| 4 | MinuteLimitExceededError | Достигнут лимит запросов в минуту | Сделайте паузу и повторите позже |
| 5 | QuotaExceededError | Квота тарифа исчерпана | Обновите тариф |
| 6 | PlanExpiredError | Подписка истекла | Продлите подписку |
TIP
Временные ошибки gRPC повторяются автоматически с экспоненциальной задержкой (до 3 попыток), поэтому обычно достаточно обрабатывать только перечисленные выше случаи SonicError.
Вспомогательные методы аккаунта
const balance = await solver.getBalance(); // → number (USD)
const health = await solver.healthCheck(); // → { healthy: boolean, version: string }
Низкоуровневые методы для задач доступны, если нужен прямой контроль над отправкой и опросом:
const created = await solver.createTask(task); // отправить Partial<Task>
const result = await solver.getTaskResult(taskId); // опросить результат
Устранение неполадок
require is not defined / Cannot use import statement outside a module — пакет только ESM. Используйте import в ESM-проекте или await import("captchasonic") из CommonJS. См. Установка.
Транспорт grpc не работает в браузере — нативный gRPC доступен только в Node.js. Переключитесь на transport: "connect" или transport: "http".
InvalidApiKeyError при каждом вызове — убедитесь, что ключ передан первым аргументом конструктора и не равен undefined (например, из-за отсутствующей переменной окружения).
Метод на основе токена истекает по таймауту — задачи с токеном опрашиваются до timeout мс (по умолчанию 120000). Увеличьте timeout и проверьте, что websiteURL / websiteKey совпадают с целевой страницей. Для Cloudflare требуется действительный proxy.
Изображения по пути к файлу не загружаются — пути к файлам читаются синхронно и доступны только в Node.js; в браузере передавайте Uint8Array.