Skip to main content
ForgeMeshPay-per-Crawl for nginx · vsnippet · free, open source

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

nginx.conf (excerpt; full example in the repo)nginx.conf
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

  1. 1Install the njs module and copy pay-per-crawl.js to /etc/nginx/njs/.
  2. 2Merge nginx.conf.example into your config: wallet, secret, upstream, mode monitor.
  3. 3nginx -t && nginx -s reload, then curl -i -A GPTBot https://your-site/ and expect 402.
  4. 4Set ppc_mode "gate" when ready.

Settings

ppc_pay_toYour 0x wallet on Base.
ppc_price_usdPrice per page, default 0.01, minimum 0.005.
ppc_modemonitor or gate.
ppc_class_policy / ppc_bot_overridesJSON policy per class and per crawler.
ppc_trust_headerHeader with the real client IP if nginx sits behind another proxy. Right-most entry used.
ppc_doh_urlDNS-over-HTTPS resolver for search-engine verification.
ppc_mpp_secretLong 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

Other stacks

WordPressNext.jsVercelCloudflare WorkersNodePythonGoPHP