| この記事の要点 |
|
エラー内容
reCAPTCHA のサーバ側検証で以下のレスポンスが返る:
array(2) {
["success"] => bool(false)
["error-codes"] => array(1) {
[0] => string(22) "invalid-input-response"
}
}
または JSON で:
{
"success": false,
"error-codes": ["invalid-input-response"]
}
原因
https://www.google.com/recaptcha/api/siteverify に POST した response パラメータ(フロントエンドの reCAPTCHA トークン)が不正と判定されています。具体的には:
- トークンが空: フロント側でユーザがチャレンジ未完了
- トークンの期限切れ: reCAPTCHA トークンは生成後 2 分間のみ有効
- トークン使い回し: 同じトークンを 2 回以上使うと無効
- トークンが改ざん: フォーム送信前に JS で書き換えられた等
- siteverify への送信形式が違う: GET / 引数間違い
対処1: フロント側の確認
HTML フォームに reCAPTCHA ウィジェットを正しく設置:
<!DOCTYPE html>
<html>
<head>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
</head>
<body>
<form method="POST" action="/submit">
<input type="text" name="email">
<!-- v2 チェックボックス -->
<div class="g-recaptcha" data-sitekey="YOUR_SITE_KEY"></div>
<button type="submit">送信</button>
</form>
</body>
</html>
送信時に g-recaptcha-response という name の hidden input が自動生成されます。サーバ側ではこれを $_POST['g-recaptcha-response'] で受け取ります。
対処2: サーバ側で siteverify を正しく呼ぶ
PHP
function verifyRecaptcha($token, $secretKey) {
$url = 'https://www.google.com/recaptcha/api/siteverify';
$params = [
'secret' => $secretKey,
'response' => $token,
'remoteip' => $_SERVER['REMOTE_ADDR'], // 任意
];
$options = [
'http' => [
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => http_build_query($params),
],
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
$result = json_decode($response, true);
if (!$result['success']) {
// エラーコード配列を返す
return ['ok' => false, 'errors' => $result['error-codes'] ?? []];
}
// v3 ならスコアもチェック
if (isset($result['score']) && $result['score'] < 0.5) {
return ['ok' => false, 'errors' => ['low-score'], 'score' => $result['score']];
}
return ['ok' => true, 'result' => $result];
}
// 使い方
$token = $_POST['g-recaptcha-response'] ?? '';
if (empty($token)) {
die('reCAPTCHA を完了してください');
}
$result = verifyRecaptcha($token, getenv('RECAPTCHA_SECRET'));
if (!$result['ok']) {
error_log('reCAPTCHA failed: ' . json_encode($result['errors']));
die('検証に失敗しました');
}
// 検証 OK → フォーム処理続行
Laravel
// Laravel 標準の Validator にカスタムルール
// または anhskohbo/no-captcha パッケージ
// composer require anhskohbo/no-captcha
// config/services.php
'recaptcha' => [
'key' => env('RECAPTCHA_SITE_KEY'),
'secret' => env('RECAPTCHA_SECRET_KEY'),
],
// Controller
public function submit(Request $request) {
$request->validate([
'g-recaptcha-response' => 'required|captcha',
'email' => 'required|email',
]);
// ... 処理
}
対処3: reCAPTCHA v3 のスコアも検証
v3 はチャレンジなしでバックグラウンド判定。score(0.0〜1.0)でボット判定:
// フロント (v3)
grecaptcha.ready(function () {
grecaptcha.execute('YOUR_SITE_KEY', {action: 'submit'})
.then(function (token) {
document.getElementById('recaptcha-token').value = token;
document.getElementById('myForm').submit();
});
});// サーバ側 (v3) は v2 と同じ siteverify を叩く
$result = verifyRecaptcha($token, $secret);
// v3 だけ追加で score を見る
if ($result['ok'] && $result['result']['score'] < 0.5) {
// 怪しい
error_log('Low score: ' . $result['result']['score']);
}
// 'action' も一致確認
if ($result['result']['action'] !== 'submit') {
error_log('Unexpected action');
}
エラーコード一覧
| error-code | 意味 | 対処 |
|---|---|---|
| missing-input-secret | secret パラメータ未送信 | secret を必ず渡す |
| invalid-input-secret | secret が間違っている | Google Console で正しい secret を確認 |
| missing-input-response | response パラメータ未送信 | g-recaptcha-response を必ず渡す |
| invalid-input-response | response が無効(空・期限切れ・改ざん) | 本記事 |
| bad-request | リクエスト形式が不正 | POST / URL エンコード形式を確認 |
| timeout-or-duplicate | トークン期限切れ or 使い回し | 毎回新規トークン取得 |
SPA / Ajax での注意
- トークンを保存して再利用しない — 必ず送信直前に
grecaptcha.executeで新規生成 - 2 分のタイマー: フォーム入力中に時間が経つとトークン期限切れ → 送信直前に再取得
- action 名は固定的に — サーバ側の検証と一致させる
- Ajax 送信時のヘッダ — CSRF と reCAPTCHA は別物。両方必要
セキュリティ補足
- secret key は絶対にフロントに置かない — サーバ側のみで保持
- siteverify は HTTPS で — secret が漏洩しないよう
- レート制限: スコアが低いリクエストの連発は IP ブロック等で対応
- v3 のスコア閾値: 0.5 が一般的だが、サイトの実情で調整
子ページ
子ページはありません
同階層のページ
- invalid-input-response
- ERROR for site owner: Invalid site key
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスのソフト一覧|Blender・Metasequoiaと用途別の選び方
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Visual Studio「デザイナーを表示できません」エラーの原因と対処 2026-10-28 12:06:00
- SSH 認証に失敗しました。再試行してください の対処 2026-10-28 12:06:00
- SSH2 秘密鍵の読み込みに失敗しました の原因と対処 2026-10-28 12:06:00
- TeraTerm のよくあるエラーと対処法完全ガイド — Connection refused / 2026-10-28 12:06:00
- Visual Studio エラー一覧|コンパイルエラー・警告の確認方法と対処 2026-10-28 11:39:57
- Whitelabel Error Page の原因と消し方|Spring Boot のエラーページ 2026-10-28 11:39:57
- Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法 2026-10-28 11:39:57
- SQL WHERE 句完全ガイド 2026-10-28 11:39:57
- SQL JOIN 完全ガイド (INNER/LEFT/RIGHT/FULL OUTER) 2026-10-28 11:39:57
- tomcat の起動 / 停止ログと catalina.log・catalina.out の違い 2026-10-28 10:24:23
- Tomcat の起動確認方法 5 つ|localhost:8080・ポート・プロセス・ログ 2026-10-28 10:24:23
- Oracle 19c COMMITの使い方: 暗黙コミット・自動確定・応答不明時の確認 2026-10-28 09:59:09
- Oracle 19c DELETE文|削除対象の確認・COMMIT前の判断・ROLLBACKの条件 2026-10-28 09:59:09
- Oracle 19c INSERT文|INSERT ALL・SELECT・RETURNINGとMERGEの使い分け 2026-10-28 09:59:09
- Oracle 19cのトランザクション制御|COMMIT・ROLLBACK・分離レベルと接続設定 2026-10-28 09:59:09