auto-captcha-solver
Version:
Automatically detect and solve various captcha types in Playwright & Puppeteer with 2Captcha/CapMonster Cloud integration
382 lines • 15.7 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.solveWith2Captcha = solveWith2Captcha;
const captcha_solver_1 = require("@2captcha/captcha-solver");
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const inject_captcha_response_1 = require("../../../utils/inject-captcha-response");
const find_captcha_image_url_1 = require("../../../utils/find-captcha-image-url");
// Function to handle the 2Captcha CAPTCHA solving
async function solveWith2Captcha(captchaInfo, captchaData, page) {
const solver = new captcha_solver_1.Solver(captchaInfo.apiKey);
switch (captchaData.type) {
case 'Image To Text': {
try {
// Get CAPTCHA image element with enhanced waiting
const captchaImage = await page.waitForSelector(captchaInfo.imageSelector || '', {
timeout: 15000,
state: 'visible'
});
if (!captchaImage) {
return {
success: false,
message: 'CAPTCHA image element not found'
};
}
console.log({ captchaImage });
// Get image source URL with validation
// const imageUrl = await captchaImage.evaluate(`(function(el) {
// if (!(el instanceof HTMLImageElement)) {
// throw new Error('Element is not an image');
// }
// return el.src;
// })();`);
const imageUrl = await (0, find_captcha_image_url_1.getCaptchaSource)(page, captchaInfo.imageSelector || '');
console.log({ imageUrl });
if (!imageUrl) {
return {
success: false,
message: 'CAPTCHA image source not found'
};
}
// Fetch image directly using Node.js HTTP client
const response = await fetch(String(imageUrl));
if (!response.ok) {
return {
success: false,
message: `Failed to fetch CAPTCHA image: ${response.status} ${response.statusText}`
};
}
// Convert response to base64
const buffer = await response.arrayBuffer();
const imageBase64 = Buffer.from(buffer).toString('base64');
// Create Image to Text request with enhanced options
const solution = await solver.imageCaptcha({
body: imageBase64,
numeric: captchaInfo.numericCount || 2,
min_len: captchaInfo.minLength || 5,
max_len: captchaInfo.maxLength || 6,
calc: captchaInfo.math ? 1 : 0
});
if (!solution.data) {
return {
success: false,
message: 'CAPTCHA solving service returned empty solution'
};
}
// Enhanced input handling
const inputSelector = captchaInfo.inputSelector || '';
await page.waitForSelector(inputSelector, {
state: 'visible',
timeout: 5000
});
await page.fill(inputSelector, solution.data);
return {
success: true,
message: `CAPTCHA solved: ${solution.data}`
};
}
catch (error) {
return {
success: false,
message: `CAPTCHA error: ${error.message}`
};
}
}
case 'reCAPTCHA v2': {
const solution = (await solver.recaptcha({
pageurl: page.url(),
googlekey: captchaData.siteKey || '',
version: 'v2'
}));
if (solution?.data) {
// Inject CAPTCHA response into the page
const success = await (0, inject_captcha_response_1.injectTokenResponse)(page, 'textarea[name="g-recaptcha-response"]', solution.data);
if (success) {
return {
success: true,
message: `reCAPTCHA v2 solved successfully.`
};
}
}
return {
success: false,
message: `Failed to inject reCAPTCHA v2 token.`
};
}
case 'reCAPTCHA v2 Invisible': {
const solution = (await solver.recaptcha({
pageurl: page.url(),
googlekey: captchaData.siteKey || '',
version: 'v2',
invisible: 1
}));
if (solution?.data) {
// Inject CAPTCHA response into the page
const success = await (0, inject_captcha_response_1.injectTokenResponse)(page, '#g-recaptcha-response', solution.data);
if (success) {
return {
success: true,
message: `reCAPTCHA v2 Invisible solved successfully.`
};
}
}
return {
success: false,
message: `Failed to inject reCAPTCHA v2 Invisible token.`
};
}
case 'reCAPTCHA v3': {
const solution = (await solver.recaptcha({
pageurl: page.url(),
googlekey: captchaData.siteKey || '',
version: 'v3',
min_score: 0.6,
action: 'submit'
}));
if (solution?.data) {
const success = await (0, inject_captcha_response_1.injectReCaptchaV3Response)(page, solution.data);
if (success) {
return {
success: true,
message: `reCAPTCHA v3 solved successfully.`
};
}
}
return {
success: false,
message: `Failed to inject reCAPTCHA v3 token.`
};
}
case 'reCAPTCHA Enterprise': {
const solution = await solver.recaptcha({
pageurl: page.url(),
googlekey: captchaData.siteKey || '',
version: 'v3',
min_score: 0.6,
enterprise: 1,
action: 'submit'
});
if (solution?.data) {
// Inject CAPTCHA response into the page
const success = await (0, inject_captcha_response_1.injectTokenResponse)(page, 'textarea[name="g-recaptcha-response"]', solution.data);
if (success) {
return {
success: true,
message: `reCAPTCHA Enterprise solved successfully.`
};
}
}
return {
success: false,
message: `Failed to inject reCAPTCHA Enterprise token.`
};
}
case 'GeeTest V4 Captcha': {
const solution = await solver.geetestV4({
pageurl: page.url(),
captcha_id: captchaData.captchaId ?? ''
});
if (solution?.data) {
try {
const injectionSuccess = await (0, inject_captcha_response_1.injectGeeTestV4Solution)(page, solution.data || {});
console.log({ injectionSuccess }); // Now shows true/false
if (injectionSuccess) {
return {
success: true,
message: `GeeTest V4 solved`
};
}
return {
success: false,
message: 'Captcha injection failed verification'
};
}
catch (error) {
return {
success: false,
message: `GeeTest V4 error: ${error.message}`
};
}
}
return {
success: false,
message: 'No captcha solution received'
};
}
case 'Text Captcha': {
const textSelector = captchaInfo.textSelector;
const inputSelector = captchaInfo.inputSelector;
try {
if (!textSelector || !inputSelector) {
return {
success: false,
message: 'Text Captcha or Input selector not found'
};
}
await page.waitForSelector(textSelector, {
state: 'visible',
timeout: 5000
});
const textQuestion = await page.locator(textSelector).innerText();
const solution = (await solver.text({
textcaptcha: textQuestion,
lang: captchaInfo.textLanguage || 'en'
}));
if (solution.status === 1 && solution.data) {
await page.waitForSelector(inputSelector, {
state: 'visible',
timeout: 5000
});
await page.fill(inputSelector, solution.data);
return {
success: true,
message: `Text Captcha solved: ${solution.data}`
};
}
return {
success: false,
message: `Failed to solve Text Captcha`
};
}
catch (error) {
return {
success: false,
message: `Text Captcha error: ${error.message}`
};
}
}
// case 'KeyCaptcha': {
// const solution = await solver.keyCaptcha({
// pageurl: page.url(),
// userId: captchaData.userId || '',
// sessionId: captchaData.sessionId || '',
// webServerSign: captchaData.sign || '',
// webServerSign2: captchaData.sign2 || ''
// });
// return {
// success: false,
// message: `Failed to inject reCAPTCHA Enterprise token.`
// };
// }
case 'hCaptcha': {
try {
const solution = await solver.hcaptcha({
pageurl: page.url(),
sitekey: captchaData.siteKey
});
if (solution.data) {
const success = await (0, inject_captcha_response_1.injectTokenResponse)(page, 'textarea[name="h-captcha-response"]', solution.data);
if (success) {
return {
success: true,
message: `hCaptcha successfully solved `
};
}
}
return {
success: false,
message: `Failed to inject hCaptcha token.`
};
}
catch (error) {
return {
success: false,
message: `CAPTCHA error: ${error.message}`
};
}
}
case 'Cloudflare Turnstile': {
const solution = (await solver.cloudflareTurnstile({
pageurl: page.url(),
sitekey: captchaData.siteKey || ''
}));
if (solution?.status === 1 && solution?.data) {
const success = await (0, inject_captcha_response_1.injectTokenResponse)(page, '[name="cf-turnstile-response"]', solution.data);
if (success) {
return {
success: true,
message: `Cloudflare Turnstile solved successfully.`
};
}
}
return {
success: false,
message: `Failed to inject Cloudflare Turnstile token.`
};
}
case 'Cloudflare CAPTCHA': {
// Inject script on every new document
try {
const preloadFile = (0, fs_1.readFileSync)(path_1.default.join(__dirname, '../2captcha/cloud-flare-inject.js'), 'utf8');
await page.addInitScript(preloadFile);
// Expose function to handle CAPTCHA callback
await page.exposeFunction('cfCallback', async (token) => {
return token;
});
// Intercept console messages
page.on('console', async (msg) => {
const txt = msg.text();
if (txt.includes('intercepted-params:')) {
const params = JSON.parse(txt.replace('intercepted-params:', ''));
try {
const res = await solver.cloudflareTurnstile(params);
// Inject solution into the page
const evaluateScript = `(function() {
window.cfCallback(${res.data});
})();`;
await page.evaluate(evaluateScript);
}
catch (error) {
console.error(`Error solving CAPTCHA: ${error.message}`);
process.exit(1);
}
}
});
return { success: true, message: 'Cloud Flare captcha is solved' };
}
catch (error) {
return {
success: false,
message: `CAPTCHA error: ${error.message}`
};
}
}
case 'MTCaptcha': {
try {
const solution = (await solver.mtCaptcha({
pageurl: page.url(),
sitekey: captchaData.siteKey || ''
}));
if (solution?.status === 1 && solution?.data) {
const success = await (0, inject_captcha_response_1.injectTokenResponse)(page, 'input[name="mtcaptcha-verifiedtoken"]', solution.data);
if (success) {
return {
success: true,
message: `MTCaptcha solved successfully.`
};
}
}
return {
success: false,
message: `Failed to solved MTCaptcha `
};
}
catch (error) {
return {
success: false,
message: `CAPTCHA error: ${error.message}`
};
}
}
default:
return {
success: false,
message: `Unsupported CAPTCHA type: ${captchaData.type}`
};
}
}
//# sourceMappingURL=two-captcha.js.map