本文へ移動
技術を、自社の仕事に。
判断と実行を助けるメディア

記事を検索

reCAPTCHAの評価にトークン発行時のIPとUAが加わった

目次 · 5項目

お問い合わせフォームにreCAPTCHAを入れたのに、機械的な送信が届き続ける。スコアを見ると高く、正規の利用者と区別できない。こうしたとき、サーバー側で確かめられる材料は多くありません。トークンが有効か、どのページで作られたか、スコアはいくつか、が中心です。

reCAPTCHA EnterpriseのAPI(projects.assessments.create)の評価結果に、トークンを作ったときの利用者のIPアドレスとUser-Agentを返す項目 tokenProperties.clientProperties が加わりました。フォームを送ってきた通信の値と、トークンを作った時点の値を比べられるようになります。本記事では、2026年10月18日にreCAPTCHA Enterprise APIのDiscovery文書(revision 20261011)とGoogleのクライアントライブラリを、10月19日に公式のAPIリファレンスとリリースノートを直接開いて確認した内容から、フォームの判定への組み込み方を整理します。資料調査と編集部の提案で、認証情報がないためAPIの呼び出しは行っていません。

加わった項目

APIリファレンスとDiscovery文書の TokenProperties に clientProperties が加わり、説明は「Output only. Information collected by the reCAPTCHA Enterprise client-side integration when the token is generated.」です。中身は2つです。

  • userAgent:「The User-Agent header string observed by reCAPTCHA during token generation.」。1000文字を超える分は切り詰められます
  • userIpAddress:「The user’s IP address at token generation.」。IPv4かIPv6で、IPv6はRFC 5952の正規の書き方、IPv4をIPv6の形で表したアドレスはIPv4に直して返ります

どちらも出力専用で、サーバーから送る値ではありません。一方、評価を頼むときにサーバーから送れる Event には、もともと userIpAddress(「The IP address in the request from the user’s device related to this event.」)と userAgent がありました。こちらはフォームを受け取ったサーバーが見た値です。

つまり今回の変更で、サーバーが見た値(送る側)と、トークンを作ったときにreCAPTCHAが見た値(返る側)が、1つの評価の中にそろいます。

reCAPTCHA Enterpriseの評価で比べられる2つの値を示す図。ブラウザでトークンを作った時点の値はtokenProperties.clientPropertiesのuserIpAddressとuserAgentとして評価結果に返る。フォームを受け取ったサーバーが見た値はEvent.userIpAddressとuserAgentとして評価の依頼に含めて送る。両者を比べて不一致を判定の材料にする

いつから、どこで使えるか

公式のAPIリファレンス(projects.assessments のページ、最終更新は2026年9月30日 UTC)には、TokenProperties の clientProperties と、その中の userIpAddress・userAgent が上と同じ説明で載っています。一方、reCAPTCHAのリリースノート(最終更新は2026年10月13日 UTC)には、この項目の告知がありません。そのため、いつ加わったかの公式の日付は分かりません。

手がかりになるのは、Googleが公開するPython用の google-api-python-client です。2.201.0(2026年9月30日公開、reCAPTCHAの定義はrevision 20260825)には clientProperties がなく、GitHubのmainブランチにある未公開の定義(revision 20261003)と、現在のDiscovery文書(revision 20261011)にはあります。8月末から10月初めのあいだに加わったと見られます。

注意したいのは、クライアントライブラリへの反映です。10月19日時点でも、Node.js用の @google-cloud/recaptcha-enterprise の最新版7.3.0(10月12日公開)の同梱ファイルにも、GitHubの googleapis/googleapis にある recaptchaenterprise.proto にも、clientProperties は見当たりませんでした。gRPCのライブラリで型として扱えるようになるまでは、REST APIの応答のJSONから読む前提で考えます。応答に実際にこの項目が入るか、どの鍵の種類(スコア型・チェックボックス型など)で入るかは、確認できていません。

送信時の値と比べる(編集部の提案)

次の例は、フォームを受け取ったサーバーで評価を頼み、返ってきた値と比べる流れです。Discovery文書の定義に沿って編集部が組んだもので、実際に送って応答を確かめたものではありません。

// フォームの送信を受けたサーバー側の処理(REST APIを直接呼ぶ例)
const res = await fetch(
  `https://recaptchaenterprise.googleapis.com/v1/projects/${projectId}/assessments`,
  {
    method: 'POST',
    headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      event: {
        token,                 // フォームから受け取ったトークン
        siteKey,
        expectedAction: 'contact_submit',
        userIpAddress: clientIp,   // サーバーが見た送信元のIP
        userAgent: request.headers.get('user-agent') ?? '',
      },
    }),
  },
);
const assessment = await res.json();
const issued = assessment.tokenProperties?.clientProperties;
// reCAPTCHAはIPv4射影アドレス(::ffff:192.0.2.1)をIPv4に直して返すため、こちらもそろえる
const normalizedIp = clientIp.replace(/^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/i, '$1');
const ipMismatch = issued?.userIpAddress && issued.userIpAddress !== normalizedIp;
const uaMismatch = issued?.userAgent && issued.userAgent !== (request.headers.get('user-agent') ?? '').slice(0, 1000);

