Node.jsでcaptcha解決:fetchを使った動作例(2026年)
Node.jsでcaptchaソルバーを作るのは、HTTPリクエストが1回です。Node 18以降にはfetchが含まれているので、APIを呼び出すのにパッケージは不要です。サイトキーとページURLを送り、レスポンスを待ち、トークンをフォームに入れてください。このガイドでは、Scarnoxが現在プロキシなしで解決しているPopularCaptchaの流れ全体を示します。
まず下のコードをテスト用のページで実行してください。無料のトライアルクレジットで始める(カード登録は不要)こともできます。
必要なもの
- Node.js 18以降(
node --versionで確認)。 - ScarnoxのAPIキー。環境変数に保存してください。
- ページのPopularCaptchaウィジェットのサイトキー。まだ持っていなければ、captchaのサイトキーの見つけ方を参照してください。
ソルバーモジュール
以下のモジュールは1つの関数です。Bearerヘッダーを付けてAPIにPOSTし、185秒で中断し、errorIdが0でない場合は例外を投げます。
// solver.mjs
const API_URL = "https://api.scarnox.com/api/tasks/create";
export async function solveCaptcha(sitekey, pageUrl, { invisible = false } = {}) {
const body = {
captcha_type: "PopularCaptchaTaskProxyless",
site_key: sitekey,
site_url: pageUrl,
};
if (invisible) body.is_invisible = true;
const res = await fetch(API_URL, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SCARNOX_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(185_000), // トークンの準備ができると戻る
});
const data = await res.json().catch(() => null);
if (!data) throw new Error(`HTTP ${res.status}: response was not JSON`);
if (data.errorId !== 0) {
throw new Error(`${data.errorCode}: ${data.errorDescription}`);
}
return data.solution.token;
}
ポーリングはありません。リクエストはトークンの準備ができるまで開いたままで、成功時にはトークンがsolution.tokenに入ります。
リトライ
失敗した解決はerrorIdが0以外になり、その分の課金はされません。一時的な失敗には短いリトライループで十分です。試行回数は少なく保ち、サイトキーやページURLが間違っているときに時間を浪費しないようにしてください。
export async function solveWithRetry(sitekey, pageUrl, attempts = 3) {
let lastError;
for (let i = 1; i <= attempts; i++) {
try {
return await solveCaptcha(sitekey, pageUrl);
} catch (err) {
lastError = err;
console.warn(`Attempt ${i} failed: ${err.message}`);
await new Promise((r) => setTimeout(r, 1000 * i));
}
}
throw lastError;
}
より完全なエラーのポリシーは、captcha解決のエラー処理を参照してください。
トークンの送信
トークンは、サイトが期待するフォームのフィールドに入れます。PopularCaptchaのページの多くはh-captcha-responseを読み、g-recaptcha-responseも読むものが多くあります。安全のために両方を送ってください。
// submit.mjs
import { solveWithRetry } from "./solver.mjs";
const pageUrl = "https://example.com/signup";
const token = await solveWithRetry("YOUR-SITEKEY-UUID", pageUrl);
const form = new URLSearchParams({
email: "you@example.com",
"h-captcha-response": token,
"g-recaptcha-response": token,
});
const res = await fetch(pageUrl, {
method: "POST",
body: form,
redirect: "manual",
});
console.log("Status:", res.status);
実行します。
SCARNOX_API_KEY=scarnox_YOURAPIKEY node submit.mjs
CookieとセッションCookie
素のfetchは、リクエストの間でCookieを保持しません。多くの会員登録や検索のページは、captchaをセッションCookieに紐づけているため、対応するCookieなしで送ったトークンは拒否されることがあります。扱い方は2つあります。
- GETのレスポンスから
set-cookieの値をコピーし、POSTで送り返す。 - ブラウザの自動化ツールを使う。ツールがセッションを保持してくれます。PlaywrightとPuppeteerでのcaptcha解決を参照してください。
フォームが単純で、サイトがJavaScriptをあまり実行しない場合は前者を選びます。それ以外は後者を選んでください。
実用的な確認方法として、POSTの後にステータスコードと最終的なURLを見てください。成功ページへのリダイレクトは、通常、トークンが受け付けられたことを意味します。ウィジェットがもう一度表示されるページは、通常、拒否されたか、GETのCookieが引き継がれていないことを意味します。最初の数回の実行ではレスポンスのボディをログに残して、どちらの場合かを見分けてください。
タイミング
トークンは約2分で期限切れになります。送信の直前に解決してください。よくある間違いは、長い処理の開始時に解決し、後で送信することです。解決したら、すぐに送信してください。captchaトークンの期限切れで詳しく扱っています。
不可視のcaptcha
ページのウィジェットがdata-size="invisible"を持つ場合は、{ invisible: true }を渡してください。関数はリクエストにis_invisible: trueを付けて送ります。
const token = await solveCaptcha("YOUR-SITEKEY-UUID", pageUrl, { invisible: true });
ページがウィジェットにコールバックを付けている場合、フォームはトークンを引数にそのコールバックを呼ぶ必要があるかもしれません。ページのスクリプトを読んで見つけてください。パターンは不可視captchaのガイドで扱っています。
ソルバーでのスクレイピング
captchaが、送信するフォームではなく、スクレイピングするページに出てくることもあります。同じパターンが使えます。HTMLの中のウィジェットを検出し、解決して、ウィジェットがPOSTする先のURLに送信します。リクエストの頻度は低く保ち、送信前にサイトの利用規約を確認してください。責任あるスクレイピングとして、robots.txtを尊重し、必要のない個人データは避け、サーバーに負荷をかけないでください。
料金
Scarnoxは成功した解決ごとに課金します。失敗した解決は課金されません。現在の料金は料金ページを参照してください。始めるには、無料のトライアルクレジットで始める(カード登録は不要)ことができます。