npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@captcha-solver-api/javascript-sdk

v1.0.1

Published

Official JavaScript SDK for the Captcha Solver API. Solve reCAPTCHA v2, Cloudflare Turnstile, GeeTest, Tencent, and image captchas.

Downloads

259

Readme

Captcha Solver JavaScript SDK

javascript-sdk-banner

npm version tests Coverage Status Node.js npm downloads TypeScript license GitHub Release Python SDK

Full API reference (all endpoints, error codes, captcha-type details): https://captcha-solver.com/en/docs/captcha-types

Table of Contents

Installation

npm install @captcha-solver-api/javascript-sdk

Configuration

The client always takes the API key as an explicit argument -- it does not read environment variables on its own. Read CAPTCHA_API_KEY yourself and pass it in:

export CAPTCHA_API_KEY=your_api_key
import { CaptchaClient } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: process.env.CAPTCHA_API_KEY });

Or just pass the key directly, without an environment variable:

const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });

Quick Start

Solve a reCAPTCHA v2 in 4 lines.

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.RecaptchaV2Proxyless({
  websiteURL: 'https://example.com/login',
  websiteKey: 'YOUR_WEBSITE_KEY'
});
const result = await captchaSolver.solve(task);
console.log(result.gRecaptchaResponse);

Runnable versions of every example below live in examples/async (async/await style) and examples/sync (promise-chain style, .then()/.catch()) -- both call the same CaptchaClient, since JavaScript has no blocking HTTP client to mirror requests vs. httpx the way the Python SDK does. See Running the examples.

Supported CAPTCHA Types

| Type | Proxyless | With Proxy | |---|---|---| | reCAPTCHA v2 | ✅ | ✅ | | reCAPTCHA v2 Enterprise | ✅ | ✅ | | reCAPTCHA v3 | ✅ | ❌ | | Cloudflare Turnstile | ✅ | ✅ | | GeeTest v3 | ✅ | ✅ | | GeeTest v4 | ✅ | ✅ | | Image to Text | ✅ | ❌ | | Yandex SmartCaptcha | ✅ | ✅ | | Coordinates (click captcha) | ✅ | ❌ | | Tencent | ✅ | ✅ |

Other supported API task types

Use GenericTask for any task type supported by the API that does not have a dedicated convenience class:

const task = new Tasks.GenericTask({
  type: 'HCaptchaTaskProxyless',
  websiteURL: 'https://example.com',
  websiteKey: 'YOUR_WEBSITE_KEY'
});

const solution = await captchaSolver.solve(task);

GenericTask preserves every supplied API field and removes only null and undefined values.

Client Reference

The methods and task classes below form the public SDK API. This section provides a quick reference without leaving the README.

CaptchaClient(...)

Constructor. Takes a single options object.

| Option | Type | Default | Description | |---|---|---|---| | clientKey | string | required | Your Captcha Solver API key. Throws ValidationError if empty. | | baseUrl | string | https://api.captcha-solver.com | API base URL. Override only for self-hosted/staging deployments. | | timeout | number | 120000 | Default max milliseconds solve() waits for a solution before throwing TimeoutError. | | pollingInterval | number | 5000 | Milliseconds between getTaskResult polls inside solve(). |

There's no manual connection pool to open or close -- fetch (via Node's built-in undici) already reuses keep-alive connections per host automatically, unlike Python's requests/httpx, which need an explicit Session/AsyncClient instance to do the same.

solve(task, languagePool)

The main entry point. Submits task, polls until it's solved, and returns the solution -- wraps createTask() + getTaskResult() so you don't poll by hand.

| Parameter | Type | Description | |---|---|---| | task | task object | One of the classes from Tasks (see Captcha Types). | | languagePool | string \| null | Optional worker pool selector, 'en' or 'ru'. Defaults to null (account default pool). |

Returns a Promise resolving to the solution object once status is 'ready' -- its shape depends on the task type (see Captcha Types). Rejects with ApiError, TimeoutError, or NetworkError.

createTask(task, languagePool)

Submits task and returns a Promise resolving to its numeric task ID, without waiting for a solution. Same parameters as solve(). Use this instead of solve() only if you need to manage polling yourself (e.g. checking on many tasks from a different process). Rejects with ApiError, NetworkError.