不一致をどう扱うかが設計の中心です。編集部としては、不一致だけで送信を拒否しないことを勧めます。正規の利用者でも、値がずれる条件があるからです。

  • 回線の切り替え: スマートフォンでWi-Fiとモバイル回線を行き来すると、ページを開いた時とボタンを押した時でIPアドレスが変わることがあります
  • IPv4とIPv6の併用: 同じ端末でも、トークンを作る通信と送信の通信で使うアドレスの種類が違えば一致しません
  • アドレスの書き方の違い: IPv4とIPv6の両方で待ち受けるNode.jsのサーバーでは、IPv4の接続元が ::ffff:192.0.2.1 のような形で見えることがあります。reCAPTCHAが返す値はIPv4の形に直されているため、そのまま比べると同じ相手でも不一致になります。IPv6も書き方の揺れがあるので、比べる前にRFC 5952の形にそろえます
  • プロキシや中継: CDNやロードバランサーの後ろにあるサーバーでは、受け取った接続元のIPが中継の機器のものになります。X-Forwarded-For などから利用者のIPを取り出す処理が正しいかを先に確かめます
  • トークンの作り直し: 入力に時間がかかってトークンを作り直す実装では、どの時点のトークンかで値が変わります

拒否ではなく、スコアや tokenProperties.invalidReason、clientSignalsFailed と並べる材料の1つにし、「スコアが境界付近で、かつIPもUser-Agentも一致しない」ときだけ確認の手順(メールでの本人確認、受付の保留など)に回す、という使い方が無理のない線です。

記録するときの注意

IPアドレスとUser-Agentは、送信者を識別しうる情報です。比較の結果を残すときは、次の点を決めてから始めます。

  1. 何を残すか: 比較の結果(一致・不一致)だけを残し、値そのものは残さない、という選択肢があります。調査に値が必要なら、保存期間を決めます
  2. プライバシーポリシーの記載: フォームでreCAPTCHAを使うことと、送信時の情報を不正対策に使うことが、サイトのプライバシーポリシーに書かれているかを確かめます
  3. 誰が見られるか: 問い合わせ管理の画面に値を表示するなら、閲覧できる人を絞ります

フォームに届く営業メールそのものの扱いは、問い合わせフォームに営業メールが殺到する問題の記事で、reCAPTCHAからの移行の判断はGoogle Cloud Fraud Defenseの記事で扱っています。機械的な送信を止める対策は1つに頼らず、受付の設計と組み合わせて考えてください。

まずは、自社のフォームのサーバーが利用者のIPアドレスを正しく取り出せているかを確かめるところから始めてください。そこがずれていると、今回の項目と比べても不一致ばかりになり、判定の材料として使えません。

2026年10月19日に、公式のAPIリファレンス(projects.assessments、最終更新2026年9月30日 UTC)とリリースノート(最終更新2026年10月13日 UTC)を直接開き、項目の説明が本文と一致すること、リリースノートに告知がないことを確認しました。2026年10月18日に、reCAPTCHA Enterprise APIのDiscovery文書(recaptchaenterprise v1、revision 20261011)、google-api-python-client 2.200.0・2.201.0に同梱の定義とPyPIの公開日時、npmの @google-cloud/recaptcha-enterprise 7.2.1・7.3.0、GitHubの googleapis/googleapis の recaptchaenterprise.proto を直接取得して確認しました(資料調査)。コード例と比較の扱いは編集部の提案です。認証情報がないためAPIの呼び出しは行っておらず、実際の応答、項目が返る鍵の種類、値が一致しない頻度は未確認です。

お問い合わせフォームの不正送信対策や、フォームまわりのサーバー側の実装の見直しは、グリームハブの開発・Web制作のご相談で承っています。フォームの構成や届いている送信の内容によって打ち手が変わるため、お問い合わせからご相談ください。

参考資料

この記事を共有XFacebook
鈴木 翔

技術の可能性に魅了され、学生時代からプログラミングとデジタルアートの分野に深い関心を持つ

この記事のテーマを、自社の次の一歩へ

Webサイトで、実現したいことから。

使う人の目的、必要な機能、更新の体制を整理し、制作・改善で最初に取り組むことを考えます。

  • サイトの目的
  • 機能と使いやすさ
  • 公開後の運用
Web制作・改善を相談する

構想段階からご相談いただけます。この記事の情報を相談フォームに引き継ぎます。

最新記事をメールで受け取る・Web制作ガイドを読む
無料ダウンロード

Web制作 費用・発注・集客 完全ガイド【2026年版】

費用相場・制作会社の選び方・集客戦略をPDFにまとめました。

The PDF and newsletter emails are currently in Japanese.

メルマガにも登録されます。いつでも解除可能です。