Proof of work
Every verification asks the visitor's browser to solve a small computational puzzle before Caputchin issues a token. That puzzle is the proof of work.
How it works
Caputchin hands the browser a challenge and asks it to find a number (a nonce) that, when hashed together with the challenge, produces a hash beginning with a required count of leading zeros. There is no shortcut: the browser has to try nonce after nonce until one happens to work. Finding a valid nonce takes many attempts; checking one is a single hash. So the work is hard to do but cheap to verify, and Caputchin confirms the answer clears the required difficulty.
Content-Security-Policy
The solver runs in a Web Worker, which the widget creates from a blob: URL, so the embedding page's Content-Security-Policy must allow blob: for workers (worker-src blob:, or child-src / default-src as the fallback chain). This part is required: there is no main-thread fallback, so a policy that blocks the worker blocks verification. Separately, the solver compiles a WebAssembly routine for speed, which needs 'wasm-unsafe-eval' in script-src. That part is optional: without it the same solver runs slower in pure JavaScript inside the Worker. See game sandboxing for the complete host-page policy.
Why it deters abuse
The point is not to make any single solve impossible. It is to make abuse at scale uneconomic.
A real visitor solves one puzzle in a fraction of a second and never notices. A bot that wants to fire thousands of requests pays that compute cost thousands of times over. If clearing the challenge costs more than the spam is worth, the attack stops making financial sense. Proof of work shifts the goal from "unbreakable" to "not worth it."
The knobs
Two settings on a key's Security page tune the cost:
- Difficulty sets how many leading zeros the hash must have, which raises the cost of each solve.
- Challenges per request multiplies that cost by asking for several solves at once.
An honest limit
No challenge is unbreakable; given enough money, anything can be solved. Proof of work accepts that and competes on cost instead. It also only proves that effort was spent, not that a real browser spent it, which is why Caputchin pairs it with instrumentation to check the environment too.