getTaskResult(taskId)

Fetches the current status of a task created with createTask(). Resolves to an object with a status key ('processing' or 'ready'); when 'ready', also has a solution object. This is a single poll, not a wait -- call it repeatedly (as solve() does) until status is 'ready'. Rejects with ApiError, NetworkError.

getBalance()

Returns a Promise resolving to the account's current balance (number) in the account's currency. Rejects with ApiError, NetworkError.

Captcha Types

Each section below covers one captcha type end-to-end: task fields, the solution shape, a runnable example, and a link to the full spec. Optional fields left unset are omitted from the request. Every code block matches a runnable file under examples/async (and its examples/sync counterpart) -- swap the placeholder websiteURL/websiteKey/etc. for values from your own target page before running. See Running the examples.

Types with a * counterpart (as opposed to *Proxyless) also accept proxyType / proxyAddress / proxyPort / proxyLogin / proxyPassword to solve through your own proxy instead of the service's IPs.

reCAPTCHA v2

API method description.

Use this method to solve reCAPTCHA v2 and obtain a token for the target page. Choose the proxy variant when the solving session must use your own IP address.

Tasks.RecaptchaV2Proxyless (no proxy) / Tasks.RecaptchaV2 (with proxy).

| Field | Required | Description | |---|---|---| | websiteURL | yes | Full URL of the page where the captcha is located. | | websiteKey | yes | Value of the widget's data-sitekey attribute. | | isInvisible | no | true for invisible reCAPTCHA v2. | | recaptchaDataSValue | no | The data-s value, found on Google Search/YouTube pages. | | apiDomain | no | Non-default domain the widget's script is served from, if any. | | userAgent | no | User-Agent to solve with. Recommended to match the agent submitting the token. | | cookies | no | Session cookies to use while solving, if the page requires them. |

Response: gRecaptchaResponse -- submit as g-recaptcha-response.

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.RecaptchaV2Proxyless({
  websiteURL: 'https://example.com/login',
  websiteKey: 'YOUR_WEBSITE_KEY'
});
const result = await captchaSolver.solve(task);
console.log(result.gRecaptchaResponse);

With proxy, use Tasks.RecaptchaV2 instead:

const task = new Tasks.RecaptchaV2({
  websiteURL: 'https://example.com/login',
  websiteKey: 'YOUR_WEBSITE_KEY',
  proxyType: 'http',
  proxyAddress: '1.2.3.4',
  proxyPort: 8080,
  proxyLogin: 'user',
  proxyPassword: 'password'
});

reCAPTCHA v2 Enterprise

API method description.

Use this method to solve the Enterprise version of reCAPTCHA v2 and obtain a token for a page that uses grecaptcha.enterprise.

Tasks.RecaptchaV2EnterpriseProxyless / Tasks.RecaptchaV2Enterprise. Same fields as reCAPTCHA v2, plus:

| Field | Required | Description | |---|---|---| | enterprisePayload | no | Extra parameters passed to grecaptcha.enterprise.render on the page, e.g. { s: '...' }. | | apiDomain | no | Defaults to google.com. |

Response: gRecaptchaResponse.

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.RecaptchaV2EnterpriseProxyless({
  websiteURL: 'https://example.com/login',
  websiteKey: 'YOUR_WEBSITE_KEY'
});
const result = await captchaSolver.solve(task);
console.log(result.gRecaptchaResponse);

With proxy, use Tasks.RecaptchaV2Enterprise (same proxy fields as reCAPTCHA v2).

reCAPTCHA v3

API method description.

Use Tasks.RecaptchaV3Proxyless for score-based reCAPTCHA v3. The API supports this task only without a customer proxy.

| Field | Required | Description | |---|---|---| | websiteURL | yes | Full URL of the page where the captcha is located. | | websiteKey | yes | Site key for the reCAPTCHA v3 widget. | | minScore | yes | Minimum token score, for example 0.3, 0.7, or 0.9. | | pageAction | no | Action passed to grecaptcha.execute() on the page. | | isEnterprise | no | Set to true for reCAPTCHA v3 Enterprise. | | apiDomain | no | Alternative domain used to load the reCAPTCHA script. |

