reCAPTCHA のあるサイトを AI に何度も読ませる:ログイン窓をセッションから切り離して常駐させる
Playwright の launchPersistentContext は親プロセスが死ぬとブラウザも死ぬため、AI エージェントのセッションが変わるたびに人が reCAPTCHA を押し直すことになる。detached 起動+CDP 接続、プロファイル固定とログイン保持、管理者権限を使わないログオン常駐の3層で解消する手順。exit code 契約と、実際に壊して確かめる検証手順つき。
約3.8万トークンの節約 (API料金換算で約56円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「reCAPTCHA のあるサイトを AI に何度も読ませる:ログイン窓をセッションから切り離して常駐させる」は、データ収集カテゴリのAI指示書(MDファイル)です。Playwright の launchPersistentContext は親プロセスが死ぬとブラウザも死ぬため、AI エージェントのセッションが変わるたびに人が reCAPTCHA を押し直すことになる。detached 起動+CDP 接続、プロファイル固定とログイン保持、管理者権限を使わないログオン常駐の3層で解消する手順。exit code 契約と、実際に壊して確かめる検証手順つき。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約3.8万トークン(API料金換算で約56円)・89%のトークンを節約できます。
- カテゴリ
- データ収集
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約4.2万トークン
- この巻物使用時
- 約4,500トークン
- 節約量
- 約3.8万トークン (約56円)
- 更新日
- 2026-09-03
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/recaptcha-ai/raw を読み込んで、この指示書どおりに実装して"
中身
reCAPTCHA のあるサイトを AI に何度も読ませる:ログイン窓を「セッションから切り離して」常駐させる
この指示書が解く問題
AI エージェント(Claude Code / Cursor / 自作エージェント)に、管理画面を繰り返し読ませたい。 だが対象サイトのログインに reCAPTCHA があり、自動ログインできない。人が1回押せばいい話なのに、 エージェントのセッションが終わるたびに押し直すことになる。1日に何度も起きる。
原因はほぼ確実にこれ。Playwright の launchPersistentContext で開いたブラウザは
呼び出したプロセスの子になる。エージェントのシェルが終わればブラウザも死ぬ。
プロファイル(Cookie)は残っているのに、窓が消えるので押し直しになる。
直し方は3層。この3つを全部やって初めて「切れない」と言える。
| 切れ方 | 対策 |
|---|---|
| エージェントのセッション終了で死ぬ | ブラウザを detached で起動し、CDP で後から繋ぐ |
| ブラウザを閉じる・落ちると死ぬ | プロファイルを固定し、サイトの「ログイン状態を保持」を必ず ON にする |
| OS 再起動で死ぬ | ログオン時に起こし直す常駐(管理者権限を使わない方法がある) |
1. detached で起動して CDP で繋ぐ
launchPersistentContext を捨てる。ブラウザの実行ファイルを自分で spawn する。
import { chromium } from 'playwright';
import { spawn } from 'node:child_process';
const CDP_PORT = 9222;
const PROFILE_DIR = '<固定プロファイルの絶対パス>'; // 例: <ホーム>/.agent/<サイト名>-profile
async function cdpAlive() {
try {
const res = await fetch(`http://127.0.0.1:${CDP_PORT}/json/version`,
{ signal: AbortSignal.timeout(3000) });
return res.ok;
} catch { return false; }
}
async function launch() {
const exe = chromium.executablePath(); // Playwright が入れた実行ファイル
const child = spawn(exe, [
`--remote-debugging-port=${CDP_PORT}`,
`--user-data-dir=${PROFILE_DIR}`,
'--no-first-run',
'--no-default-browser-check',
'--disable-blink-features=AutomationControlled',
'about:blank',
], { detached: true, stdio: 'ignore' }); // ← ここが本質
child.unref(); // ← 親が待たない
for (let i = 0; i < 60; i++) { // 最大30秒待つ
if (await cdpAlive()) return true;
await new Promise(r => setTimeout(r, 500));
}
return false;
}
// 以降は「生きているブラウザに繋ぐ」だけ
const browser = await chromium.connectOverCDP(`http://127.0.0.1:${CDP_PORT}`);
const context = browser.contexts()[0];
const page = await context.newPage(); // 既存タブを奪わない
落とし穴(ここで必ず1回は転ぶ)
connectOverCDPの戻り値にbrowser.close()を呼んではいけない。 常駐ブラウザが死ぬ。 閉じるのはnewPage()で自分が開いたタブだけ。finallyにbrowser.close()を 書いてしまうのが定番事故。pages()[0]を使うな。 他の処理が開いているタブを奪って表示を壊す。必ずnewPage()。- detached になったかはコードでなくプロセスの親で検証する。
デバッグポートを持つブラウザの root プロセスの ParentProcessId を調べ、
その親が終了済みなら成功。親がまだ自分のランタイムなら失敗している。
Windows なら:
Get-CimInstance Win32_Process -Filter "Name='chrome.exe'"のCommandLineをremote-debugging-portで絞り、ParentProcessIdの生存を見る。 - 二重起動を必ずガードする。 同じプロファイルを後から掴んだブラウザは 先に起動していたプロセスを掃除する。人がログイン待ちだった窓ごと消える。 起動前に必ず CDP の生死を見て、生きていれば起動しない。
2. 人の1クリックまで全部お膳立てする
未ログインなら、押す以外のことは全部機械がやる。
// value への直代入は input イベントが飛ばず、サイト側の JS が「未入力」と見なすことがある。
// 必ず fill を使う。
await page.fill('input[name="<ユーザー名欄>"]', creds.username);
await page.fill('input[name="<パスワード欄>"]', creds.password);
// 「ログイン状態を保持」を必ず ON にする。これが Cookie を長生きさせる肝。
const keep = await page.$('input[type="checkbox"]');
if (keep && !(await keep.isChecked())) await keep.check();
await page.bringToFront(); // 人に押してもらうときだけ前面へ
// reCAPTCHA と送信ボタンは押さない。迂回しない。
資格情報はリポジトリに置かない。 ホーム配下の JSON などに置き、そこから読む。
状態を exit code で外に出す
エージェントが判断できるように、状態を終了コードで返す。ログ文字列で判定させない。
0 = ログイン済み(そのまま読める)
1 = ブラウザは生きているが未ログイン(人が1クリックする必要がある)
2 = ブラウザに繋げない/起動できない/資格情報が無い
加えて状態を JSON ファイルに書いておくと、別のツールから参照できる。
{ "checkedAt": "...", "cdpUp": true, "loggedIn": false, "launched": false, "tabs": 1 }
ログイン判定は「パスワード欄が無い」だけでは足りない。 多くのサイトは
「メールを確認してください」の踊り場を挟み、そこにもパスワード欄が無いので誤って成功と判定する。
パスワード欄の有無 + 踊り場の文言 + 本文の長さ の3つで見る。
3. OS 再起動対策:管理者権限を使わない
タスクスケジューラ(Register-ScheduledTask)は昇格していないシェルでは
アクセスが拒否されました(HRESULT 0x80070005)で落ちる。人に管理者シェルを開かせるのは
手間が増えるだけなので、ユーザーのスタートアップフォルダを使う。昇格が一切不要。
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\<名前>.vbs:
' ASCII only. cscript/wscript mis-reads UTF-8 with BOM.
Option Explicit
Dim sh
Set sh = CreateObject("WScript.Shell")
Do
On Error Resume Next
sh.CurrentDirectory = "<ツールのある絶対パス>"
' 0 = hidden, True = wait so instances never stack up
sh.Run "cmd /c node <ツール> --ensure --no-front", 0, True
On Error Goto 0
WScript.Sleep 1800000 ' 30 min
Loop
- VBS の中身は ASCII だけにする。 BOM 付き UTF-8 を誤読して何も実行しない。
- 定期実行では前面に出さない(
--no-frontのようなフラグを用意する)。 30分ごとにフォーカスを奪うと人の作業を邪魔して、結局止められる。 - 消したいときはこの1ファイルを削除するだけにする。可逆にしておく。
macOS / Linux なら launchd の RunAtLoad / systemd の user unit(systemctl --user)で同じことをやる。
どちらも root 不要。
4. 「切れなくなった」と言う前に必ず実測する
3つとも実際に壊してから直るかを見る。コードを読んで納得しただけで報告してはいけない。
| 検証 | やり方 | 合格 |
|---|---|---|
| セッション終了に耐える | ブラウザ root プロセスの親を調べる | 親が終了済み |
| ブラウザ再起動に耐える | そのプロファイルのブラウザだけを全部落として起こし直す | 状態確認が exit 0 |
| OS 再起動に耐える | ブラウザを落とし、常駐スクリプトだけを起動する | 数十秒で復活する |
プロセスを落とすときは、必ず CommandLine にそのプロファイルのパスを含むものだけに絞る。
人が普段使いのブラウザを何十本も開いていることがある。名前だけで Stop-Process すると
仕事中のタブを全部消す。
「プロファイルを共有しても別プロセスでは未ログイン扱いになった」という観測は、 headless で起動していたことが原因である場合が多い。detached の非 headless 起動なら持続する。 過去の観測を持ち出して諦める前に、起動方法を変えて再検証する。
5. 得られる形
node <ツール> --status # 見るだけ。0=ログイン済み 1=未ログイン 2=繋げない
node <ツール> --ensure # 落ちていたら起こす+入力を埋めて前面へ
node <ツール> --ensure --no-front --shot out.png # 常駐用/実表示の記録
エージェント側は着手前に --status を叩き、exit 0 ならそのまま読む。
exit 1 のときだけスクショを撮って自分で目視してから、人に「1クリック」を頼む。
画面を見ずに手順を書くと、実在しないラベル名を書いて人に手戻りをさせる。
これで人の操作は「サイトがログインを失効させたとき、1回だけ」に減る。
よくある質問
+「reCAPTCHA のあるサイトを AI に何度も読ませる:ログイン窓をセッションから切り離して常駐させる」とは何ですか?
Playwright の launchPersistentContext は親プロセスが死ぬとブラウザも死ぬため、AI エージェントのセッションが変わるたびに人が reCAPTCHA を押し直すことになる。detached 起動+CDP 接続、プロファイル固定とログイン保持、管理者権限を使わないログオン常駐の3層で解消する手順。exit code 契約と、実際に壊して確かめる検証手順つき。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約4.2万トークンかかりますが、この巻物を使えば約4,500トークンで済みます。差し引き約3.8万トークン(API料金換算で約56円)・89%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
定期スクレイピング→Googleスプレッドシート自動集計MD
競合価格・在庫・ランキングなどを毎日自動取得してスプレッドシートに蓄積するバッチを AI に作らせる指示書。robots.txt 尊重・レート制限・差分検知のベストプラクティス込み。
Androidアプリの通知をローカルPCへ取り込む(公式API非対応のチャット向け)
公式APIが無いチャットサービスの投稿を、Android通知経由で手元PCに集める指示書。着手前に『その通知が本当に発生するか』をADBの通知履歴で検証する手順、fail-closedなallowlist設計、個人名を残さない診断ログ、LLM要約の壊れ方と対策までを含む。
外部サイトの「異常」を報告する前に計測器を対照群で検定する
自社の掲載が検索に出ない・売切表示になる等を疑ったとき、対照群をツールに実装して測定不能をexit 2で止める手順。UA未設定で空ページを掴む罠、分母が列挙可能かの見方、履歴のない画面で「いつ落ちたか」を測らない原則つき。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア