AgentHouse HumanProof
Stop bots and spam on HTML forms—without cookies, fingerprinting, or third-party CAPTCHA widgets. One JavaScript file and a server-side verify call; the proof runs quietly in the background.
A modern alternative to CAPTCHAs
Classic CAPTCHAs slow people down, strain accessibility, and often pull in tracking-heavy third-party scripts. HumanProof uses a short-lived signed challenge and lightweight proof-of-work in the browser—no puzzles, images, or extra widgets.
- No fingerprinting and no cross-site tracking profile from a widget network.
- No Google or external CAPTCHA provider required on your page.
- Secrets stay on your server: the browser never holds the verify key.
How it works
From challenge to verified submission in four steps.
- The SDK requests a signed challenge for your public site key and form id.
- The browser solves a small proof-of-work (off the main thread when possible).
- The proof is attached as a hidden field on your normal form submit.
- Your server calls the verify API with the secret key and receives accept, quarantine, or fake-success guidance.
Built for privacy-first sites
A good fit for GDPR-conscious teams and EU-first hosting: small surface area, no ad-tech scripts on your form.
- No cookies required for the widget.
- Traffic stays between your origin and the AgentHouse API—no ad-network scripts.
- Verification-side logging is kept minimal and retention-aware.
- You decide how to act on each result—accept, quarantine, or fake-success—on your own backend.
One JavaScript file—nothing else
No npm, no bundler, no framework: load one script from the AgentHouse API, set data attributes on your forms, and you are done. One script can protect many forms on the same page. Optional “Powered by AgentHouse” line included by default.
Developer-friendly integration
Frontend: add one script. Backend: one JSON POST to verify. Works with any stack—Node.js, PHP, Python, or anything that can call HTTPS.
Script and API URLs on this page follow your configuration (production defaults to api.agenthouse.org; set humanproof.publicSdkBase in secrets.json to point at a dev API).
When the SDK must fetch a challenge and solve proof-of-work on submit, it dispatches the CustomEvent humanproof.securingForm on window (detail includes form, siteKey, and formId) so your app can show progress. On failure it dispatches humanproof-error on the form.
window.addEventListener('humanproof.securingForm', function (e) { /* e.detail.form, siteKey, formId */ });
You cannot solve proof-of-work before the server issues a challenge. Optional: set data-prefetch-challenge-delay-ms on the script (milliseconds after load) to fetch a challenge and solve in the background; submit then reuses the proof while it is still valid. Use data-prefetch-expiry-margin-ms to require that much remaining TTL before reuse (clock skew). Per-form overrides: data-humanproof-prefetch-challenge-delay-ms and data-humanproof-prefetch-expiry-margin-ms on the form.
<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>// POST https://api.agenthouse.org/humanproof/verify — JSON body (Node 18+ fetch)
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,
siteKey: payload.siteKey,
formId: payload.formId,
challengeId: payload.challengeId,
challenge: payload.challenge,
nonce: payload.nonce,
signature: payload.signature,
algorithm: payload.algorithm,
salt: payload.salt,
expiresAt: payload.expiresAt,
difficulty: payload.difficulty,
boundHost: payload.boundHost,
boundAction: payload.boundAction,
submitDurationMs: payload.submitDurationMs
};
const res = await fetch(verifyUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
const result = await res.json();
// result.status: 'ok' | 'suspicious' | 'reject'
// result.suggestedAction: 'accept' | 'quarantine' | 'fake-success' | 'reject'<?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);
$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);
?>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}
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:
return json.load(resp)Branding
HumanProof shows a small “Powered by AgentHouse” line by default. Remove it with a simple monthly subscription—same product, same privacy guarantees.
- Small “Powered by” line included on the free tier.
- Paid plan hides the line; behaviour and verification stay identical.
- Contact us when you are ready to license.
Why teams choose HumanProof
Practical wins for product and compliance teams alike.
- Fewer interruptions than image or puzzle CAPTCHAs—nothing new for users to click.
- Better accessibility: no visual challenge step, works with keyboard-driven flows.
- Strong privacy posture: no third-party CAPTCHA or ad widget on your form.
- Fast to ship: one script, one verify API, examples for common backends.
- Policy you control: per-form difficulty and how to treat suspicious submits.
Try it live
Submit the form below: proof-of-work runs in the background, then the demo posts to our server (nothing is stored).
Start protecting your forms
Configure your site key and per-form rules in AgentHouse, add the script, and verify every submission on your backend. That is the whole integration—we are here if you want help rolling out.