この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:atom
更新日時:2026-06-11 07:07:02

タイトル: エラー一覧
SEOタイトル: reCAPTCHA エラー一覧と対処完全ガイド

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong>missing-input-secret</strong>: シークレットキー未送信 → サーバ側で secret パラメータ漏れ</li><li><strong>invalid-input-secret</strong>: シークレットキー誤り → v2/v3 の取り違え、サイトキーを使っていないか</li><li><strong>missing-input-response</strong>: トークン未送信 → フォームに <code>g-recaptcha-response</code> が無い</li><li><strong>invalid-input-response</strong>: トークン無効 → 期限切れ (2 分)、別ドメインで生成、テストキー本番混在</li><li><strong>timeout-or-duplicate</strong>: 同一トークン二重送信 / 期限切れ → 検証は 1 回のみ・即時に実施</li></ul></td></tr></table>
<h2>reCAPTCHA とは</h2>

<p>Google が提供する Bot 判定サービス。フォームの自動投稿(スパム / 不正登録)を防ぐためにクライアント側で <code>g-recaptcha-response</code> トークンを生成し、サーバ側で Google の API に問い合わせて検証します。</p>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>バージョン</th><th>特徴</th><th>UI</th></tr></thead>
<tbody>
<tr><td>v2 Checkbox</td><td>「私はロボットではありません」</td><td>クリック + 画像チャレンジ</td></tr>
<tr><td>v2 Invisible</td><td>透明、ボタンクリックで起動</td><td>必要時のみチャレンジ</td></tr>
<tr><td>v3</td><td>スコア (0.0〜1.0) 返却、UI なし</td><td>無し、サイト側で閾値判定</td></tr>
<tr><td>Enterprise</td><td>有料、高度な機能</td><td>v3 ベース</td></tr>
</tbody>
</table>

<h2>error-codes の主要パターン</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#ffebee"><th>エラーコード</th><th>意味</th><th>主な原因</th></tr></thead>
<tbody>
<tr><td><code>missing-input-secret</code></td><td>secret パラメータが無い</td><td>サーバ送信パラメータ漏れ</td></tr>
<tr><td><code>invalid-input-secret</code></td><td>secret が無効</td><td>キー打ち間違い、サイトキー渡しミス、v2/v3 取り違え</td></tr>
<tr><td><code>missing-input-response</code></td><td>response パラメータが無い</td><td>クライアントからのトークン送信漏れ</td></tr>
<tr><td><code>invalid-input-response</code></td><td>response が無効</td><td>期限切れ (2 分)、改竄、別サイトキーで生成</td></tr>
<tr><td><code>bad-request</code></td><td>リクエスト不正</td><td>HTTP メソッド誤り、ヘッダー不足</td></tr>
<tr><td><code>timeout-or-duplicate</code></td><td>期限切れ or 二重利用</td><td>トークン使い回し、検証遅延</td></tr>
<tr><td><code>browser-error</code></td><td>ブラウザ側エラー</td><td>JS 無効、CSP ブロック</td></tr>
</tbody>
</table>

<h2>サーバ側検証の最小実装 (PHP)</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">$token = $_POST[&apos;g-recaptcha-response&apos;] ?? &apos;&apos;;
$secret = env(&apos;RECAPTCHA_SECRET&apos;);

$response = file_get_contents(
    &apos;https://www.google.com/recaptcha/api/siteverify?&apos; . http_build_query([
        &apos;secret&apos; => $secret,
        &apos;response&apos; => $token,
        &apos;remoteip&apos; => $_SERVER[&apos;REMOTE_ADDR&apos;],
    ])
);

$result = json_decode($response, true);
/*
[
    &apos;success&apos; => true,
    &apos;challenge_ts&apos; => &apos;2026-06-10T01:23:45Z&apos;,
    &apos;hostname&apos; => &apos;example.com&apos;,
    &apos;score&apos; => 0.9,           // v3 のみ
    &apos;action&apos; => &apos;login&apos;,      // v3 のみ
    &apos;error-codes&apos; => [...],   // エラー時のみ
]
*/

if (!($result[&apos;success&apos;] ?? false)) {
    $codes = $result[&apos;error-codes&apos;] ?? [];
    throw new Exception(&apos;reCAPTCHA 失敗: &apos; . implode(&apos;,&apos;, $codes));
}

// v3 はスコア閾値判定
if (($result[&apos;score&apos;] ?? 0) < 0.5) {
    throw new Exception(&apos;Bot の疑いがあります&apos;);
}</code></pre>
<h2>各エラーの詳細対処</h2>

<h3>missing-input-secret / invalid-input-secret</h3>

<ul>
<li>Google Cloud Console → reCAPTCHA admin で<strong>シークレットキー</strong> (6L で始まる) を再確認</li>
<li>サイトキー (HTML 側、6L から始まる) と<strong>取り違えていないか</strong></li>
<li>v2 用キーで v3 を検証していないか(バージョン違いキーは互換性無し)</li>
<li><code>.env</code> に <code>RECAPTCHA_SECRET</code> が定義されているか、<code>php artisan config:cache</code> 漏れ</li>
<li>テスト用キー(<code>6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe</code> 等)を本番に残していないか</li>
</ul>

