Package Exports
- @onecaptcha/sdk
Readme
@onecaptcha/sdk
Official Node.js SDK for the OneCaptcha unified captcha-solving gateway.
Website | Docs | SDKs | Error Codes
- Zero dependencies. Built-in
fetch(Node 18+). - Works with both ESM (
import) and CommonJS (require). - Per-type sync and async helper methods with full JSDoc.
Install
npm install @onecaptcha/sdkQuick start
import { OneCaptchaClient } from '@onecaptcha/sdk';
const client = new OneCaptchaClient({
apiKey: process.env.ONECAPTCHA_API_KEY,
});
// Solve a reCAPTCHA v2
const result = await client.solveRecaptchaV2({
url: 'https://example.com/login',
sitekey: '6Lc...',
});
console.log(result.token);
await result.reportGood(); // tell the gateway it worked
// Solve an image captcha — just pass the base64 string
const img = await client.solveImageToText(base64);
console.log(img.text);
await img.reportGood();Constructor options
| Option | Default | Description |
|---|---|---|
apiKey |
required | Your gateway API key (sent as X-API-Key) |
baseUrl |
https://api.one-captcha.com |
Gateway origin, no trailing slash |
timeout |
30000 |
ms timeout for non-solve calls |
solveTimeout |
120 (seconds) |
Default X-Timeout for sync solve(). Min 10, max 180. |
pollInterval |
5000 |
ms between polls in waitForTask |
pollTimeout |
180000 |
Total ms waitForTask waits before giving up |
fetch |
globalThis.fetch |
Custom fetch implementation (test injection) |
Sync solve
One call — the gateway holds the connection open until the solution is ready. Best for most use cases.
// Per-type helper (recommended)
const result = await client.solveRecaptchaV2({ url, sitekey });
// Generic form
const result = await client.solve({
type: 'recaptcha_v2',
params: { url, sitekey },
});Per-type sync helpers
client.solveImageToText(base64) // or { body, caseSensitive, ... }
client.solveImageToCoordinates(base64) // or { body, comment, mode }
client.solveRecaptchaV2({ url, sitekey })
client.solveRecaptchaV2Enterprise({ url, sitekey })
client.solveRecaptchaV3({ url, sitekey, action, minScore })
client.solveRecaptchaV3Enterprise({ url, sitekey, action, minScore })
client.solveFunCaptcha({ url, publicKey, subdomain, data })
client.solveGeeTestV3({ url, gt, challenge })
client.solveGeeTestV4({ url, captchaId })
client.solveTurnstile({ url, sitekey })
client.solveAmazonWaf({ url, key })
client.solveMtCaptcha({ url, sitekey })
client.solveProsopo({ url, sitekey })
client.solveFriendlyCaptcha({ url, sitekey })Async solve
Submit the task and poll until ready. Use when you need non-blocking submission or want to control the polling loop. Every sync helper has a matching ...Async variant.
// Per-type async helper — submits + polls automatically
const result = await client.solveRecaptchaV2Async({
url: 'https://example.com',
sitekey: '6Lc...',
}, { pollInterval: 3000, pollTimeout: 120000 });
console.log(result.token);
// Image OCR async
const img = await client.solveImageToTextAsync(base64);
console.log(img.text);Per-type async helpers
client.solveImageToTextAsync(base64, waitOpts?)
client.solveImageToCoordinatesAsync(base64, waitOpts?)
client.solveRecaptchaV2Async(params, waitOpts?)
client.solveRecaptchaV2EnterpriseAsync(params, waitOpts?)
client.solveRecaptchaV3Async(params, waitOpts?)
client.solveRecaptchaV3EnterpriseAsync(params, waitOpts?)
client.solveFunCaptchaAsync(params, waitOpts?)
client.solveGeeTestV3Async(params, waitOpts?)
client.solveGeeTestV4Async(params, waitOpts?)
client.solveTurnstileAsync(params, waitOpts?)
client.solveAmazonWafAsync(params, waitOpts?)
client.solveMtCaptchaAsync(params, waitOpts?)
client.solveProsopoAsync(params, waitOpts?)
client.solveFriendlyCaptchaAsync(params, waitOpts?)waitOpts is optional: { pollInterval?: number, pollTimeout?: number }.
Result
Both sync and async helpers return the same shape:
{
type: 'recaptcha_v2',
status: 'ready',
taskRef: '550e8400-e29b-41d4-a716-446655440000', // UUID for reporting
token: '03AGdBq24...', // token-based captchas
text: 'K4ADHP', // image_to_text
coordinates: [...], // image_to_coordinates
cost: 0.002990, // USD charged
balanceRemaining: 9.997, // balance after charge
rateLimit: { limit, remaining, reset },
reportGood: () => Promise, // shortcut for reportTask(taskRef, true)
reportBad: () => Promise, // shortcut for reportTask(taskRef, false)
}Fields present depend on the captcha type (token for site-based, text for OCR, coordinates for click-based).
Reporting
Tell the gateway whether the solution worked on the target site. This helps providers flag bad workers, may trigger refunds, and for image captchas promotes the result into the cache so future identical images resolve instantly.
const result = await client.solveRecaptchaV2({ url, sitekey });
// Use the token on the target site, then report back:
await result.reportGood(); // solution worked
await result.reportBad(); // solution was rejected
// Equivalent long form:
await client.reportTask(result.taskRef, true);
await client.reportTask(result.taskRef, false);Every result object from solve(), solveAsync(), createTask(), getTask(), and waitForTask() carries .reportGood() and .reportBad() when a taskRef is present.
Balance
const { balance, currency } = await client.getBalance();Errors
Every method throws OneCaptchaError on failure.
import { OneCaptchaError, ERROR_CODES } from '@onecaptcha/sdk';
try {
await client.solveRecaptchaV2({ url, sitekey });
} catch (err) {
if (err instanceof OneCaptchaError) {
err.code // 'BALANCE_EMPTY' | 'PROVIDER_SITEKEY' | 'UNSOLVABLE' | ...
err.message // human-readable
err.status // HTTP status
err.retryable // boolean — check this before retrying
err.retryAfter // seconds to wait (null if not retryable)
err.balanceRemaining // null or number
err.rateLimit // null or { limit, remaining, reset }
}
}ERROR_CODES enumerates all codes, plus two SDK-only codes (SDK_TIMEOUT, SDK_NETWORK) for local failures.
Billing
Per-solve pricing. Each solve request deducts the type's base price from your API key balance. Check current pricing at one-captcha.com.
The post-operation balance is on every response as result.balanceRemaining.
License
MIT