Human verification without tracking

# 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.

No cookies

Single-file script

Backend-verified

## 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.

HTML HTML multi-form Node.js PHP Python 

```
<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).

Name 

Email 

Company 

Message 

Submit form 

### Demo result

OK 

## 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.

[Get started](/en/consulting/#cta)