Self-Host ALTCHA on Your Form in 30 Minutes
Step-by-step setup of the open-source proof-of-work CAPTCHA from scratch , widget, server library, and verification flow.
ALTCHA is the easiest self-hosted CAPTCHA in 2026 because there's almost nothing to host , the JavaScript widget runs in the visitor's browser, and the verification is a small library call in your server code. There's no central service, no database, no daemon. You can have it working on a contact form in under 30 minutes.
What you need
- A static or dynamic page that hosts your form
- A server-side language (Node, Go, Python, PHP, Ruby, Rust, Java, .NET all have ALTCHA libraries)
- About 30 minutes
That's it. No vendor account, no API key, no monthly cost.
Step 1: Add the widget to your form
Include the ALTCHA script (about 10 KB) and the widget element:
<script async defer src="https://cdn.jsdelivr.net/npm/altcha/dist/altcha.min.js" type="module"></script>
```The widget renders inline and adds a hidden input named "altcha" containing the proof when solved. On the visitor's browser this takes 300-800ms in the background; they see "Verifying" briefly and the button stays enabled.
Step 2: Add the challenge endpoint to your server
In Node:
import { createChallenge, verifySolution } from 'altcha-lib';const HMAC_KEY = process.env.ALTCHA_HMAC_KEY;
app.get('/altcha-challenge', async (req, res) => { const challenge = await createChallenge({ hmacKey: HMAC_KEY, maxNumber: 100000, expires: new Date(Date.now() + 600000) }); res.json(challenge); }); ```
The HMAC key is your secret , generate any random string and store it as an environment variable. Anyone who knows the key can generate fake challenges, so treat it like a database password.
Step 3: Verify the proof on form submission
app.post('/submit', async (req, res) => {
const proof = req.body.altcha;
const valid = await verifySolution(proof, HMAC_KEY);
if (!valid) {
return res.status(400).send('Bot detected');
}
// ... process the form
});
That's the entire integration. The verifySolution call returns true if the proof is valid, the HMAC matches, and the expiry hasn't passed. False otherwise.
What this actually defends against
ALTCHA stops every bot that doesn't run real browser JavaScript. That covers cURL scripts, simple HTTP libraries (Python requests, Node fetch), and bargain-basement spam tools. It also raises the cost for bots that do run real browsers (Playwright, Puppeteer) because they have to pay 500ms of CPU per form submission, which makes high-volume spam uneconomic.
ALTCHA does not stop a determined attacker who runs a real browser and is willing to pay the CPU cost on every submission. For that, you need additional layers (IP reputation, rate limiting, honeypots, behavioral checks). ALTCHA is a clean privacy-friendly first layer that handles roughly 95% of form spam at zero ongoing cost.
When to upgrade from ALTCHA
If you see persistent spam getting through after deploying ALTCHA, you're being targeted by a real attacker, not a bot crawler. Adding more CAPTCHA difficulty won't help , you need to change layer. The right next moves are: rate limits per IP (Cloudflare WAF free rule), email reputation scoring (Sendgrid Email Validation $0.005/check), and possibly switching to Friendly Captcha for the dashboard and abuse signals.
For most contact forms, comment forms, and signup forms, ALTCHA plus a honeypot plus a basic IP rate limit handles spam permanently with no vendor dependency. The 30-minute setup pays back in zero ongoing cost and zero data leaving your infrastructure.