clicks-recaptcha-solver
Version:
A powerful automation tool for solving Google reCAPTCHA challenges using Playwright and Puppeteer. This package intelligently detects and simulates human-like interactions, including mouse movements and precise clicks, to bypass reCAPTCHA v2 and other sim
98 lines (81 loc) • 3.99 kB
text/typescript
import { Solver } from '@2captcha/captcha-solver';
import { Page } from 'playwright-core';
import { initCaptchaParamsExtractor } from './lib/initCaptchaParamsExtractor';
import { getCaptchaParams } from './lib/getCaptchaParams';
import { clickRecaptchaVerifyButton } from './lib/clickRecaptchaVerifyButton';
import { clickAtCoordinates } from './lib/clickAtCoordinates';
import { isRecaptchaPassed } from './lib/isRecaptchaPassed';
import { isFoundRecaptchaChallengeFrame } from './lib/isFoundRecaptchaChallengeFrame';
import { isFoundReCaptchaBadge } from './lib/isFoundReCaptchaBadge';
const sleep = (time: number) => new Promise((resolve) => setTimeout(resolve, time));
export const captchaSolver = async function (page: Page, APIkey: string) {
const solver = new Solver(APIkey, 500);
const recaptchaBadgeIframeSelector = 'iframe[title="reCAPTCHA"]';
const recaptchaCheckboxSelector = 'span.recaptcha-checkbox-unchecked';
await page.waitForSelector(recaptchaBadgeIframeSelector, { timeout: 30000 });
await sleep(5000);
if (!(await isFoundReCaptchaBadge(page))) {
throw new Error('reCAPTCHA Badge not found!');
}
const iframeElementHandle = await page.$(recaptchaBadgeIframeSelector);
if (!iframeElementHandle) {
throw new Error('reCAPTCHA Badge iframe not found!');
}
const recaptchaBadgeIframe = await iframeElementHandle.contentFrame();
if (recaptchaBadgeIframe) {
await recaptchaBadgeIframe.evaluate((recaptchaCheckboxSelector) => {
const recaptchaCheckbox = document.querySelector(recaptchaCheckboxSelector);
if (recaptchaCheckbox) {
(recaptchaCheckbox as HTMLElement).click();
} else {
throw new Error('reCAPTCHA checkbox not found!');
}
}, recaptchaCheckboxSelector);
await sleep(5000);
if (await isFoundRecaptchaChallengeFrame(page)) {
const frameHandle = await page.waitForSelector(
'iframe[src*="https://www.google.com/recaptcha/api2/bframe"]'
);
const frame = await frameHandle.contentFrame();
await initCaptchaParamsExtractor(frame);
let isCaptchaNotSolved = true;
const highlightClicks = false;
while (isCaptchaNotSolved) {
const captchaParams = await getCaptchaParams(frame);
const answer = await solver.grid({
body: captchaParams.body,
textinstructions: captchaParams.comment,
cols: captchaParams.columns,
rows: captchaParams.rows,
canSkip: 1,
imgType: 'recaptcha',
recaptcha: 1
});
if (answer.data) {
if (answer.data === 'No_matching_images') {
await sleep(1213);
await clickRecaptchaVerifyButton(page);
}
} else {
return false;
}
const clicks = answer.data
.replace('click:', '')
.split('/')
.map((el) => Number(el));
const captchaSize = captchaParams.columns;
const timeToSleep = 100;
for (const [index, el] of clicks.entries()) {
await sleep(timeToSleep * index);
await clickAtCoordinates(page, captchaSize, el, highlightClicks);
}
await sleep(timeToSleep * (clicks.length + 1) + 2202);
await clickRecaptchaVerifyButton(page, highlightClicks);
await sleep(3000);
isCaptchaNotSolved = !(await isRecaptchaPassed(page));
}
return true;
}
}
return false;
};