Response: gRecaptchaResponse.

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';

const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.RecaptchaV3Proxyless({
  websiteURL: 'https://example.com/login',
  websiteKey: 'YOUR_WEBSITE_KEY',
  minScore: 0.3,
  pageAction: 'homepage'
});

const result = await captchaSolver.solve(task);
console.log(result.gRecaptchaResponse);

Cloudflare Turnstile

API method description.

Use this method to solve a Cloudflare Turnstile widget and obtain the token that the target page expects in cf-turnstile-response.

Tasks.TurnstileProxyless / Tasks.Turnstile.

| Field | Required | Description | |---|---|---| | websiteURL | yes | Full URL of the page where the widget is located. | | websiteKey | yes | Value of the widget's data-sitekey attribute. | | action | no | Value of the widget's data-action attribute, if set. | | data | no | Custom payload from the widget's data-cdata attribute, if set. | | pagedata | no | Value of the chlPageData parameter, needed for some Cloudflare challenge pages beyond the basic widget. Note the lowercase, single-word spelling -- unlike every other field on this page, the real API does not accept pageData. | | userAgent | no | Current browser User-Agent. Pass it for Cloudflare Challenge pages; it is not needed for a standalone widget. |

Response: token -- submit as cf-turnstile-response. For Cloudflare Challenge pages, pass action, data, pagedata, and the current browser userAgent in the task. Keep the browser User-Agent unchanged when invoking the callback. The solution may also contain userAgent; do not switch the browser to this returned value.

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.TurnstileProxyless({
  websiteURL: 'https://example.com/login',
  websiteKey: 'YOUR_WEBSITE_KEY'
});
const result = await captchaSolver.solve(task);
console.log(result.token);

With proxy, use Tasks.Turnstile (same proxy fields as reCAPTCHA v2).

Image to Text

API method description.

Use this method to recognize text, numbers, or simple math expressions in an image captcha. The image is sent directly and does not require a proxy.

Tasks.ImageToText. No proxy variant -- the image is submitted directly, no browser session involved.

| Field | Required | Description | |---|---|---| | body | yes | The captcha image, base64-encoded (no data:image/...;base64, prefix). | | phrase | no | true if the answer is multiple words. | | case_ | no | true if the answer is case-sensitive. Serializes to the case field (renamed to work around the reserved word). | | numeric | no | 0 unspecified, 1 digits only, 2 letters only, 3 any with digits, 4 any with letters. | | math | no | true if the image contains a math expression to evaluate. | | minLength / maxLength | no | Expected answer length bounds. | | comment | no | Free-text hint for the worker. | | imgInstructions | no | Optional supplementary instruction image, base64-encoded. |

Response: text -- the recognized text/answer.

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
import fs from 'fs';
const imageBase64 = fs.readFileSync('examples/assets/text-captcha.png').toString('base64');
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.ImageToText({
  body: imageBase64,
  numeric: 2,
  minLength: 4,
  maxLength: 6
});
const result = await captchaSolver.solve(task);
console.log(result.text);

GeeTest (v3 & v4)

API method description: v3, v4

Use this method to solve GeeTest puzzle captchas. Select version 3 or 4 and pass the values collected from the target page before creating the task.

Tasks.GeeTestProxyless / Tasks.GeeTest. Set version: 4 for v4 (with initParameters.captcha_id); v3 is the default and needs gt/challenge instead.

| Field | Required | Description | |---|---|---| | websiteURL | yes | Full URL of the page where the widget is located. | | version | no | 3 (default) or 4. | | gt | v3 only | Public key of the GeeTest widget. | | challenge | v3 only | Session-specific challenge value from the page -- must be freshly fetched for every request, it cannot be reused. | | initParameters | v4 only | Extra parameters from the page's initGeetest call; for v4 must contain captcha_id. | | geetestApiServerSubdomain | no | Custom GeeTest API subdomain, if the site uses one. | | userAgent | no | User-Agent to solve with. | | risk_type | no | Dynamic, single-use value included in the page's captcha-loading request, if present. Note the snake_case name -- unlike every other field here, the real API does not accept riskType. |

