reorgstats groups observed Bitcoin stale headers into connected branches. It
counts one-block, two-block, three-block, and deeper branches and can overlay
them on an estimated network hash-rate chart.
The program has no third-party Go dependencies.
Rows without a full 80-byte header are reported and excluded from depth counts. Their parent linkage cannot be reconstructed from a block hash alone.
For a simple mining race, one stale header is depth 1. Two linked stale headers are depth 2. The program follows each stale header's previous-block hash and uses the longest linked path as the event's observed depth.
This is not a globally complete log of node reorganizations. A stale branch may have caused one node to disconnect blocks while another node only ever followed the winning branch. Missing stale headers can also make a branch look shorter. The result should therefore be read as observed stale-branch depth.
Deep branches need manual classification. The source dataset includes deliberate chain splits and policy forks in addition to ordinary mining races. A connected 18-block branch is not automatically evidence that Bitcoin mainnet suffered an 18-block probabilistic reorg.
Use a node's activity log when you need proof that the specific node changed from one active tip to another.
The chart at https://bitcoin-data.github.io/stale-blocks/ does not plot reorg depth. Its y-axis is stale blocks per 1,000 blocks, smoothed with a 10,000-block rolling average. The table below that chart lists individual stale blocks but does not join their parent links.
reorgstats adds that missing grouping. It follows the previous-block hashes
and counts the resulting connected stale branches by depth.
go build -o reorgstats .The default data source is
bitcoin-data/stale-blocks.
./reorgstats summaryRestrict the time range:
./reorgstats summary --since 2015-01-01 --until 2025-12-31Machine-readable output:
./reorgstats summary --format csv
./reorgstats summary --format json./reorgstats list --depth 1
./reorgstats list --depth 2
./reorgstats list --min-depth 3
./reorgstats list --min-depth 2 --format jsonThe CSV and JSON formats include full block hashes. The table shortens hashes for readability.
./reorgstats chart --since 2015-01-01 --out reorgs.svgThe chart uses Blockchain.com's daily estimated hash-rate series by default.
Hash rate uses a logarithmic axis. Stale-branch depth uses the right-hand axis.
Depths above 10 share the 10+ position so short branches remain visible. Use
--depth-cap 0 for an uncapped axis.
Both data sources can be local files:
./reorgstats chart \
--input stale-blocks.csv \
--hashrate-input hash-rate.json \
--out reorgs.svgThe CSV reader decodes every 80-byte block header and recomputes its double SHA-256 block hash. It rejects a row when the computed hash differs from the CSV hash.
The tool deduplicates headers by hash. Headers connected through a previous-block hash form one event. If a stale component branches, its depth is the longest path and its block count includes every observed block in the component.
- Stale headers: https://github.com/bitcoin-data/stale-blocks
- Hash rate: https://api.blockchain.info/charts/hash-rate?timespan=all&format=json
- Per-node fork monitoring: https://fork.observer/