WordPress, as a plugin
Contact Form 7, comments, WooCommerce login, registration, lost-password and checkout. wp-login.php and XML-RPC too, off by default. The secret lives in options and never reaches the browser.
L7 · Gate — a Torjua product
Torjua Verify is a drop-in replacement for reCAPTCHA that runs on your own hardware. The same script tag, the same server-side verify call — except no request leaves your infrastructure, and nobody is ever asked to identify a bus.
<script src="https://verify.torjua.com/v1/widget.js" async defer></script> <form action="/contact" method="post"> <input name="email" type="email"> <textarea name="message"></textarea> <div class="torjua-verify" data-sitekey="pk_live_…"></div> <button type="submit">Send</button></form> Over the wire
4.5 KB, one file
Third-party calls
None
Image puzzles
None, ever
Verify contract
reCAPTCHA-shaped
How it runs
Most people should never know the check happened. The deterrent is not difficulty — it is cost, charged per request, to whoever is sending them.
One script, one request, no cookies. It fetches a single-use nonce bound to the requesting address and to the origin the page is actually served from.
A SHA-256 proof of work runs in a Web Worker, so the page never blocks. A visitor waits a fraction of a second. Anyone minting a million submissions pays that cost a million times.
Time from render to answer, whether any pointer or key event happened at all, headless markers such as navigator.webdriver, and the reputation of the hashed address. Four rules you can read in the source, not a model you cannot.
The widget writes a signed ES256 token into a hidden field. Your server posts it to /v1/siteverify with the site secret and gets back success, score and hostname. The token is consumed on first use.
A visitor who scores badly is not turned away on the first attempt. They get one more, behind an explicit gesture and a harder proof of work — and a site can be configured to refuse a token outright below a threshold you set.
Replacing reCAPTCHA
Verify was built to be swapped in, not migrated to. The verify endpoint takes the same fields and answers with the same JSON, so most integrations change a URL and a key pair. What changes underneath is who is standing in front of your visitors.
Where the check runs
reCAPTCHA
Google's servers. Every visitor to a protected page becomes a request to a third party.
Torjua Verify
A container next to your own application, on hardware you rent or own.
What a visitor does
reCAPTCHA
Usually nothing — until it escalates and asks them to find the bicycles.
Torjua Verify
Usually nothing. When it escalates: one deliberate click and a harder proof of work. There is no image grid to fall back to, because we did not build one.
Personal data
reCAPTCHA
Visitor IP and interaction data are processed by a US provider — a transfer you have to account for in your records.
Torjua Verify
Addresses are HMAC-hashed with a key only you hold. Raw IPs are never written down, and audit rows are purged after 30 days.
What the page loads
reCAPTCHA
Several files from a third-party domain, on every protected page.
Torjua Verify
17 KB of JavaScript from your own host — about 4.5 KB compressed — served immutable at a content-hashed URL.
Server-side check
reCAPTCHA
POST your secret and the token, receive JSON.
Torjua Verify
The same POST with the same field names, and the same JSON back. Existing plugins and libraries usually need one URL changed.
Token reuse
reCAPTCHA
Tokens expire.
Torjua Verify
Tokens expire and are consumed exactly once. A replayed token is rejected and logged against the hashed address that sent it.
The deterrent
reCAPTCHA
A score from a model you cannot inspect or tune.
Torjua Verify
A per-request cost that climbs for addresses behaving badly, and drops again when they behave. Every threshold is yours to set per site.
When it is unreachable
reCAPTCHA
The form goes down with it, unless you wrote a fallback yourself.
Torjua Verify
Fail-open or fail-closed, chosen per integration. The edge always fails open.
The server half
One POST, form-encoded, with your site secret and the token the widget produced. The response carries success, a score, the hostname the token was earned on, and an error-code array — the shape every existing library already expects.
Pass remoteip and a replayed token is attributed to the address that sent it, not just refused.
POST https://verify.torjua.com/v1/siteverifyContent-Type: application/x-www-form-urlencoded secret=sk_live_…&response=<token>&remoteip=203.0.113.7 200 OK{ "success": true, "score": 0.9, "challenge_ts": "2026-08-20T09:14:02Z", "hostname": "protocache.com", "error-codes": []} Where it plugs in
Contact Form 7, comments, WooCommerce login, registration, lost-password and checkout. wp-login.php and XML-RPC too, off by default. The secret lives in options and never reaches the browser.
Any language that can post a form body. Registration and login endpoints call siteverify before they touch credentials, and can step up rather than reject when a score comes back low.
Varnish sends suspicious traffic to a gate page instead of your origin. Clearing it sets a signed first-party cookie that the edge checks with a local HMAC — no API call, no latency for cleared visitors.
Running it
Verify is a single Rust binary with Postgres for the durable state and Redis for everything that expires in minutes. It makes no outbound calls. Whatever it knows about your visitors is on a machine you can walk up to — which is a stronger statement than any processing agreement.
Raw addresses are never persisted; only an HMAC of them, keyed with a secret that stays on your side. There are no cookies on the form path at all, and the one the edge gate sets carries a signature and an expiry, nothing else.
| Runtime | One Rust binary · Postgres · Redis |
|---|---|
| Deployment | Docker Compose, single region |
| Tenancy | A sitekey and secret per site |
| Secrets | argon2id hashed, shown once |
| Token signing | ES256, rotated by key id |
| Data location | Wherever you run the container |
Tell us which forms you are protecting and what you are running them on. We will send back a sitekey pair, the WordPress plugin, and the compose file — or stand the whole thing up inside your own network if you would rather not operate it.