Response: v3 -- challenge, validate, seccode. v4 -- captcha_id, lot_number, pass_token, gen_time, captcha_output. Docs: v3 ↗, v4 ↗

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key', timeout: 300000, pollingInterval: 10000 });
const task = new Tasks.GeeTestProxyless({
  websiteURL: 'https://example.com/login',
  gt: 'f2ae6cadcf7886856696c46d84d109d1',
  challenge: '12345678abc90123d45678e90123f45g6' // dynamic -- fetch a fresh one per request
});
const result = await captchaSolver.solve(task);
console.log(result.validate);
console.log(result.seccode);

challenge is session-specific and expires quickly, so it can't be hardcoded into a static example -- see examples/async/geetest_v3.js for where the fetch belongs in the flow.

const task = new Tasks.GeeTestProxyless({
  websiteURL: 'https://example.com/login',
  version: 4,
  initParameters: { captcha_id: 'YOUR_CAPTCHA_ID' }
});
const result = await captchaSolver.solve(task);
console.log(result.captcha_output);

With proxy, use Tasks.GeeTest (same proxy fields as reCAPTCHA v2).

Yandex SmartCaptcha

API method description.

Use this method to solve the token-based Yandex SmartCaptcha and obtain a token for the widget on the target page. Use the coordinates method for image challenges.

Tasks.YandexSmartCaptchaTaskProxyless / Tasks.YandexSmartCaptchaTask -- token-based challenge. For the image challenge instead, use Tasks.CoordinatesTask with

| Field | Required | Description | |---|---|---| | websiteURL | yes | Full URL of the page where the widget is located. | | websiteKey | yes | The sitekey value from the page source or captcha iframe. | | userAgent | no | User-Agent to solve with. | | cookies | no | Session cookies to use while solving, if the page requires them. |

Proxy variant note: proxyType also accepts 'https' for this captcha type only (in addition to http/socks4/socks5).

Response: token.

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.YandexSmartCaptchaTaskProxyless({
  websiteURL: 'https://example.com/login',
  websiteKey: 'YOUR_WEBSITE_KEY'
});
const result = await captchaSolver.solve(task);
console.log(result.token);

With proxy, use Tasks.YandexSmartCaptchaTask (same proxy fields as reCAPTCHA v2, plus the https option above).

Coordinates (click captcha)

API method description.

Use this method to identify points that a worker should click in an image. It supports generic click captchas and the image version of Yandex SmartCaptcha.

Tasks.CoordinatesTask. Used both for generic "click on X" captchas and for directly.

| Field | Required | Description | |---|---|---| | body | yes | The captcha image, base64-encoded. | | comment | no (recommended) | Hint for the worker, e.g. 'click on the green apple'. | | minClicks | no | Minimum number of clicks expected (default 1). | | maxClicks | no | Maximum number of clicks allowed. |

Response: coordinates -- an array of { x, y } pixel positions to click, in order.

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
import fs from 'fs';
const body = fs.readFileSync('examples/assets/coordinates-captcha.png').toString('base64');
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.CoordinatesTask({
  body: body,
  comment: 'click on the green apple'
});
const result = await captchaSolver.solve(task);
console.log(result.coordinates); // [{ x: 358, y: 268 }]

mode" block in examples/async/coordinates.js (or examples/sync/coordinates.js).

Tencent

API method description.

Use this method to solve Tencent Captcha and obtain the ticket and callback values required by the target page.

Tasks.TencentTaskProxyless / Tasks.TencentTask.

| Field | Required | Description | |---|---|---| | websiteURL | yes | Full URL of the page where the captcha is located. | | appId | yes | Value of the appId parameter found in the page source. | | captchaScript | no | URL of the Tencent captcha script, if the page uses a non-default one. |

Response: appid, ret, ticket, randstr -- pass all four into the page's Tencent captcha callback.

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const task = new Tasks.TencentTaskProxyless({
  websiteURL: 'https://example.com/register',
  appId: 'YOUR_APP_ID'
});
const result = await captchaSolver.solve(task);
console.log(result.ticket);

With proxy, use Tasks.TencentTask (same proxy fields as reCAPTCHA v2).

Advanced Usage

Check balance

import { CaptchaClient } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
const balance = await captchaSolver.getBalance();
console.log(`Balance: ${balance}`);

Custom timeout and polling

