UNPKG

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

103 lines (95 loc) 4.98 kB
import type { CaptchaParams } from '@/types'; /** * Initializes a custom function within the captcha iframe to extract parameters. * * This function injects a script that extracts the required parameters from the captcha page. * It creates a canvas to work with captcha images, extracts image tiles, and provides metadata like * rows, columns, and a base64-encoded image of the current captcha state. * * @async * @function initCaptchaParamsExtractor * @param {import('puppeteer').Frame} frame - A Puppeteer frame representing the reCAPTCHA iframe. * @returns {Promise<void>} This function doesn't return a value itself but adds a function (`getRecaptchaParams`) * into the frame context to extract captcha parameters. * @throws Will reject the promise if reCAPTCHA elements cannot be found on the page. */ export const initCaptchaParamsExtractor = async function (frame: any): Promise<void> { await frame.evaluate(() => { (window as any).getRecaptchaParams = (): Promise<CaptchaParams> => { return new Promise((resolve, reject) => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); if (!ctx) { reject('Failed to get canvas rendering context'); return; } const commentElement = document.querySelector('.rc-imageselect-desc-wrapper'); const comment = commentElement ? commentElement.textContent?.replaceAll('\n', ' ') || '' : ''; const img4x4 = document.querySelector<HTMLImageElement>('img.rc-image-tile-44'); if (!img4x4) { const table3x3 = document.querySelector( 'table.rc-imageselect-table-33 > tbody' ); if (!table3x3) { reject('Cannot find reCAPTCHA elements'); return; } const initial3x3img = table3x3.querySelector<HTMLImageElement>('img.rc-image-tile-33'); if (!initial3x3img) { reject('Cannot find initial 3x3 image'); return; } canvas.width = initial3x3img.naturalWidth; canvas.height = initial3x3img.naturalHeight; ctx.drawImage(initial3x3img, 0, 0); const updatedTiles = document.querySelectorAll<HTMLImageElement>('img.rc-image-tile-11'); if (updatedTiles.length > 0) { const pos = [ { x: 0, y: 0 }, { x: ctx.canvas.width / 3, y: 0 }, { x: (ctx.canvas.width / 3) * 2, y: 0 }, { x: 0, y: ctx.canvas.height / 3 }, { x: ctx.canvas.width / 3, y: ctx.canvas.height / 3 }, { x: (ctx.canvas.width / 3) * 2, y: ctx.canvas.height / 3 }, { x: 0, y: (ctx.canvas.height / 3) * 2 }, { x: ctx.canvas.width / 3, y: (ctx.canvas.height / 3) * 2 }, { x: (ctx.canvas.width / 3) * 2, y: (ctx.canvas.height / 3) * 2 } ]; updatedTiles.forEach((t) => { const parentElement = t.parentElement?.parentElement ?.parentElement as HTMLElement | null; if (parentElement && parentElement.tabIndex >= 3) { const ind = parentElement.tabIndex - 3; if (ind >= 0 && ind < pos.length) { ctx.drawImage(t, pos[ind].x, pos[ind].y); } } }); } resolve({ rows: 3, columns: 3, type: 'GridTask', comment, body: canvas.toDataURL().replace(/^data:image\/?[A-z]*;base64,/, '') }); } else { canvas.width = img4x4.naturalWidth; canvas.height = img4x4.naturalHeight; ctx.drawImage(img4x4, 0, 0); resolve({ rows: 4, columns: 4, comment, body: canvas.toDataURL().replace(/^data:image\/?[A-z]*;base64,/, ''), type: 'GridTask' }); } }); }; }); };