Nodejs 如何 绕过 reCAPTCHA v2#

logoNextCaptcha
March 15,2024

关于 reCAPTCHA v2#

reCAPTCHA v2是谷歌开发的一种验证码系统,旨在帮助网站区分人类用户和自动化程序(如机器人)。它通过要求用户在完成表单提交或登录等操作之前点击复选框来验证其人类身份。reCAPTCHA v2通过分析用户的点击行为和浏览模式等信息,判断用户是否为真实的人类

reCAPTCHA v2 的类型#

  • Checkbox

如图所示,“我不是机器人”复选框要求用户单击指示用户不是机器人的复选框。这将立即通过用户(没有验证码)或挑战他们验证他们是否是人类

newCaptchaAnchor

  • Invisible

如图所示,不可见的 reCAPTCHA 徽章不需要用户单击复选框,而是在用户单击站点上的现有按钮时直接调用,或者可以通过 JavaScript API 调用来调用。reCAPTCHA 验证完成后,集成需要 JavaScript 回调。默认情况下,只有最可疑的流量才会被提示解决验证码

Untitled

在本文中,我们将揭开验证码的神秘面纱,并逐步介绍使用 nodejs 构建简单的reCAPTCHA v2求解器的过程。

环境准备#

首先,确保您的系统上安装了 Nodejs。此外,安装所需的库:
npm install axios
npm install cheerio
当目标网页是静态页面时,我们直接使用 `axios` 来下载相关网页,然后使用 `cheerio` 来解析网页并提取 绕过 reCAPTCHA v2 需要的相关数据 在开始正式绕过之前我们需要先注册下这个网站 NextCaptcha,注册个账号之后大家可以在后台获取一个账户密钥,也就是 clientKey,保存备用。 获取了相关 clientKey 后,我们就正式开始 绕过 reCAPTCHA v2 旅程了。 这里我们以官方的 Demo 来做例子 网址是 https://www.google.com/recaptcha/api2/demo

获取网页的 HTML#

const axios = require('axios');
 
async function getPageData(url) {
    try {
	    const data = await axios.get(url)
	    return data.data;
    }  catch (e) {
        console.error('getPageData error', e.message);
        return null;
    }
}
 
getPageData('https://www.google.com/recaptcha/api2/demo');

获取 reCAPTCHA 相关参数#

const cheerio = require('cheerio');
 
function parserData(html) {
    try {
        const $ = cheerio.load(html);
 
        return $('[data-sitekey]').data('sitekey')
 
    } catch (e) {
        console.error('parserData error', e.message);
        return null;
    }
}
 

构建绕过 reCAPTCHA v2 请求#

const axios = require('axios');
 
async function createCaptchaTask(url, siteKey, isInvisible) {
    try {
        const data = await axios.post('https://api.nextcaptcha.com/createTask', {
            "clientKey": "clientKey", // clientKey from NextCaptcha dashboard
            "task": {
                type: "RecaptchaV2TaskProxyless",
                websiteURL: url,
                websiteKey: siteKey,
                isInvisible
            }
        });
        return data.data;
    } catch (e) {
        console.error('createCaptchaTask error', e.message);
        return null;
    }
}

获取 reCAPTCHA v2 绕过任务结果#

const axios = require('axios');
 
async function sleep(time = 500) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve();
        }, time)
    })
}
async function getTaskResult(taskId) {
    try {
        const data = await axios.post('https://api.nextcaptcha.com/getTaskResult', {
            "clientKey": "clientKey", // clientKey from NextCaptcha
            taskId
        });
        if (data.data.status === 'processing') {
            await sleep();
            return getTaskResult(taskId)
        } else {
            console.error('createCaptchaTask errorCode', data.data.errorCode);
            console.error('createCaptchaTask errorDescription', data.data.errorDescription);
            return null;
        }
    } catch (e) {
        console.error('createCaptchaTask error', e.message);
        return null;
    }
}

把它们放在一起#

其中获取的 `result` 中的 gRecaptchaResponse 就是 reCAPTCHA v2 解决的 token, 我们可以拿 这个key 去提交给网站的相关接口
const axios = require('axios');
const cheerio = require('cheerio');
 
async function getPageData(url) {
    try {
	    const data = await axios.get(url)
	    return data.data;
    }  catch (e) {
        console.error('getPageData error', e.message);
        return null;
    }
}
 
function parserData(html) {
    try {
        const $ = cheerio.load(html);
 
        return $('[data-sitekey]').data('sitekey')
 
    } catch (e) {
        console.error('parserData error', e.message);
        return null;
    }
}
 
async function createCaptchaTask(url, siteKey, isInvisible) {
    try {
        const data = await axios.post('https://api.nextcaptcha.com/createTask', {
            "clientKey": "clientKey", // clientKey from NextCaptcha dashboard
            "task": {
                type: "RecaptchaV2TaskProxyless",
                websiteURL: url,
                websiteKey: siteKey,
                isInvisible
            }
        });
        return data.data;
    } catch (e) {
        console.error('createCaptchaTask error', e.message);
        return null;
    }
}
 
async function sleep(time = 500) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve();
        }, time)
    })
}
 
async function getTaskResult(taskId, tryTimes = 60) {
    try {
        const data = await axios.post('https://api.nextcaptcha.com/getTaskResult', {
            "clientKey": "clientKey", // clientKey from NextCaptcha
            taskId
        });
         if (data.data.status === 'ready') {
            return data.data;
        } else if (data.data.status === 'processing' && tryTimes >= 0) {
            await sleep();
            return getTaskResult(taskId)
        } else {
            if (tryTimes < 0) {
                console.error('getTaskResult out of time');
            } else {
                console.error('getTaskResult errorCode', data.data.errorCode);
                console.error('getTaskResult errorDescription', data.data.errorDescription);
            }
            return null;
        }
    } catch (e) {
        console.error('getTaskResult error', e.message);
        return null;
    }
}
 
async function mian() {
    const url = 'https://www.google.com/recaptcha/api2/demo'
    const html = await getPageData(url);
    const sitekey = parserData(html);
    console.log(sitekey)
    const task = await createCaptchaTask(url, sitekey, false);
    const result = await getTaskResult(task.taskId);
    console.log(result)
}
 
mian()