const captchaSolver = new CaptchaClient({
  clientKey: 'your_api_key',
  timeout: 180000,
  pollingInterval: 5000
});

Worker language pool

Pass languagePool as the second argument to solve() (or createTask()) to pick a worker pool by language. Accepted values: 'en' or 'ru'.

const result = await captchaSolver.solve(task, 'en');

Solving multiple captchas in parallel

CaptchaClient is promise-based throughout, so running several solve() calls concurrently is just Promise.all() -- no separate async client needed:

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });

const task1 = captchaSolver.solve(new Tasks.RecaptchaV2Proxyless({ websiteURL: 'https://site1.com', websiteKey: 'key1' }));
const task2 = captchaSolver.solve(new Tasks.TurnstileProxyless({ websiteURL: 'https://site2.com', websiteKey: 'key2' }));

const results = await Promise.allSettled([task1, task2]);

This completes in roughly the time of the slowest single captcha, not the sum of all of them.

Error handling

import { CaptchaClient, ApiError, TimeoutError, NetworkError, ValidationError } from '@captcha-solver-api/javascript-sdk';
const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });
try {
  const result = await captchaSolver.solve(task);
} catch (error) {
  if (error instanceof ValidationError) {
    console.log(`Invalid input: ${error.message}`);
  } else if (error instanceof ApiError) {
    console.log(`API error: ${error.errorCode} ${error.errorDescription}`);
  } else if (error instanceof TimeoutError) {
    console.log('Task timed out');
  } else if (error instanceof NetworkError) {
    console.log(`Network error: ${error.message}`);
  }
}

TypeScript

The package ships its own type declarations, so no @types/* install is needed. Every task constructor takes a typed options object, and solve() infers the solution type from the task class:

import { CaptchaClient, Tasks } from '@captcha-solver-api/javascript-sdk';
import type { TurnstileSolution } from '@captcha-solver-api/javascript-sdk';

const captchaSolver = new CaptchaClient({ clientKey: 'your_api_key' });

const result = await captchaSolver.solve(new Tasks.TurnstileProxyless({
  websiteURL: 'https://example.com/login',
  websiteKey: 'YOUR_WEBSITE_KEY'
}));
result.token;      // string
result.userAgent;  // string

// The same shape is exported by name if you need to pass it around.
const stored: TurnstileSolution = result;

Parameter types (RecaptchaV2Params, GeeTestProxylessParams, ...) and solution types (RecaptchaSolution, GeeTestSolution, ...) are exported from the package root. GenericTask resolves to a plain Record<string, unknown>. Every public class, method and field carries JSDoc, so hover documentation in the editor matches this README.

Running the examples

  • Image/click captchas (image_to_text.js, coordinates.js) run end-to-end with nothing but a valid CAPTCHA_API_KEY -- they read sample images bundled in examples/assets, no target page needed. turnstile.js, yandex_smartcaptcha.js, geetest_v4.js, tencent.js) use placeholder values (https://example.com/..., YOUR_WEBSITE_KEY, YOUR_APP_ID, YOUR_CAPTCHA_ID) -- replace these with the real values from your own target page before running.
  • geetest_v3.js additionally needs challenge fetched fresh for every request -- it's single-use and expires within seconds, so it can't be hardcoded into a static example. 'https://target-site.com/path/to/geetest/init' is a placeholder; replace it with a request to your own target's equivalent endpoint (or wherever it exposes gt/challenge) -- see the script for where that fetch belongs in the flow.
  • Proxy variants (Tasks.* classes without Proxyless in the name) use placeholder proxy credentials (1.2.3.4 / user / password) in every example file -- proxies are a paid, account-specific resource, so there's nothing public to ship here. Swap in your own proxy details to run those blocks for real.
export CAPTCHA_API_KEY=your_api_key
node examples/async/balance.js
node examples/async/image_to_text.js
node examples/async/coordinates.js

Full details, an example index, and a per-type breakdown of what each script covers live in examples/README.md.

Requirements

  • Node.js 18 or newer. Modern browser with fetch support.
  • Captcha Solver account with a valid API key.

API Documentation

Full API reference: https://captcha-solver.com/en/docs/captcha-types

Useful Links

License

This project is licensed under the MIT License. See LICENSE.md for details.