

I’ve spent the past few days digging into OP_RETURN—Bitcoin’s mechanism for embedding arbitrary data into the blockchain. What follows is a technically oriented summary of how OP_RETURN works, its limitations, and some practical considerations.
—
Bitcoin Transaction Internals: A Quick Recap
Every Bitcoin transaction consumes one or more inputs and creates one or more outputs. Each output is composed of:
Value: The amount of BTC to be transferred.
Locking Script (scriptPubKey): A script that defines the conditions required to spend the output. In standard transactions, this is typically a P2PKH or P2WPKH script that locks the output to a specific public key hash.
Normally, these outputs become UTXOs (Unspent Transaction Outputs), which are tracked in memory by full nodes (e.g., bitcoind, btcd). However, there is one key exception: outputs with an OP_RETURN script.
—
Context: Pre-OP_RETURN Data Hacks
Before OP_RETURN was introduced in Bitcoin Core 0.9.0 (March 2014), various hacks were used to embed data into the chain:
Vanity addresses: BTC was sent to syntactically valid but unspendable addresses such as 1TodayIsFridayatpoGgzqxD7r2BMLr9dG.
Bare OP_CHECKMULTISIG outputs: Used as null-data outputs.
These techniques had a major downside: the outputs were seen as spendable (even though they weren’t in practice) and thus remained as UTXOs. This caused UTXO set bloat, increasing RAM requirements for all nodes. Worse, the coins sent to these outputs were permanently lost—effectively burned.
—
Enter OP_RETURN: Prunable Null Data Outputs
OP_RETURN was introduced to allow data storage in the blockchain without bloating the UTXO set. When a Bitcoin full node parses a transaction output script and sees OP_RETURN, it flags the output as unspendable and excludes it from the UTXO set.
A canonical OP_RETURN script looks like this: