Quick answer
A proof-of-work challenge asks a client to perform a small computation and return the answer before it is allowed through. A real browser does this automatically in a fraction of a second with nothing to click, while a simple script cannot do it at all because it has no JavaScript engine. The point is not that the work is hard — it is that it must be repeated for every request, which is negligible for one visitor and ruinous for an attacker sending millions.
How it works
The server returns a small page instead of the content, containing a puzzle: typically, find a value that when hashed with a given seed produces a hash starting with a certain number of zeros. There is no shortcut — the only method is to try values until one fits.
The browser runs that loop, submits the answer, and receives a token stored in a cookie. Subsequent requests present the token and skip the challenge entirely, so the cost is paid once per session rather than per page.
seed = 'a91f...' // issued by the server
difficulty = 11 // required leading zero bits
let n = 0;
while (!hash(seed + n).startsWith(zeros(difficulty))) n++;
// submit n — the server verifies it in a single hashWhy it changes the economics
The asymmetry is the whole design. Solving costs a browser a few hundred milliseconds once. Verifying costs the server a single hash. But an attacker who wanted to send a million requests must now solve a million puzzles, which means running a real JavaScript engine a million times.
That turns a cheap attack into an expensive one. Flood tooling is built to send requests as fast as possible with minimal per-request cost; requiring a browser engine per request removes exactly the advantage the attacker was relying on.
| Real visitor | Flood tooling | |
|---|---|---|
| Challenges to solve | One per session | One per request |
| Needs a JS engine | Already has one | Must run one, per request |
| Practical cost | Well under a second, once | Orders of magnitude more CPU than the attack was worth |
Compared with a CAPTCHA
A traditional CAPTCHA asks a person to do something — identify images, click a box. It works, but every legitimate visitor pays with an interaction, and image-based puzzles are now often solved more reliably by machines than by tired humans.
A proof-of-work challenge asks the browser instead of the person. Nothing is clicked and usually nothing is noticed beyond a brief delay. It does not prove humanity — a headless browser passes — but it does prove that a full browser engine ran, which is enough to stop the overwhelming majority of automated traffic.
Tuning difficulty
Difficulty sets how many attempts the solution needs on average, and it is a genuine trade-off: too low and tooling can afford it, too high and someone on an old phone waits noticeably.
The sensible approach is adaptive. Raise difficulty only while the origin is genuinely under strain, and scale it with how suspicious the request already looks, so ordinary visitors get an imperceptible puzzle and clearly suspect clients get an expensive one.
Frequently asked questions
Last updated