A powerful and easy-to-use NodeJS library that unifies multiple captcha-solving services under a single, elegant, and robust interface.
- 🧩 Multi-Provider Support: Built-in support for the most popular captcha services.
- 🛡️ Unified Interface: Use the same code to talk to different services. Switch providers by changing just one line!
- 🦾 Resilient & Robust: Automatic retry system with exponential backoff and custom error handling.
- 🧠 Intelligent Retry Logic: Smart retry system that avoids unnecessary retries on permanent errors like invalid API keys.
- 🌐 Modern Support: Solves ImageToText, reCAPTCHA v2/v3, hCaptcha and more.
- 🕵️ Proxy Support: Send your proxies to solving services for complex scraping tasks.
- 💯 Strictly Typed: Developed 100% in TypeScript for safer and more predictable code.
- [x] 2Captcha
- [x] Anti-Captcha
- [x] CapMonster Cloud
- ... and more coming soon!
npm install multi-captcha-solver-adapter
import {
MultiCaptchaSolver,
ECaptchaSolverService,
} from 'multi-captcha-solver-adapter';
const imageBase64 = '...'; // your captcha image in base64
async function solveImage() {
const solver = new MultiCaptchaSolver({
apiKey: 'YOUR_PROVIDER_API_KEY',
captchaService: ECaptchaSolverService.TwoCaptcha,
});
try {
const solution = await solver.solveImageCaptcha(imageBase64);
console.log(`🎉 The solution is: ${solution}`);
} catch (error) {
console.error('😱 An error occurred:', error);
}
}
solveImage();
import {
MultiCaptchaSolver,
ECaptchaSolverService,
// Import custom errors for detailed handling!
InvalidApiKeyError,
InsufficientBalanceError,
CaptchaServiceError,
ProxyOptions,
} from 'multi-captcha-solver-adapter';
async function solveAdvanced() {
const solver = new MultiCaptchaSolver({
apiKey: 'YOUR_PROVIDER_API_KEY',
captchaService: ECaptchaSolverService.AntiCaptcha,
retries: 3, // Optional: number of retries
});
const proxy: ProxyOptions = {
type: 'http',
uri: '127.0.0.1:8888',
username: 'proxy_user', // optional
password: 'proxy_pass', // optional
};
try {
const balance = await solver.getBalance();
console.log(`Current balance: $${balance}`);
const token = await solver.solveRecaptchaV3(
'https://my-target-website.com',
'google-site-key-here',
0.7, // minScore
'homepage_action', // pageAction
proxy,
);
console.log(`reCAPTCHA v3 token obtained: ${token.substring(0, 30)}...`);
} catch (error) {
if (error instanceof InvalidApiKeyError) {
console.error(`API Key is invalid for ${error.service}.`);
} else if (error instanceof InsufficientBalanceError) {
console.error(`Insufficient balance in ${error.service}.`);
} else if (error instanceof CaptchaServiceError) {
console.error(`API error from ${error.service}: ${error.message}`);
} else {
console.error('😱 An unexpected error occurred:', error);
}
}
}
solveAdvanced();
Solve traditional image-based captchas:
const solution = await solver.solveImageCaptcha(base64ImageString);
Solve Google's reCAPTCHA v2 challenges:
const token = await solver.solveRecaptchaV2(
'https://example.com', // Website URL
'site-key-here', // Google site key
proxy, // Optional: proxy configuration
);
Solve Google's reCAPTCHA v3 challenges:
const token = await solver.solveRecaptchaV3(
'https://example.com', // Website URL
'site-key-here', // Google site key
0.7, // Minimum score (0.1 to 0.9)
'submit', // Page action
proxy, // Optional: proxy configuration
);
Solve hCaptcha challenges:
const token = await solver.solveHCaptcha(
'https://example.com', // Website URL
'site-key-here', // hCaptcha site key
proxy, // Optional: proxy configuration
);
CapMonster Cloud offers high-quality captcha solving with competitive pricing:
import {
MultiCaptchaSolver,
ECaptchaSolverService,
} from 'multi-captcha-solver-adapter';
const solver = new MultiCaptchaSolver({
apiKey: 'YOUR_CAPMONSTER_API_KEY',
captchaService: ECaptchaSolverService.CapMonster,
retries: 3,
});
// CapMonster excels at image captchas
const imageSolution = await solver.solveImageCaptcha(base64Image);
// Supports all modern captcha types
const recaptchaToken = await solver.solveRecaptchaV2(
'https://example.com',
'site-key',
);
// reCAPTCHA v3 with high accuracy
const v3Token = await solver.solveRecaptchaV3(
'https://example.com',
'site-key',
0.7,
'homepage',
);
The library includes a sophisticated retry system with exponential backoff and intelligent error handling that automatically distinguishes between retryable and non-retryable errors.
const solver = new MultiCaptchaSolver({
apiKey: 'YOUR_API_KEY',
captchaService: ECaptchaSolverService.TwoCaptcha,
retries: 5, // Will retry up to 5 times (default: 3)
});
// The solver will automatically retry failed requests with increasing delays
const token = await solver.solveRecaptchaV2('https://example.com', 'site-key');
The library intelligently handles different types of errors:
✅ Will Retry (Network/Temporary Errors):
- Network timeouts and connection errors
- Temporary server errors (5xx HTTP status codes)
- Generic errors that might be transient
❌ Won't Retry (Permanent API Errors):
-
InvalidApiKeyError
- Invalid or malformed API key -
InsufficientBalanceError
- Account has no balance -
IpBlockedError
- IP address is blocked by the service - Other specific
CaptchaServiceError
instances
import {
MultiCaptchaSolver,
ECaptchaSolverService,
InvalidApiKeyError,
InsufficientBalanceError,
} from 'multi-captcha-solver-adapter';
async function demonstrateIntelligentRetries() {
const solver = new MultiCaptchaSolver({
apiKey: 'INVALID_KEY', // This will cause an InvalidApiKeyError
captchaService: ECaptchaSolverService.TwoCaptcha,
retries: 3,
});
try {
// This will fail immediately without retries because API key is invalid
const token = await solver.solveRecaptchaV2(
'https://example.com',
'site-key',
);
} catch (error) {
if (error instanceof InvalidApiKeyError) {
console.log(
'❌ API key error detected - no retries attempted (saves time!)',
);
}
}
}
// Conservative retry configuration
const conservativeSolver = new MultiCaptchaSolver({
apiKey: 'YOUR_API_KEY',
captchaService: ECaptchaSolverService.AntiCaptcha,
retries: 2, // Fewer retries for faster failures
});
// Aggressive retry configuration
const aggressiveSolver = new MultiCaptchaSolver({
apiKey: 'YOUR_API_KEY',
captchaService: ECaptchaSolverService.TwoCaptcha,
retries: 5, // More retries for higher success rate
});
Configure proxies for solving web-based captchas:
import { ProxyOptions } from 'multi-captcha-solver-adapter';
const proxyConfig: ProxyOptions = {
type: 'http', // 'http', 'https', 'socks4', or 'socks5'
uri: '127.0.0.1:8080', // proxy host:port
username: 'user', // optional authentication
password: 'pass', // optional authentication
};
// Use proxy with any web-based captcha
const token = await solver.solveRecaptchaV2(
'https://example.com',
'site-key',
proxyConfig,
);
The library includes a powerful CaptchaDetector
utility that can automatically identify captcha types present on web pages. This is particularly useful for automation workflows where you need to determine what type of captcha to solve.
import { CaptchaDetector, CaptchaType } from 'multi-captcha-solver-adapter';
const detector = new CaptchaDetector();
// Detect captcha on a webpage
const captchaType = await detector.detect('https://example.com/login');
switch (captchaType) {
case CaptchaType.RECAPTCHA_V2:
console.log('Found reCAPTCHA v2 - use solveRecaptchaV2()');
break;
case CaptchaType.RECAPTCHA_V3:
console.log('Found reCAPTCHA v3 - use solveRecaptchaV3()');
break;
case CaptchaType.HCAPTCHA:
console.log('Found hCaptcha - use solveHCaptcha()');
break;
case null:
console.log('No captcha detected');
break;
}
const detector = new CaptchaDetector({
timeout: 15000, // 15 second timeout
userAgent: 'Custom User Agent',
});
const proxy = {
type: 'http' as const,
uri: '127.0.0.1:8080',
username: 'proxy_user',
password: 'proxy_pass',
};
const captchaType = await detector.detect('https://example.com', proxy);
async function autoSolveCaptcha(url: string, siteKey?: string) {
const detector = new CaptchaDetector();
const solver = new MultiCaptchaSolver({
apiKey: 'YOUR_API_KEY',
captchaService: ECaptchaSolverService.CapMonster,
});
// Detect what type of captcha is present
const captchaType = await detector.detect(url);
if (!captchaType) {
console.log('No captcha found on page');
return null;
}
// Solve based on detected type
switch (captchaType) {
case CaptchaType.RECAPTCHA_V2:
if (!siteKey) throw new Error('Site key required for reCAPTCHA v2');
return await solver.solveRecaptchaV2(url, siteKey);
case CaptchaType.RECAPTCHA_V3:
if (!siteKey) throw new Error('Site key required for reCAPTCHA v3');
return await solver.solveRecaptchaV3(url, siteKey, 0.7, 'submit');
case CaptchaType.HCAPTCHA:
if (!siteKey) throw new Error('Site key required for hCaptcha');
return await solver.solveHCaptcha(url, siteKey);
default:
throw new Error(`Unsupported captcha type: ${captchaType}`);
}
}
// Usage
const token = await autoSolveCaptcha(
'https://example.com/login',
'6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI'
);
The CaptchaDetector
can identify captchas using various patterns:
reCAPTCHA v2:
- Google reCAPTCHA scripts (
google.com/recaptcha
) -
g-recaptcha
CSS classes -
grecaptcha.render()
function calls - reCAPTCHA iframes
reCAPTCHA v3:
-
grecaptcha.execute()
function calls -
action
parameters in scripts -
render=
parameter in script URLs
hCaptcha:
- hCaptcha scripts (
hcaptcha.com
,js.hcaptcha.com
) -
h-captcha
CSS classes -
hcaptcha.render()
function calls - hCaptcha iframes
The detector is designed to work with modern web applications including Single Page Applications (SPAs) built with React, Vue, Angular, Svelte, and other frameworks.
The library provides specific error types for better error handling and implements intelligent retry logic based on error types:
import {
MultiCaptchaError, // Base error class
CaptchaServiceError, // General API errors (won't retry)
InvalidApiKeyError, // Invalid API key (won't retry)
InsufficientBalanceError, // Not enough balance (won't retry)
IpBlockedError, // IP address blocked (won't retry)
} from 'multi-captcha-solver-adapter';
try {
const token = await solver.solveRecaptchaV2(
'https://example.com',
'site-key',
);
} catch (error) {
if (error instanceof InvalidApiKeyError) {
console.error(
`❌ Invalid API key for ${error.service} - No retries attempted`,
);
} else if (error instanceof InsufficientBalanceError) {
console.error(
`💰 Insufficient balance in ${error.service} - No retries attempted`,
);
} else if (error instanceof IpBlockedError) {
console.error(`🚫 IP blocked by ${error.service} - No retries attempted`);
} else if (error instanceof CaptchaServiceError) {
console.error(
`🔧 API error in ${error.service}: ${error.message} - No retries attempted`,
);
} else if (error instanceof MultiCaptchaError) {
console.error(`📚 Library error: ${error.message}`);
} else {
console.error(
`🔄 Network/Generic error: ${error.message} - May have been retried`,
);
}
}
Understanding which errors trigger retries helps you build more efficient applications:
async function handleDifferentErrorTypes() {
const solver = new MultiCaptchaSolver({
apiKey: 'YOUR_API_KEY',
captchaService: ECaptchaSolverService.TwoCaptcha,
retries: 3
});
try {
const token = await solver.solveRecaptchaV2('https://example.com', 'site-key');
console.log('✅ Success:', token);
} catch (error) {
// Check if this error type would have triggered retries
const isRetryableError = !(error instanceof CaptchaServiceError);
if (isRetryableError) {
console.log('🔄 This error was retried automatically');
} else {
console.log('⚡ This error failed immediately (no retries)');
}
throw error; // Re-throw for application handling
}
}
new MultiCaptchaSolver(options: IMultiCaptchaSolverOptions)
Options:
-
apiKey: string
- Your captcha service API key -
captchaService: ECaptchaSolverService
- The service to use -
retries?: number
- Number of retries (default: 3)
-
getBalance(): Promise<number>
- Get account balance -
solveImageCaptcha(base64string: string): Promise<string>
- Solve image captcha -
solveRecaptchaV2(websiteURL: string, websiteKey: string, proxy?: ProxyOptions): Promise<string>
- Solve reCAPTCHA v2 -
solveRecaptchaV3(websiteURL: string, websiteKey: string, minScore: number, pageAction: string, proxy?: ProxyOptions): Promise<string>
- Solve reCAPTCHA v3 -
solveHCaptcha(websiteURL: string, websiteKey: string, proxy?: ProxyOptions): Promise<string>
- Solve hCaptcha
-
ECaptchaSolverService.TwoCaptcha
- 2Captcha service -
ECaptchaSolverService.AntiCaptcha
- Anti-Captcha service -
ECaptchaSolverService.CapMonster
- CapMonster Cloud service
Check out the examples directory for complete working examples:
- Basic Example - Basic usage for all captcha types
- Proxy Example - Advanced usage with proxy configuration
This library includes comprehensive test suites to ensure reliability and quality:
Run the standard unit tests with mocked dependencies:
npm test
Run integration tests with real API calls to captcha services:
npm run test:integration
Note: Integration tests require valid API keys set as environment variables:
export TWOCAPTCHA_API_KEY=your_2captcha_api_key
export ANTICAPTCHA_API_KEY=your_anticaptcha_api_key
export CAPMONSTER_API_KEY=your_capmonster_api_key
Integration tests will automatically skip services for which API keys are not provided, allowing you to test only the services you have access to.
Run comprehensive E2E tests that validate the complete flow from captcha detection to resolution:
# Run E2E tests with API keys
ANTICAPTCHA_API_KEY=your_key npm run test:integration src/__tests__/e2e.integration.spec.ts
E2E tests include:
-
Captcha Detection: Validates automatic captcha type detection using
CaptchaDetector
- Service Integration: Tests real API communication with captcha solving services
- Complete Flow: End-to-end validation from detection to token resolution
- Multi-Service Support: Tests compatibility across all supported services
Demo Page Used: hCaptcha Demo with site key 4c672d35-0701-42b2-88c3-78380b0db560
View test coverage reports:
npm test
# Coverage report will be generated in ./coverage/lcov-report/index.html
Contributions are the heart of the open-source community! We are delighted to accept your help. Please check out our Contribution Guide to get started.
This project is licensed under the Apache-2.0 License. See the LICENSE file for details.
- Email: dev.alexander.daza@gmail.com
- GitHub: @devalexanderdaza