Documentation

How HumanProof works

A high-level view of the widget, platform proxy, challenge engine, risk signals, usage accounting, and server verification flow.

Platform overview

A managed trust layer between the browser and your backend.

HumanProof keeps the challenge backend behind the platform, maps public site keys to internal challenge keys, applies domain and plan checks, enriches challenge starts with risk signals, and gives your server one simple verification endpoint.

Browser

Loads widget.js and sends challenge requests with widget context.

Platform

Checks project, domain, plan, billing, and risk rules before proxying.

Challenge engine

Issues and redeems proof-of-work challenges through internal project keys.

Telemetry

Records protected attempts, outcomes, risk reasons, and usage history.

Your backend

Verifies humanproof-token with the backend secret before accepting the action.

Challenge engine

The browser never talks directly to the private challenge backend. It calls the HumanProof project endpoint with the public site key. HumanProof translates that into the internal challenge key, forwards the request, and returns only the challenge payload or redemption result needed by the widget.

Challenge startThe widget asks for a challenge. HumanProof checks project state, origin, plan capabilities, limits, billing, and risk mode first.
Challenge redeemThe widget submits the proof result. Successful and failed redeem attempts are tracked as protected attempts.
SiteverifyYour backend verifies the token after the form submit. This confirms the browser-side challenge result without exposing internal challenge secrets.

Risk signals

The HumanProof widget sends lightweight interaction signals with challenge starts, such as trigger type, widget variant, elapsed time, focus and blur counts, keyboard activity, pointer activity, and page visibility. These signals help identify suspicious automation without replacing server-side verification.

Observe mode

Signals are recorded and shown in usage/risk views, but HumanProof still forwards eligible challenges.

Enforce mode

Requests that exceed the project preset threshold can be blocked before the challenge engine is called.

Presets

Balanced, strict, and custom project settings control challenge difficulty and risk blocking thresholds.

Protection presets

Protection presets combine challenge-engine settings with HumanProof risk scoring thresholds. They let you tune friction and enforcement without editing code for every form.

PresetChallenge profileRisk thresholdBest for
RelaxedDifficulty 3, 60 challenges, lighter obfuscation, higher rate limit.Blocks at 8.0 / 10 when enforce mode is enabled.Low-risk forms, internal flows, or trusted traffic.
BalancedDifficulty 4, 80 challenges, default obfuscation, standard rate limit.Blocks at 6.0 / 10 when enforce mode is enabled.Most public contact, signup, and lead forms.
StrictDifficulty 5, 120 challenges, stronger obfuscation, lower rate limit.Blocks at 4.0 / 10 when enforce mode is enabled.Login, registration, checkout, and abused endpoints.
Observe mode

The preset still tunes the challenge engine. Risk scores are recorded but not used to block requests.

Enforce mode

The same preset also defines the risk score where HumanProof can block before the challenge engine is called.

Domain and plan gates

Before a challenge is issued, HumanProof verifies that the request origin matches a configured production or testing domain, the project is active, billing allows traffic, monthly usage is available, and the requested widget variant or branding is allowed by the organization plan.

Usage accounting

A protected attempt is counted when the challenge flow produces value: a solved challenge, a failed redeem, or an enforced risk block. Backend siteverify calls do not double-count the same browser solve; they are tracked separately as verification analytics.

Security boundary

The browser is responsible for rendering the widget and obtaining a token. Your backend is responsible for deciding whether the protected action continues. Never trust a client-side widget state alone; always verify the submitted token with your backend secret.