A fifth of an x402 marketplace's requests come from the marketplace
This content reflects minia2a as of its publication date and is kept for the record. Current model: x402 pay-per-call in USDC on Base only, 5 free trial calls per signed wallet, no credits and no top-up rail.
November 2026
An x402 catalogue answers a lot of requests. The number on the dashboard goes up every day, and it is tempting to read that line as demand. It is not demand. It is mostly machines checking whether the endpoints are still there, plus the operator's own checks, plus a long tail of clients that announce nothing at all.
This post is a 24-hour census of one live catalogue, taken from the web server's own access log, with the client address read before the User-Agent. The result is not flattering, which is the point: a marketplace that cannot separate its own traffic from a buyer's cannot tell you whether anyone wants what it sells.
The window
From 10 November 2026 20:44 UTC to 11 November 2026 20:44 UTC, the log held 117,272 requests. Every line carries the address the edge reported, and most carry a User-Agent string. Addresses were classified against the platform's own list of its machines - the same list the gateway uses to decide whether a request comes from a host we run - and only then against the announced User-Agent.
- window: 24.0 h, 117,272 requests
- origin: external 93,153 (79.4%), ours 24,119 (20.6%)
- status:
402: 98,278,200: 16,232,202: 774,404: 687, rest < 550 - 2xx on a paid path (
/x402,/svc): external callers: 2 (2 requests), internal: 70
Two outside clients got a 2xx from a paid endpoint in a full day, and both are settlement probes from public directories - a probe that pays one cent to check a listing still delivers. Everything else that reached a 2xx came from our own machines. The 98,278 challenges are not usage either: a 402 is the door answering, not a buyer walking through it.
What the traffic actually is
| Class | Requests | Share |
|---|---|---|
| Third-party directory indexers (liveness) | 45,924 | 39.2% |
| Other / unrecognised clients | 31,920 | 27.2% |
| Third-party probes and scanners | 12,138 | 10.4% |
| Our own guards (announced) | 11,941 | 10.2% |
| Generic HTTP runtimes (curl, requests, urllib) | 9,082 | 7.7% |
| Browsers | 3,716 | 3.2% |
| No User-Agent at all | 2,551 | 2.2% |
Note that the largest single row is not a customer. It is a directory asking, at high frequency, whether our endpoints still answer. That is useful - it is how a catalogue stays listed - but it is supply-side maintenance traffic, and it dwarfs the two outside calls that actually paid.
Why the User-Agent cannot answer this question
The first version of this census classified callers by their announced User-Agent, because that is the field that was already in the log. It produced a comfortable story and it was wrong in both directions.
Our own guard sweep walks the whole catalogue once a day, one anonymous GET per endpoint. It sends no identifying User-Agent, so it lands in the same bucket as any unattended script: on the day this was measured, the top "generic runtime" entry was Python-urllib with 1,708 requests - 1,686 of them our own sweep.
Meanwhile the opposite error was live too: the census knew two of our hosts and the platform knows five, so traffic from three of our own machines was being published as an outside caller. About 300 requests a day sat on the wrong side of that line.
A User-Agent is a claim by the caller, not a fact about it. If you operate a service, classify by address first and get your own host list from one place - ours lives in the gateway that enforces the same rule at request time. If the list is copied into each reporting tool, one copy will be missing a host, and the tool will confidently publish your own traffic as demand.
What follows for anyone reading an index
If you build on a discovery directory, this is the question to ask about any number it shows you: what is subtracted? A timestamp that means "last bought" and a timestamp that means "last called" are different facts, and a request count that includes liveness probes is a measure of how many directories watch the endpoint, not how many agents want it.
We have the same limitation on the other side of the table - our catalogue's own freshness stamp comes from a daily manifest generation, not from a verification, and we say so where it is published.
The asymmetry has a practical consequence. If you are deciding where to list, the useful metric is not requests, and not even 402s. It is distinct paying wallets over a window, with the operator's own machines removed. On the same day this log was taken, that number for this platform was five in seven days, counting wallets rather than identities, and including paid calls made by verification probes. That is a small number. Publishing it is more useful than publishing the traffic line, because it tells you what the traffic line cannot.
Method, limits, what we do not claim
- Client addresses come from the edge's reported address; rows with no address are counted as unknown, never guessed as external.
- The User-Agent class is the declared string after lowercasing and prefix matching. It is not a fingerprint and it can be spoofed by any client.
- Private and loopback addresses are treated the way the gateway treats them: a request that cannot have crossed the public internet came from a host we run. The ranges are spelled out rather than taken from a library default, because the defaults also cover documentation ranges and carrier-grade NAT.
- "Paid path" means the request line started with
/x402/or/svc/. A 2xx there is a delivered response; a 402 is a challenge and is counted as one.
The census is a script in this repository that runs daily against the site's own log and stores no client address - the question it answers is "which channel", not "who". The two numbers in this post that matter are the ones that would embarrass a marketplace if they were wrong, and they were wrong two days ago in both directions. Writing them down is the only way they stay honest.
Originally published at minia2a.uk.
Comments
No comments yet. Start the discussion.