Node.jsでreCAPTCHA Enterpriseを解く
Node.js 22以降で公式solvethree JavaScript SDKを使用します。有効なサイトプロファイルを設定し、サイトのホスト名とアクションを指定して、プロキシ経由で解決します。SDKはトークンとブラウザー識別情報を返し、アプリケーションがそれらを対象に送信します。
このページの内容
SDKのインストールとサイトの設定
公式パッケージをsolvethree.comから直接インストールします。
npm install https://solvethree.com/downloads/solvethree-sdk-0.1.0.tgz- 1.
サイトプロファイルの有効化
コンソールで対象サイトを設定し、そのプロファイルが有効で、ワークスペースから利用できることを確認してください。ホスト名とアクションを送信しても、プロファイルは作成されません。サイトプロファイルの設定を参照してください。
- 2.
サーバー環境の設定
Node.jsプロセスの環境で、SOLVETHREE_API_KEYにワークスペースのAPIキーを、SOLVETHREE_PROXYにプロキシURLを設定してください。APIキーはサーバー側で保持し、ブラウザーコードに公開しないでください。
- 3.
スクリプトの準備
次の例をsolve.mjsとして保存してください。accounts.example.comを設定済みのホスト名に、loginをそのページの実際のreCAPTCHAアクションに置き換えてください。
Enterpriseトークンのリクエスト
siteにはページURLではなくホスト名を使用してください。reCAPTCHAのデフォルトはenterprise-v3なので、この例ではrecaptchaTypeは不要です。typeやurlは追加しないでください。リクエストにはproxyまたはproxyCandidatesのいずれか一方だけが必要です。この例では単一のプロキシを使用します。
import { randomUUID } from 'node:crypto';
import { Solvethree, SolvethreeError, TaskFailedError } from '@solvethree/sdk';
const client = new Solvethree({ apiKey: process.env.SOLVETHREE_API_KEY });
const request = {
site: 'accounts.example.com', // Use your configured hostname.
action: 'login', // Use the page's actual action.
proxy: process.env.SOLVETHREE_PROXY,
requestId: randomUUID(),
};
let result;
try {
result = await client.solve(request, { timeoutMs: 180_000 });
} catch (error) {
if (error instanceof TaskFailedError) {
throw new Error(`Task failed: ${error.errorCode}`);
}
if (error instanceof SolvethreeError) {
// Save these IDs; use them to recover the existing task.
console.error({ requestId: error.requestId, taskId: error.taskId });
}
throw error;
}
const { token, userAgent, secChUa } = result.solution;
console.log('Ready task:', result.id); // Keep solution credentials private.環境変数を設定してから、Node.jsでスクリプトを実行してください。solveはタスクを一度作成し、準備完了になるか例外を送出するまでポーリングします。180,000ミリ秒のタイムアウトは、クライアントの待機時間の上限です。
返される各フィールドの役割は次のとおりです。
result.idはタスクを識別します。CAPTCHAトークンではありません。result.solution.tokenは、アプリケーションのCAPTCHAフィールドに送信する値です。result.solution.userAgentとresult.solution.secChUaは、そのトークンと一緒に使用するブラウザー識別情報です。
解決結果の値は非公開にしてください。プロセスの再起動後に復旧する必要がある場合は、solveを呼び出す前にrequestIdと正確なタスク入力を保存し、プロキシの認証情報を保護してください。
同じプロキシ経由で送信する
solveが返った後、同じスクリプト内で処理を続けます。この例ではundiciを使用するため、コメントの説明に従って別途インストールする必要があります。トークンをrequest.proxy経由で送信し、返されたブラウザー識別情報の両フィールドを使用します。
// Continue after client.solve(). Install undici separately: npm install undici@7.
import { fetch, ProxyAgent } from 'undici';
const dispatcher = new ProxyAgent(request.proxy);
try {
// Replace the URL and form fields with your application's contract.
const response = await fetch('https://accounts.example.com/login', {
method: 'POST',
dispatcher,
redirect: 'manual',
headers: {
'user-agent': result.solution.userAgent,
'sec-ch-ua': result.solution.secChUa,
},
body: new URLSearchParams({
'g-recaptcha-response': result.solution.token,
}),
signal: AbortSignal.timeout(30_000),
});
console.log('Application HTTP status:', response.status);
await response.arrayBuffer();
} finally {
await dispatcher.close();
}URLとフォームフィールドを、アプリケーションの仕様に合わせて置き換えてください。この例で指定しているのはg-recaptcha-responseだけです。アプリケーションが必要とするその他のフィールドとセッションデータも含めてください。送信先は、解決時のサイトとアクションに一致させてください。
解決リクエストではプロキシを1つ使用しているため、request.proxyを再利用すると、送信にもそのプロキシが使用されます。リクエストを変更してproxyCandidatesを使用する場合は、代わりにSDKのsuccessfulProxyヘルパーで成功したプロキシを選択してください。
タスクが準備完了になったことは、解決結果が生成されたことを意味し、送信先がアプリケーションリクエストを受け入れたことを意味するわけではありません。送信先のレスポンスを確認し、実際の成功条件を満たしているか判断してください。HTTPステータスを出力するだけでは不十分です。拒否の原因を診断するには、準備完了のトークンが拒否された場合を参照してください。
障害への対処と中断したリクエストの復旧
解決処理の例では、タスクの最終的な失敗とその他のSDKエラーを分けています。この区別を維持してください。タスクの失敗とHTTPリクエストの失敗では、必要な対処が異なります。
- solveがTaskFailedErrorを送出する
例外にはerrorCodeとtaskIdが含まれます。エラーテキストを含む、失敗したタスクの完全なレスポンスが必要な場合は、getTask(taskId)を呼び出してください。
試してみましょう: そのタスクのポーリングを停止し、別のタスクを作成する前に、報告された原因に対処してください。無効な入力を変更しないまま再試行しないでください。
- SolvethreeErrorにtaskIdが含まれる
SDKは既存タスクのIDを保持しています。
試してみましょう: getTaskでポーリングを再開してください。pendingまたはsolvingの間は続行し、readyになった場合にのみ解決結果を使用し、failedになったら停止してください。
- 作成が中断し、requestIdしか利用できない
接続がタイムアウトしても、タスクが作成されなかったとは限りません。
試してみましょう: まったく同じタスク入力と同じrequestIdを使って、createTaskで復旧してください。そのIDを異なる入力で再利用すると、競合が発生します。
- APIがHTTPリクエストを拒否する
レスポンスを準備完了または失敗したタスクとして扱うのではなく、ApiErrorが公開するHTTPステータスを確認してください。
試してみましょう: 成功時のペイロードを処理する前に、HTTPエラーに対処してください。すべての失敗が残高不足によるものだと決めつけないでください。
このサンプルでは、プログラムが起動するたびに新しいrequestIdを生成します。そのまま再実行しても復旧にはなりません。代わりに、保存したリクエストとIDを使用してください。SDKはタスク作成を自動的には再試行しません。ただし、解決処理の期限内に発生した一時的なポーリングの失敗では、Retry-Afterに従います。
明示的なポーリングと待機設定については、タスクのポーリングとタイムアウトを参照してください。
参照元とAPIリファレンス
最初のタスクを実行しましょう。
$5のワークスペースクレジットで始められます。