A heuristic is a rule that is frequently correct, but not always. TRACEY uses heuristics to find probable patterns. The Bitcoin blockchain records amounts, addresses, transactions and times. It does not record names, wallets, companies or intentions. All other data that TRACEY adds is a guess. These guesses come from the usual structure of transactions.
A heuristic is not proof. It is frequently correct, but it can be very wrong. Some users and privacy tools make transactions that break heuristics intentionally. Use each heuristic only as a lead. Compare it with other evidence, for example court records, answers from exchanges or attributions. Do not state it as a fact.
On this page: Change · Common ownership · CoinJoin · B/E/S · Behavioral fingerprint · Peel chain · Trace settings
When a wallet makes a payment, it usually sends the remaining amount back to the sender. This new output is the “change”. If you know which output is the change, you know where the money of the sender went next.
TRACEY examines only transactions with exactly two outputs. The change output is the output that:
If these rules do not give one clear result, TRACEY does not mark an output. A grey dashed line shows a change output.
These conditions cause incorrect results: wallets that send change to the same address type as the payment, PayJoins, and change with a round amount. Many new wallets make the change type the same as the payment type. They do this to prevent this guess.
Sources: Bitcoin Wiki: Privacy, change address detection · Meiklejohn et al. (2013): A Fistful of Bitcoins · Ishaana Misra (2023): Wallet Fingerprints
To spend coins, a wallet must sign each input. Thus, the addresses that pay into the same transaction usually belong to one wallet. This is the oldest heuristic in blockchain analysis. Analysts also use it more than all other heuristics.
A CoinJoin puts the coins of many unrelated persons into one transaction. If TRACEY does not identify a CoinJoin, common ownership puts these persons into one wallet. This error then moves along the links to more addresses. PayJoins break the rule intentionally. Exchanges spend the deposits of many customers together. Thus, one “wallet” can be one company, not one person.
Sources: Satoshi Nakamoto (2008): Bitcoin whitepaper, section 10 · Bitcoin Wiki: Common-input-ownership heuristic · Meiklejohn et al. (2013): A Fistful of Bitcoins
A CoinJoin is a privacy transaction. Many persons put their coins into one transaction, so it is difficult to know which coins went where. Some designs (for example Whirlpool or JoinMarket) give each person the same output amount. Other designs, for example WabiSabi (Wasabi Wallet), use many different amounts and mix them.
TRACEY uses the CoinJoin rule of mempool.space. All of these conditions must be true:
A transaction that agrees with these rules gets a yellow “cj” badge. TRACEY never uses CoinJoins for common ownership. This is true when you select the “show CoinJoin” box and when you do not select it. TRACEY finds inscriptions from their standard marker. mempool.space does a full analysis of inscriptions.
The mempool.space code calls this rule a “fast but bad heuristic”. It does not find CoinJoins with many different amounts or with fewer than 5 persons. It can incorrectly mark usual payouts that have many equal amounts.
Sources: mempool.space source code: getTransactionFlags (common.ts) · Bitcoin Wiki: CoinJoin
Analysis companies and researchers usually do not identify exchanges from one pattern. They start with addresses that they know belong to an exchange. These addresses come from their own test deposits and withdrawals, from published addresses and from court records. Then they use common ownership to find more addresses. TRACEY cannot know the start addresses of an exchange. You must supply them as labels.
An address gets the purple B/E/S badge when one of these conditions is true:
TRACEY does not use the number of transactions of an address for this rule. That number only sets when TRACEY stops at an address. Put the pointer on the badge to see which rule applies.
A person or a mining pool that pays many persons at the same time looks like a large payout. A large CoinJoin can also look like a large payout. When the badge goes along common ownership, it also takes all the errors of that heuristic. TRACEY does not find services that do not pay many outputs in one transaction.
How analysts usually identify exchanges: Meiklejohn et al. (2013): A Fistful of Bitcoins · United States v. Sterlingov (D.D.C. 2024): co-spend clustering in court · Cryptocurrency Address Clustering and Labeling (deposit address heuristic, Ethereum) · Kappos et al. (2022): How to Peel a Million · Harlev et al. (2018): Breaking Bad · Zola et al. (2019): Cascading Machine Learning to Attack Bitcoin Anonymity
Background information (TRACEY does not use these for the large-payout rule): Bitcoin Optech: Payment batching · mempool.space source code: batch payout flag (common.ts)
Each wallet program sets the technical details of a transaction in its own way. These details include the version number, the locktime, the sequence numbers, the order of inputs and outputs, and the change. These default settings can show which software made a transaction.
TRACEY removes wallets from the list one at a time. It removes a wallet when the transaction has a property that the wallet never makes with its default settings. The wallets that remain are the result. If 3 or fewer wallets remain, the tag shows all of them (“Bitcoin Core or Sparrow”). If 4 or more wallets remain, there is no tag.
| Wallet | Version | Locktime | nSequence | Order and other traits | Compared with |
|---|---|---|---|---|---|
| Bitcoin Core | 2 | block height | MAX-2 | random order; only low-R signatures; the change type is the same as the payment type | current code (Nov 2026) |
| Electrum | 2 | block height | MAX-2 | BIP69 inputs and outputs; only low-R signatures | current code (4.8.4) |
| Sparrow | 2 | block height | MAX-2 | random order of inputs and outputs | current code |
| BlueWallet | 2 | 0 | exactly 2,147,483,648 | the change is the last output | current code (8.0.2) |
| Trezor Suite | 1 | 0 | MAX-2 | random order | current code |
| Ledger Live | 1 | 0 | exactly 0 | oldest coins first; the change is the last output | current code |
| Wasabi Wallet | 2 | random: 0 in 90% of transactions, if not, near the block height | final, or MAX-1 with a locktime (no RBF signal) | random order of inputs and outputs | current code (2.8.5) · no tag |
| BitBoxApp (BitBox02) | 1 | 0 | MAX-2 | random order of inputs and outputs: on the blockchain, the same as Trezor Suite | current code (4.52.0) |
MAX-2 is the sequence value 0xfffffffd. MAX-1 is 0xfffffffe. TRACEY examines “oldest coins first” only for transactions with 3 or more inputs, and only while Ledger is still possible. This examination needs one more request for each input. Trezor Suite and BitBoxApp make transactions in the same way. Thus, TRACEY always shows them together. Wasabi Wallet is in the list, but TRACEY never shows a Wasabi tag. Wasabi intentionally makes its usual transactions look like usual network traffic: version 2, a random locktime that is usually 0, and no RBF signal. In a test on 1,500 recent transactions, a Wasabi tag matched 214 transactions. Almost all of them were the most usual type of transaction. Thus, the tag shows mostly other software. The CoinJoin rule still finds Wasabi CoinJoins. Coldcard is not in the list. It only signs transactions that other software makes (for example Sparrow or Electrum). Thus, its transactions show the fingerprint of that software. The rules for address reuse, OP_RETURN and Taproot spends come from the 2023 study by Misra. Exodus, Coinbase Wallet and Trust Wallet are not in the list. Their code is not public, and only data from 2023 is available.
TRACEY compares the transactions that do not agree with a known wallet. It uses the traits below. Each wallet (grouped by common ownership) gets a profile. The profile contains the traits that all of these transactions of the wallet have. Two or more wallets get the same “fingerprint” tag when they have the same traits. The number of these traits must be equal to or more than the setting (default 9/9). TRACEY does not use CoinJoins.
| Trait | Used | How TRACEY examines it | Reason / cost |
|---|---|---|---|
| Version 1 | yes | the transaction version is 1 | most wallets use version 2 |
| Locktime 0 | yes | the transaction has no locktime | frequent, thus weak alone |
| RBF off | yes | the sequence of each input is final | most wallets signal RBF |
| BIP69 inputs | yes, 3+ inputs | inputs in the order of previous txid, then index | with 2 inputs, the order is correct by chance in half of all transactions |
| BIP69 outputs | yes, 3+ outputs | outputs in the order of amount, then script | same reason |
| Same whole-number fee rate | yes | the fee rate is within 0.05 of a whole number, and the number is the same | a fixed rate can show a fixed setting |
| Rare input type | yes | all inputs are the same multisig type (for example 1-of-1), bare multisig or P2PK | usual wallets do not make these |
| Change to a rare address type | yes | TRACEY finds the change with the wallet-fingerprint change rules. It counts the change only if it goes to P2WSH, P2SH or P2PKH | common types (P2WPKH, Taproot) are too frequent to show a pattern; the change rules can select the incorrect output |
| Close in time | yes | the two wallets have transactions within 6 blocks (approximately one hour) | this can show one sender, not one software; it needs no more requests |
| Single-use input addresses | no | – | needs one more request for each input |
| Inputs from exchange-type payouts | no | – | needs one request for each input; it shows the source of the money, not the software |
| The same fingerprint spends the change later | partially | only if the change address is in the same wallet group | – |
| Same payout amount | no, intentionally | – | it is specific to one case and is not a fingerprint |
| Peel chain pattern | separate | see Peel chain | – |
Profiles show the default settings of specific versions. Users can change settings, and wallets change their defaults. Wallets that are not in the list can look like a wallet in the list. The tag means “behaves like”, not “is”. In the study by Misra, one transaction identified its wallet in approximately half of the cases.
Sources: Ishaana Misra (2023): Wallet Fingerprints: Detection & Analysis · Misra: detection code · Bitcoin Core: spend.cpp · Electrum: wallet.py · Sparrow: Wallet.java · BlueWallet: abstract-hd-electrum-wallet.ts · Trezor Suite: sorting default · Ledger Live: buildTransaction.ts · Wasabi: LockTimeSelector.cs · Wasabi: TransactionFactory.cs · NBitcoin (used by Wasabi): TransactionBuilder.cs · BitBoxApp: maketx.go · Bitcoin Optech #410 (2026): RBF signaling as a fingerprint · Discrypt (2025): Wallet fingerprinting in Bitcoin
In a peel chain, the owner spends a large coin again and again. Each transaction pays out (“peels off”) a smaller amount. It sends the larger remaining amount to a new address. The next transaction spends that address in the same way. Services that pay customers make peel chains. Persons who move money in steps also make them. Frequently, automatic software makes these transactions.
TRACEY finds only chains that the graph shows. Expand transactions to follow a chain farther. TRACEY assumes that the larger output is the remaining amount. This is usually correct, but not always. A person who makes many usual payments in a sequence from one coin looks the same.
Sources: Meiklejohn et al. (2013): A Fistful of Bitcoins (peeling chains) · Kappos et al. (2022): How to Peel a Million
These settings control what the graph shows. They are limits. They are not guesses about the owner of an address.
| Address / transaction ID | Label | Label source | ||
|---|---|---|---|---|
Type Bitcoin addresses or transaction IDs. You can also type labels. TRACEY traces each address in the list. For a transaction ID, TRACEY shows the addresses that paid into it and the sources of those coins (one hop back). It also traces each output forward. You can paste a list with one address on each line. After an address, you can add a comma and a label.