Disclaimer: this module was developed with the help of AI 🤖 under the supervision. Reviews of the code are done with humans.
Proof of Work protects selected routes against scrapers and other automated traffic. Visitors without a valid pass are redirected to a challenge page. Once they pass the challenge, a signed cookie lets them through for the pass lifetime of that challenge.
The module is stateless: challenges, tokens and passes are HMAC-signed with the client IP address (IPv6 per /64) and a timestamp. No sessions, database tables or other storage are used.
Features
- Protect any route from the settings page, or from code with the
_proof_of_workroute option. - Pluggable challenges: enable them, order them by weight and configure each one, including its own pass lifetime.
- SHA-256 puzzle: the browser solves a SHA-256 puzzle in a Web Worker. Every extra bit of difficulty doubles the average solving time.
- Waiting time: a fallback without JavaScript that forwards the visitor after a waiting time.
- Protected pages stay cacheable in Drupal's internal page cache; visitors without a pass are still redirected to the challenge.
- Protected pages are sent with
Cache-Control: private, so shared caches (Varnish, CDN) do not store them. - Users with the Bypass proof of work challenge permission are never challenged.
- Theme-friendly: templates without classes and basic CSS with custom properties.
Requirements
- Drupal 11.1 or later.
- PHP 8.3 or later.
- HTTPS for the SHA-256 puzzle: browsers only expose the Web Crypto API on secure origins.
Installation
composer require drupal/proof_of_work drush en proof_of_work
Then go to Administration » Configuration » System » Proof of work to select the routes to protect and configure the challenges.
Good to know
- Passes are bound to the client IP address. Behind a reverse proxy or load balancer, configure
reverse_proxyinsettings.php, otherwise all visitors share the IP address of the proxy and a single pass works for everyone. - Anyone can choose the challenge without JavaScript, so the weakest enabled challenge determines the actual protection.
- Proof of work raises the cost per IP address for cheap scrapers and mass requests. It does not stop a determined attacker: native code solves the puzzle far faster than a browser. Combine it with rate limiting in your reverse proxy or web application firewall.
Writing your own challenge
Challenges are plugins with the #[ProofOfWorkChallenge] attribute. Extend ProofOfWorkChallengeBase and implement build(), verify() and buildVerifyResponse(). See the README for details.
Maintainers
Developed and maintained by SWIS.
Ask your assistant about Proof of work
Check compatibility with your Drupal and PHP version, maintenance and security coverage, from current release data. How it works
Depends on
Dependencies of the latest stable release
No dependencies recorded for this project.
Required by
Tracked projects that depend on this one
No tracked projects depend on this one yet.
Activity
Releases
| Version | Type | Core | PHP | Release date | |
|---|---|---|---|---|---|
| 1.0.0-alpha3 | Pre-release | 11 | PHP >=8.3 | Nov 9, 2026 | |
| 1.0.0-alpha1 | Pre-release | 11 | PHP >=8.3 | Nov 9, 2026 |