AgentHouse HumanProof
HTMLフォームのボット・スパム対策に。Cookie・フィンガープリント・第三者CAPTCHAウィジェットは不要。1つのJavaScriptとサーバー側検証。証明はバックグラウンドで静かに実行されます。
CAPTCHAの現代的な代替
従来のCAPTCHAは手間とアクセシビリティ負荷が大きく、追跡的な第三者スクリプトを引き込みがちです。HumanProofは短命の署名付きチャレンジと軽量PoWをブラウザで行います。パズル・画像・余計なウィジェットはありません。
- ウィジェット網によるフィンガープリントやクロスサイト追跡プロファイルはありません。
- ページにGoogleや外部CAPTCHAプロバイダは不要です。
- 秘密はサーバー側に。ブラウザが検証用キーを持つことはありません。
仕組み
チャレンジから検証済み送信まで4ステップ。
- SDKが公開サイトキーとフォームIDで署名付きチャレンジを要求します。
- ブラウザが小さなPoWを解きます(可能ならメインスレッド外)。
- 通常の送信時に隠しフィールドとして証明を付与します。
- サーバーが秘密鍵で検証APIを呼び、accept / quarantine / fake-successの指針を受け取ります。
プライバシー優先サイト向け
GDPR意識の高いチームやEU優先ホスティング向け。攻撃面が小さく、フォームに広告系スクリプトはありません。
- ウィジェットにCookieは不要。
- 通信は自サイトのオリジンとAgentHouse APIの間だけ。広告ネットワークのスクリプトはありません。
- 検証側のログは最小限かつ保持方針に配慮。
- 各結果の扱い(受理・隔離・fake-success)は自前のバックエンドで決められます。
JavaScriptは1ファイルだけ
npm・バンドラ・フレームワーク不要。AgentHouse APIのスクリプトを1つ読み込み、フォームにdata属性を付けるだけ。1本のスクリプトで同一ページの複数フォームを保護できます。任意の「Powered by AgentHouse」表記はデフォルトで含まれます。
開発者に優しい統合
フロントはスクリプト1つ。バックエンドは検証用のJSON POST 1回。Node.js、PHP、Python、HTTPSを呼べる環境なら何でも対応。
バックエンド: 同じJSON本文を POST …/humanproof/verify へ。応答には status、suggestedAction、reasonCode、accept(ブール — 検証済みの送信として扱う場合のみ true)などが含まれます。必ずサーバーからのみ。secretKey はブラウザへ送らないでください。
フォーム設定によっては verify の JSON に hostname が必要です(クライアントの boundHost と一致すること — チャレンジ取得時に使ったホスト)。requireVerifyHostname 有効時に hostname が無いと reasonCode が HOSTNAME_REQUIRED になります。127.0.0.1 と localhost は別名です。hostnames に両方を入れるか、サイトURLと data-challenge-hostname を verify 本文と揃えてください。
スクリプト/APIのURLは設定に従います(本番はapi.agenthouse.org、開発はsecretsのpublicSdkBase)。
送信時にチャレンジ取得とPoWが必要な場合、SDKは window で CustomEvent の humanproof.securingForm を発火します(detail に form、siteKey、formId)。進捗表示に利用できます。失敗時はフォームで humanproof-error。
window.addEventListener('humanproof.securingForm', function (e) { /* e.detail.form, siteKey, formId */ });
PoWはサーバーのチャレンジ取得後にのみ可能です。任意で、scriptにdata-prefetch-challenge-delay-ms(読み込み後のミリ秒)を指定するとバックグラウンドで取得・計算し、送信時にまだ有効なら再利用します。data-prefetch-expiry-margin-msは再利用前に必要な残りTTL(時刻ずれ対策)です。フォーム単位はdata-humanproof-prefetch-challenge-delay-msとdata-humanproof-prefetch-expiry-margin-ms。
<form id="contact-form" data-humanproof="YOUR_FORM_ID">
<label>Email <input type="email" name="email" required></label>
<button type="submit">Send</button>
</form>
<script
src="https://api.agenthouse.org/humanproof/humanproof.js"
data-site-key="YOUR_PUBLIC_SITE_KEY"
data-powered-by="true"
data-endpoint="https://api.agenthouse.org/humanproof"
data-prefetch-challenge-delay-ms="2500"
data-prefetch-expiry-margin-ms="15000"
></script><form id="a" data-humanproof="form-a">...</form>
<form id="b" data-humanproof="form-b">...</form>
<script
src="https://api.agenthouse.org/humanproof/humanproof.js"
data-site-key="YOUR_PUBLIC_SITE_KEY"
data-powered-by="true"
data-endpoint="https://api.agenthouse.org/humanproof"
data-prefetch-challenge-delay-ms="2500"
data-prefetch-expiry-margin-ms="15000"
></script>const verifyUrl = 'https://api.agenthouse.org/humanproof/verify';
const secretKey = ''; // set from your secrets store before use
const payload = JSON.parse(formFields.humanproof);
const body = { secretKey, ...payload };
if (typeof body.hostname !== 'string' || !body.hostname.trim()) {
if (typeof body.boundHost === 'string' && body.boundHost.trim()) {
body.hostname = body.boundHost.trim();
}
}
const result = await (await fetch(verifyUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
})).json();
if (!result.accept) return; // do not process as a verified submit<?php
$url = 'https://api.agenthouse.org/humanproof/verify';
$secret = ''; // set from your server secret store before use
$payload = json_decode($_POST['humanproof'], true);
$body = array_merge(['secretKey' => $secret], $payload);
if (empty($body['hostname']) && !empty($body['boundHost'])) {
$body['hostname'] = $body['boundHost'];
}
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode($body),
CURLOPT_RETURNTRANSFER => true,
]);
$out = curl_exec($ch);
$result = json_decode($out, true);
// if (empty($result['accept'])) { return; }
?>import json
import urllib.request
VERIFY_URL = "https://api.agenthouse.org/humanproof/verify"
def verify_humanproof(secret_key: str, payload: dict) -> dict:
body = {"secretKey": secret_key, **payload}
if not (isinstance(body.get("hostname"), str) and body["hostname"].strip()):
bh = body.get("boundHost")
if isinstance(bh, str) and bh.strip():
body["hostname"] = bh.strip()
req = urllib.request.Request(
VERIFY_URL,
data=json.dumps(body).encode("utf-8"),
headers={"Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(req, timeout=30) as resp:
r = json.load(resp)
# if not r.get("accept"): return
return rブランディング
HumanProofは既定で短い「Powered by AgentHouse」表記を表示します。シンプルな月額で非表示にできます。製品とプライバシー上の保証は同じです。
- 無料枠では短い「Powered by」表記が含まれます。
- 有料プランで表記を非表示に。挙動と検証は同じです。
- ライセンスのご相談はお問い合わせください。
チームがHumanProofを選ぶ理由
プロダクトとコンプライアンスの両方に効くメリット。
- 画像やパズル型CAPTCHAより割り込みが少なく、新たにクリックさせるステップはありません。
- アクセシビリティに配慮。視覚的なチャレンジ画面はなく、キーボード操作の流れと相性が良いです。
- プライバシー面が明確。フォーム上に第三者CAPTCHAや広告ウィジェットはありません。
- 導入が速い。スクリプト1本、検証API1つ、主要バックエンド向けの例付き。
- 方針はあなた次第。フォームごとの難易度と、疑わしい送信の扱いを決められます。
ライブで試す
下のフォームを送信すると、バックグラウンドでPoWが走り、デモがサーバーへPOSTします(保存はしません)。