TypeScriptでCAPTCHAタスクの結果を安全に処理する
result.solution を読み取る前に、result.status で分岐してください。利用可能なソリューションが含まれるのは ready だけですが、その場合も、リクエストした製品に必要なフィールドを確認する必要があります。Kasada はヘッダーを返し、reCAPTCHA と TMPT はそれぞれ用途の異なるトークンを返します。
このページの内容
ソリューションを読む前にステータスで型を絞り込む
入力には SDK がエクスポートする TaskRequest を、レスポンスには TaskResult を使用してください。ステータスで型を絞り込むことで、any や、コンパイラーに単に信用させるだけのキャストを使わずに、TypeScript が未完了、失敗、準備完了を区別できるようになります。
import { Solvethree, type TaskRequest, type TaskResult } from '@solvethree/sdk';
const client = new Solvethree({ apiKey: process.env.SOLVETHREE_API_KEY! });
const input: TaskRequest = { site: 'accounts.example.com', action: 'login', proxy: process.env.SOLVETHREE_PROXY! };
function inspect(result: TaskResult): void {
switch (result.status) {
case 'pending':
case 'solving':
console.log('Retrieve this task again:', result.id);
return;
case 'failed':
console.error('Failed task:', result.id, result.errorCode);
return;
case 'ready':
// Solution fields depend on the requested product; check optional fields.
if (!result.solution.token || !result.solution.userAgent || !result.solution.secChUa) {
throw new Error('Expected a complete reCAPTCHA solution');
}
console.log('Ready task:', result.id);
// Submit token privately with its browser identity and original proxy.
return;
}
}
inspect(await client.createTask(input, { waitMs: 0 }));
// Save the returned ID and call getTask while pending/solving with a deadline.この例では、タスクを1つ作成し、直後のレスポンスを確認します。pending と solving の場合は再取得し、failed の場合は処理を停止し、ready の場合はソリューションの検証に進みます。ready の分岐をヘルパーに切り出す場合は、引数にエクスポートされた ReadyTask 型を使用してください。これでステータスは絞り込まれますが、製品固有のすべてのソリューションフィールドが必須になるわけではありません。
この入力は reCAPTCHA を要求するため、ガードではトークンと2つのブラウザー識別フィールドを確認します。ただし、これらの確認でトークンが対象サイトに受け入れられると証明できるわけではありません。この例では意図的にトークンを出力していません。
- Node.js 22+ を使用し、API ドキュメントに記載された公式 SDK の tarball インストール手順に従ってください。npm レジストリにリリースがあるとは限りません。
- サーバー環境で
SOLVETHREE_API_KEYとSOLVETHREE_PROXYを設定してください。!アサーションは、実行時に環境変数の欠落を検証するものではありません。 accounts.example.comとloginを、使用するホスト名とアクションに置き換えてください。そのサイトには、ワークスペースで有効なプロファイルがあらかじめ必要です。サイトプロファイルの設定を参照してください。
新しいタスクではなく、保存した ID をポーリングする
この例では、ポーリングは呼び出し側に任せています。作成処理はそのループの外に置いてください。createTask を再度呼び出しても、最初のタスクが完了したかどうかは確認できません。
- 1.
作成結果の ID を保存する
返された ID が空でない文字列であることを確認してから、取得に使用してください。元のリクエストと紐付けて保持してください。成功したプロキシを選択する際にも、元のリクエストが必要です。
- 2.
同じタスクを取得する
ステータスが
pendingまたはsolvingの間は、ローカルの期限を設けて、保存した ID でgetTaskを呼び出してください。各レスポンスを処理する前に、その ID が保存した ID と一致することを確認します。ID の一致で確認できるのは、扱っているタスクがどれかということであり、成功したかどうかではありません。 - 3.
終端結果で停止する
readyの場合は、要求した製品に必要なフィールドを検証します。failedの場合は、errorCodeとerrorの両方を確認し、そのタスクのポーリングを停止してください。リクエストエラーは別に処理します。取得リクエストの失敗自体は、タスクの終端的な失敗ではありません。
ID を受け取る前に作成がタイムアウトしても、タスクが作成されなかったとは判断しないでください。requestId を指定していた場合は、同じ値で同一のリクエストを再送すると、既存のタスクを復旧できます。入力を変更してその値を再利用すると競合します。新しい値を生成しても、元のタスクは復旧できません。
ready の結果にも適切な製品ハンドラーが必要
元のリクエストに基づいてハンドラーを選び、想定されるソリューションフィールドを確認してください。トークンが存在するだけでは、reCAPTCHA レスポンスと TMPT Cookie 値を区別できません。
| 要求した製品 | ソリューションの値 | 使用方法 |
|---|---|---|
| reCAPTCHA Enterprise | solution.token | 対象のホスト名とアクションに対応する reCAPTCHA トークンとして送信します。 |
| KasadaTask | solution.headers | 返されたヘッダーをまとめて適用してください。この結果をトークンとして扱わないでください。 |
| TicketmasterTmptTask | solution.token | reCAPTCHA トークンではなく、生の tmpt Cookie 値として使用します。 |
スタンドアロンの Kasada は現在、www.ticketmaster.com の HTTPS ターゲットに対応しており、任意のサイトには対応していません。そのヘッダーハンドラーは、汎用的な Kasada 連携ではありません。
各製品では、返された userAgent と secChUa、および成功したプロキシを使って送信してください。プロキシ候補を使用する場合は、最初の候補が成功したと決めつけず、successfulProxy(originalTask, readyResult) を使用します。SDK が対象サイトにソリューションを適用するわけではなく、ready も、その後のリクエストが受け入れられることを保証しません。
参照元とAPIリファレンス
最初のタスクを実行しましょう。
$5のワークスペースクレジットで始められます。