pay-per-crawl-go

module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 17, 2026 License: MIT

README

ForgeMesh Pay-per-Crawl (Go)

Charge AI crawlers and bots per page. Humans and rDNS-verified search engines read free; AI, SEO, automation and unknown bots get an HTTP 402 and pay in USDC on Base with x402 (v1 and v2) or MPP, then retry the same URL.

One Go module, one policy engine, three adapters:

Adapter Path Use it for
net/http middleware middleware any Go service
Caddy module http.handlers.pay_per_crawl caddy sites behind Caddy
Traefik plugin traefik sites behind Traefik

The core is paypercrawl (Classify, Challenge, ExtractPayment, Precheck, VerifyAndSettle, NonceLock, discovery documents, Config). It is a port of the WordPress plugin and behaves the same.

Money flow

The site owner keeps 100%. The USDC goes from the paying agent's wallet straight to your PayTo address. There is no custody, no ForgeMesh account, no API key and no revenue share. The gate calls the payment facilitator itself (default https://facilitator.payai.network: x402 v1 and v2, Base mainnet, no key, no seller fee) and serves the page only after /settle returns a non-empty transaction hash. Nothing is sent anywhere else unless you set an optional Pro key.

Quick start (net/http)

package main

import (
	"net/http"

	"github.com/forgemeshlabs/pay-per-crawl-go/middleware"
	"github.com/forgemeshlabs/pay-per-crawl-go/paypercrawl"
)

func main() {
	site := http.FileServer(http.Dir("./public"))
	http.ListenAndServe(":8080", middleware.Handler(paypercrawl.Config{
		PayTo:    "0xYourWalletAddress",
		PriceUSD: 0.01,
	}, site))
}
go get github.com/forgemeshlabs/pay-per-crawl-go@v0.1.0

Behaviour

  • Classes: human, search, social, monitor (free by default); seo, ai, automation, bot (paid). 85 known crawlers (GPTBot, ClaudeBot, PerplexityBot, AhrefsBot, curl, ...) plus generic bot detection.
  • Search engines are verified by reverse and forward DNS. A request claiming to be Googlebot from a non-Google address is classed automation and charged. Without a verifiable IP, or when DNS is down, the claim is kept.
  • Policy: ClassPolicy per class and BotOverrides per bot, each free, paid or block. Mode: "monitor" classifies and logs what you would have earned without ever answering 402.
  • 402 response: PAYMENT-REQUIRED header (base64 x402 v2 envelope), a v1-shaped JSON body (so stock x402-fetch 1.x can pay; includes invalidReason on a rejected payment), and WWW-Authenticate: Payment (MPP). HEAD is treated like GET.
  • Payment in: PAYMENT-SIGNATURE (v2), X-PAYMENT (v1), Authorization: Payment (MPP). Cheap local checks first (recipient, amount, asset, network, expiry), then the facilitator /verify and /settle. A v1 payment is forwarded in v1 shape. Receipts: PAYMENT-RESPONSE and X-PAYMENT-RESPONSE (plus Payment-Receipt for MPP).
  • Replay lock: an authorization nonce can be presented once. In-memory by default; implement paypercrawl.NonceLock over Redis or a database to share it across instances.
  • Discovery: /.well-known/x402.json, /llms.txt, /agents.txt served for you (DisableDiscovery turns them off); Gate.RobotsAppend returns pointer lines for your robots.txt.
  • Never gated: /robots.txt, /llms.txt, /agents.txt, /.well-known/, /favicon.ico, /sitemap*, and your AllowPaths.

Config

Field Default Notes
PayTo required in gate mode 0x EVM address on Base that receives the USDC
PriceUSD 0.01 per page fetch
Mode gate gate or monitor
FacilitatorURL PayAI any x402 facilitator that supports exact on Base
FacilitatorAuth none sent as the Authorization header to the facilitator
ClassPolicy, BotOverrides see Behaviour free / paid / block
AllowPaths none path prefixes never gated
TrustedIPHeader none see below
ProKey none optional hosted dashboard license (fmppc_...)
MPPSecret random per process set a long random string so MPP challenges survive restarts and span instances
BaseURL, Realm, SiteName, SiteDescription, Contact derived challenge and discovery text
HTTPClient, Lock, Resolver, OnHit, ClientIP defaults injection points
Real client IP behind a proxy

Search-engine verification needs the real client address. Set TrustedIPHeader only to a header that your own proxy overwrites or appends to. For a multi-value header such as X-Forwarded-For the right-most entry is used (the one your proxy added); the left-most is client-controlled, so a scraper cannot prepend a Googlebot address to get the free lane. Single-value edge headers (CF-Connecting-IP, X-Real-IP, True-Client-IP) are taken as-is. If the header is not controlled by your proxy, leave it unset.

Cloudflare

If the site is behind Cloudflare, "Block AI bots" / "AI Crawl Control" must be set to Allow for the crawlers you want to charge. Cloudflare blocks them at the edge before they ever reach this gate, so no 402 is served and nothing can be paid. Also set TrustedIPHeader: "CF-Connecting-IP".

Optional Pro reporter

With a ProKey the gate pushes daily rollups and settlements to the hosted dashboard at proxy.forgemesh.io (Bearer auth, hourly) and pulls the crawler-intel feed. Without a key nothing calls out except the facilitator.

Verified on mainnet

Real paid calls through the PayAI facilitator against examples/nethttp, $0.01 each, to the payTo wallet; receipts confirmed on Base mainnet (status 0x1, USDC transfer of 10000 units):

Rail Transaction
x402 v1 (X-PAYMENT, network base) 0x948aa9522f9feed31a1a8bc77e7c1de88699b1e629759f5677bd6a2e3117c4e8
x402 v2 (PAYMENT-SIGNATURE, eip155:8453) 0x80b5b56043bba8b4b17c95eb9759415affbf9857f8a22a249b841ac16260aebc

The Caddy module was built with xcaddy and the Traefik plugin loaded by Traefik v3.7.15 in local plugin mode; both served the 402, the free human path, HEAD 402, discovery files and a paid retry.

Development

go test -race ./...

Keccak-256 (for the MPP nonce) is implemented in pure Go so the core loads inside Traefik's Yaegi interpreter; tests cross-check it against golang.org/x/crypto/sha3.

MIT licensed. ForgeMesh Labs, hello@forgemesh.io.

Directories

Path Synopsis
Package caddy is the Caddy 2 adapter for ForgeMesh Pay-per-Crawl.
Package caddy is the Caddy 2 adapter for ForgeMesh Pay-per-Crawl.
examples
nethttp command
Example: put the pay-per-crawl gate in front of a plain net/http site.
Example: put the pay-per-crawl gate in front of a plain net/http site.
Package middleware is the plain net/http adapter for ForgeMesh Pay-per-Crawl.
Package middleware is the plain net/http adapter for ForgeMesh Pay-per-Crawl.
Package paypercrawl is the core of ForgeMesh Pay-per-Crawl: it classifies who is asking, answers bot traffic with an x402 (v1 + v2) and MPP 402 challenge, and serves the page only after the facilitator returns a settlement transaction hash.
Package paypercrawl is the core of ForgeMesh Pay-per-Crawl: it classifies who is asking, answers bot traffic with an x402 (v1 + v2) and MPP 402 challenge, and serves the page only after the facilitator returns a settlement transaction hash.
Package traefik is the Traefik plugin (Yaegi) adapter for ForgeMesh Pay-per-Crawl.
Package traefik is the Traefik plugin (Yaegi) adapter for ForgeMesh Pay-per-Crawl.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL