Every developer knows the drill. You add a form to your site, bots find it within hours, and suddenly you're dealing with spam submissions. The traditional answer? CAPTCHA.
But CAPTCHAs come with serious trade-offs:
- Conversion killer: Studies show CAPTCHAs reduce form completions by 12–40%
- Accessibility nightmare: Visual puzzles are fundamentally inaccessible to screen reader users
- Privacy concerns: reCAPTCHA sets cookies and sends data to Google's US servers
- User frustration: Nobody enjoys clicking traffic lights
How Proof-of-Work Changes the Game
Proof-of-Work (PoW) flips the model. Instead of asking humans to prove they're human, it asks browsers to solve a small math problem — a SHA-256 hash challenge.
For humans: Completely invisible. The challenge solves in ~200ms in a background WebWorker. Users never see or interact with anything.
For bots: Computationally expensive at scale. A bot trying to submit 10,000 forms needs 10,000 unique PoW solutions. The economics don't work.
The Technical Implementation
Here's how PoW works for form protection (using the ALTCHA wire format):
- Browser requests a challenge from the server
- Challenge includes a SHA-256 hash target and a maximum number to search
- WebWorker iterates through numbers, hashing each with the challenge salt
- When a matching hash is found, the solution is attached to the form submission
- Server verifies the solution with a single-use nonce (no replay attacks)
The entire process happens in the background. No UI, no interaction, no cookies.
Composite Scoring: Beyond Just PoW
PoW alone isn't enough. A serious implementation should combine multiple signals into a composite score:
- PoW verification: Did the browser solve a valid challenge?
- Timing analysis: Was the form submitted suspiciously fast?
- Honeypot detection: Did a bot fill a hidden field?
- AI spam scoring: Does the content look like spam?
Each signal contributes to a final pass/soft-block/reject decision. No single signal is a deal-breaker — and no single bypass breaks the whole system.
What About No-JavaScript Users?
Progressive enhancement matters. If a user has JavaScript disabled:
- The form still submits normally
- The server flags it as "no-shield" (suspicious but not blocked)
- Server-side heuristics (timing, honeypot, AI) still apply
- Increased rate limiting provides additional protection
No user is locked out. The protection degrades gracefully.
The GDPR Angle
Unlike reCAPTCHA (which sets NID and _GRECAPTCHA cookies and sends data to the US), a PoW-based approach:
- Sets zero cookies
- Performs no browser fingerprinting
- Stores no personal data
- Can run entirely on EU infrastructure
No cookie consent banner needed. No GDPR risk assessment required. The architecture itself is the compliance strategy.
Try It
I built this approach into nForms — a form backend that combines PoW bot protection with WCAG 2.2 AA form validation in a single script tag:
<script src="https://api.nforms.eu/shield.js"></script>
<form data-nforms-key="YOUR_KEY">
<input name="email" data-validate="required|email" />
<button type="submit">Send</button>
</form>
Free plan includes Shield Basic (honeypot + timing). The Developer plan (€9/mo for early users) adds full PoW protection.
The contact form on nforms.eu is a live demo — Shield is active on it.
The bottom line: CAPTCHAs were a necessary evil. Proof-of-Work makes them unnecessary. Your forms get protected, your users get a better experience, and your compliance team gets peace of mind.
The future of form protection is invisible.
Top comments (2)
Solid writeup. The composite scoring approach is the right call -- PoW alone stops dumb bots, but timing + honeypot + AI scoring is where you actually catch the sophisticated ones.
I've been building something similar and landed on a slightly different tradeoff. Instead of SHA-256, I went with Argon2d for the hash function. It's memory-hard, which means GPUs and ASICs can't parallelize the solving the way they can with SHA-256. The cost per challenge stays roughly equal between a phone and a server farm, which matters when you're thinking about bot operators throwing hardware at it.
The other thing I added was adaptive difficulty -- the server adjusts the challenge based on traffic patterns. During a credential stuffing spike, difficulty goes up automatically. Normal traffic barely notices.
Wrote up the full implementation here if you want to compare approaches: dev.to/zekebuilds/how-i-stopped-fo...
The npm package is
@powforge/captcha-- zero deps, 14kb, runs everything in a WebWorker like you described. Would be curious what you think about the Argon2d tradeoff vs pure SHA-256.The Argon2d choice makes sense, especially since SHA-256 lets you throw rented GPU time at it for pretty cheap. But honestly, the hash function debate matters less than the adaptive difficulty piece you built. The real threat model isn't a script kiddie with a single VPS — it's browser-farm services where real Chrome instances solve your challenges inside real browser contexts. PoW can't distinguish a paid human's browser from a free visitor's browser. That's where the composite scoring (timing + honeypot + content analysis) earns its keep, because the challenge itself becomes just one signal among many rather than the entire defense.