Issue Nº 29 — Sep 12, 2026

The mempool.space API splits across two backends, and each one fails differently

Issue twenty-nine covers mempool.space, the free Bitcoin block explorer and fee API. It needs no key. This session queried it live. Two separate backends sit behind one /api prefix, a bad address returns a different error shape than a bad transaction ID, and an address with zero history still returns 200, not an error.

One /api prefix, two backends, two error styles

GET /api/v1/fees/recommended, queried live this session, returned 200 with an x-powered-by header of Express. GET /api/blocks/tip/height, queried live this session, also returned 200, but its x-powered-by header read mempool-electrs 3.4.0-dev-bf622e5. Two different servers answer the same /api prefix.

The split follows a simple rule. Paths under /api/v1/ go to the Express backend, the mempool.space application itself. Paths without that prefix, such as /api/tx, /api/address, and /api/block, go to a bundled electrs fork, the Bitcoin indexer.

The two backends also disagree on response format. /api/blocks/tip/height, an electrs endpoint, returned the plain number 966502 as text/plain, even on a 200. /api/v1/fees/recommended, an Express endpoint, returned JSON. A client that always parses the body as JSON breaks on the electrs endpoints.

A malformed address and a missing transaction fail differently

GET /api/address/notarealaddress, queried live this session, returned 400 with a text/plain body reading Invalid Bitcoin address. The address string fails format validation before the indexer even looks it up.

GET /api/tx/{all-zero txid}, queried live this session, returned 404 with a text/plain body reading Transaction not found. The zero txid has valid hex format, so the indexer accepts the request and only then reports no matching record.

GET /api/block-height/99999999, queried live this session, returned the same pattern: 404 with a text/plain body reading Block not found. A malformed input gets 400. A well-formed input with no match gets 404. A client that treats both status codes as one generic failure loses that distinction.

A valid but unused address returns 200, not an error

This session generated a random, syntactically valid Bitcoin address that has never appeared on the chain. GET /api/address/{that address}, queried live this session, returned 200 with a JSON body of all-zero counts: funded_txo_count and tx_count both read 0, in chain_stats and in mempool_stats.

That 200 response contrasts with the 400 for a malformed address string. The API treats a wallet with no history as a valid, empty answer, not an error.

A status-code check alone cannot tell an empty wallet from an active one; both return 200. Read tx_count in the body to tell them apart.

Mempool, by the numbers

Rendered live from the atlas entry
AuthenticationNone required
HTTPSSupported
CORSEnabled
PricingFreemium
FormatsJSON, WebSocket
Rate limit

Enforced (exceeding it returns HTTP 429); exact numeric threshold is not publicly disclosed, though a paid enterprise sponsorship raises it

Key endpoints
  • GET/blocks/tip/height
  • GET/v1/fees/recommended
  • GET/tx/{txid}
bitcoinmempoolblock-explorerfee-estimationlightning-network

Sources

Facts checked Sep 2026