<h3>missing-input-response</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- ✅ v2 Checkbox -->
<script src="https://www.google.com/recaptcha/api.js" async defer></script>

<form method="POST" action="/submit">
    <div class="g-recaptcha" data-sitekey="YOUR_SITE_KEY"></div>
    <!-- ↑ submit 時に hidden の name="g-recaptcha-response" が自動生成される -->
    <button type="submit">送信</button>
</form>

<!-- ✅ v3 (透明) -->
<script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>
<script>
grecaptcha.ready(() => {
  grecaptcha.execute(&apos;YOUR_SITE_KEY&apos;, { action: &apos;login&apos; }).then((token) => {
    document.getElementById(&apos;recaptcha-token&apos;).value = token;
  });
});
</script>
<form id="login-form">
  <input type="hidden" name="g-recaptcha-response" id="recaptcha-token">
</form></code></pre>
<h3>invalid-input-response</h3>

<ul>
<li>トークンの寿命は<strong>2 分</strong>。フォーム表示から送信まで時間がかかる場合は<strong>再生成</strong>が必要</li>
<li>SPA / 多段ページのフローでトークンを使い回している</li>
<li>サイトキーとシークレットキーが<strong>別ドメイン分</strong>になっている(ステージング用キーを本番で使用など)</li>
<li>Google Cloud で<strong>ドメイン登録</strong>済か(v2/v3 とも本番ドメインを admin に追加要)</li>
</ul>

<h3>timeout-or-duplicate</h3>

<ul>
<li>同一トークンを<strong>2 回検証</strong>している(リダイレクト後再送、リトライ機構)</li>
<li>サーバ側のキューに積んで遅延処理 → 既に 2 分経過</li>
<li>クライアント側 JS バグでトークンを使い回し</li>
</ul>

<h2>Laravel での実装 (anhskohbo/no-captcha)</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-bash">composer require anhskohbo/no-captcha</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// .env
NOCAPTCHA_SECRET=6LXXXXXXX_secret_key
NOCAPTCHA_SITEKEY=6LXXXXXXX_site_key

// config/no-captcha.php
return [
    &apos;secret&apos; => env(&apos;NOCAPTCHA_SECRET&apos;),
    &apos;sitekey&apos; => env(&apos;NOCAPTCHA_SITEKEY&apos;),
    &apos;options&apos; => [
        &apos;timeout&apos; => 30,
    ],
];

// Blade
{!! NoCaptcha::renderJs(&apos;ja&apos;) !!}
<form method="POST">
    @csrf
    {!! NoCaptcha::display() !!}
    <button>送信</button>
</form>

// バリデーション
$request->validate([
    &apos;g-recaptcha-response&apos; => &apos;required|captcha&apos;,
]);</code></pre>
<h2>v3 のスコア活用</h2>

<p>v3 は 0.0 (Bot 確実) 〜 1.0 (人間確実) のスコアを返します。閾値はサイト次第:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">$score = $result[&apos;score&apos;] ?? 0;
$action = $result[&apos;action&apos;] ?? &apos;&apos;;

if ($action !== &apos;login&apos;) {
    abort(400, &apos;action mismatch&apos;);
}

if ($score >= 0.7) {
    // 通常処理
} elseif ($score >= 0.3) {
    // 追加チャレンジ(メール認証 / SMS)
} else {
    // ブロック or 詳細ログ
    Log::warning(&apos;Low reCAPTCHA score&apos;, [&apos;score&apos; => $score, &apos;ip&apos; => request()->ip()]);
    abort(403);
}</code></pre>
<h2>その他のトラブル</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#fff3e0"><th>症状</th><th>原因</th><th>対処</th></tr></thead>
<tbody>
<tr><td>reCAPTCHA が表示されない</td><td>サイトキー間違い、CSP がドメインブロック</td><td>キー確認 / <code>Content-Security-Policy</code> に google.com 追加</td></tr>
<tr><td>localhost で動かない</td><td>許可ドメイン未登録</td><td>admin で <code>localhost</code> を追加 or テストキー使用</td></tr>
<tr><td>毎回画像チャレンジが出る</td><td>IP / ブラウザがスコア低</td><td>v3 移行 / Enterprise 検討</td></tr>
<tr><td>iframe 内で動かない</td><td>X-Frame-Options ブロック</td><td>埋め込み元の許可設定</td></tr>
</tbody>
</table>

<h2>FAQ</h2>

<p><strong>Q: v2 と v3 を同じページで併用できる?</strong><br />
A: 技術的には可能ですが、JS の競合が起きやすいので非推奨。サイト全体を v3 に統一が無難です。</p>

<p><strong>Q: ローカル開発でテストするには?</strong><br />
A: Google 公式の<strong>テスト用キー</strong>(<code>6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI</code> など)を使うと常に成功します。本番リリース時は必ず本物のキーに差し替え。</p>

<p><strong>Q: 検証 API へのリクエストがタイムアウトする</strong><br />
A: 本番サーバから <code>https://www.google.com</code> へ OUT 通信が許可されているか確認。プロキシ越しの場合は <code>HTTPS_PROXY</code> 設定。</p>