Nodejs で reCAPTCHA v2 をバイパスする方法#

logoNextCaptcha
March 15,2024

reCAPTCHA v2 について#

reCAPTCHA v2 は、Web サイトが人間のユーザーと自動プログラム (ボットなど) を区別できるようにするために Google によって開発された検証コード システムです。フォームの送信やログインなどのアクションを完了する前にチェックボックスをクリックすることをユーザーに要求することで、ユーザーの身元を確認します。 reCAPTCHA v2 は、ユーザーのクリック動作や閲覧パターンなどの情報を分析することで、ユーザーが本物の人間であるかどうかを判断します。

reCAPTCHA v2 の種類#

  • Checkbox

図に示すように、「私はロボットではありません」チェックボックスでは、ユーザーがロボットではないことを示すチェックボックスをクリックする必要があります。これにより、ユーザーは即座に (キャプチャなしで) 認証されるか、自分が人間であるかどうかを確認されます。

newCaptchaAnchor

  • Invisible

図に示すように、非表示の reCAPTCHA バッジはユーザーがチェックボックスをクリックする必要はありませんが、代わりにユーザーがサイト上の既存のボタンをクリックしたときに直接呼び出されるか、JavaScript API 呼び出し経由で呼び出すことができます。統合には、reCAPTCHA 検証が完了した後の JavaScript コールバックが必要です。デフォルトでは、最も疑わしいトラフィックのみに CAPTCHA を解決するよう求められます。

Untitled

この記事では、CAPTCHA をわかりやすく説明し、nodejs を使用してシンプルな reCAPTCHA v2 ソルバーを構築するプロセスを順を追って説明します。

環境整備#

まず、Nodejs がシステムにインストールされていることを確認します。さらに、必要なライブラリをインストールします。
npm install axios
npm install cheerio
ターゲット Web ページが静的ページの場合、`axios` を使用して関連する Web ページをダウンロードし、その後、`cheerio` を使用して Web ページを解析し、reCAPTCHA v2 をバイパスするために必要な関連データを抽出します。 公式バイパスを開始する前に、Web サイト NextCaptcha を登録する必要があります。アカウントを登録した後、バックグラウンドでアカウント キー (clientKey) を取得し、後で使用できるように保存できます。 関連する clientKey を取得した後、reCAPTCHA v2 をバイパスする作業を正式に開始します。 ここでは例として公式デモを使用します。URL は https://www.google.com/recaptcha/api2/demo です。

Webページの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;
    }
}

それらを一緒にします#

取得した「結果」の gRecaptchaResponse は reCAPTCHA v2 によって解決されたトークンであり、このキーを使用して Web サイトの関連インターフェイスに送信できます。
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()