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 (1)
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.