Charge AI crawlers at nginx with an njs script
A config snippet, not a package. The njs script issues the 402, accepts the payment, has the facilitator settle it, and proxies to your origin only on a transaction hash.
Works with: nginx with ngx_http_js_module, njs 0.8.0 or newer
Install
apt install nginx-module-njs # from the nginx.org repository
Add the gate
load_module modules/ngx_http_js_module.so;
http {
js_path "/etc/nginx/njs/";
js_import ppc from pay-per-crawl.js;
js_shared_dict_zone zone=ppc_locks:1m timeout=600s evict;
resolver 1.1.1.1;
server {
set $ppc_pay_to "0xYourWalletOnBase";
set $ppc_price_usd "0.01";
set $ppc_mode "monitor";
set $ppc_mpp_secret "long-random-string";
location / { js_content ppc.handle; }
location @origin { proxy_pass http://127.0.0.1:8080; }
}
}Turn it on
- 1Install the njs module and copy pay-per-crawl.js to /etc/nginx/njs/.
- 2Merge nginx.conf.example into your config: wallet, secret, upstream, mode monitor.
- 3nginx -t && nginx -s reload, then curl -i -A GPTBot https://your-site/ and expect 402.
- 4Set ppc_mode "gate" when ready.
Settings
| ppc_pay_to | Your 0x wallet on Base. |
|---|---|
| ppc_price_usd | Price per page, default 0.01, minimum 0.005. |
| ppc_mode | monitor or gate. |
| ppc_class_policy / ppc_bot_overrides | JSON policy per class and per crawler. |
| ppc_trust_header | Header with the real client IP if nginx sits behind another proxy. Right-most entry used. |
| ppc_doh_url | DNS-over-HTTPS resolver for search-engine verification. |
| ppc_mpp_secret | Long random string signing MPP challenges. |
Things to know
- Needs resolver and js_fetch_trusted_certificate for the HTTPS calls to the facilitator and the DoH resolver.
- Log variables $ppc_status, $ppc_class, $ppc_bot, $ppc_tx and $ppc_reason are available to log_format.
- The Pro reporter is not included in this edition.
- Behind Cloudflare, set AI Crawl Control and any "Block AI bots" rule to Allow for the crawlers you want to charge. A crawler blocked at the edge never reaches the gate and never sees the 402.
- Humans never see a 402. Search engines are verified by reverse DNS; a request that only claims to be Googlebot is charged.
- Start in monitor mode. It logs every bot with what it would have paid and never blocks. Switch to gate when the numbers make sense.
Proof it settles
Real settlements on Base mainnet through the PayAI facilitator, $0.01 each, October 2026:
- Tested with the 37-check curl matrix and a mock facilitator on nginx 1.26 / njs 0.8.9; wire code shared with the Node edition