• Hash256
  • Hash160
  • Reverse Bytes
  • Hexadecimal
  • Satoshis


Storing data in bitcoin transactions.

NULL DATA is a standard locking script that you can use to store data on the blockchain.

WARNING: This locking script cannot be unlocked, so I wouldn’t use it as a lock for any amount of bitcoins.

How does it work?

The OP_RETURN opcode immediately ends the execution of the script and marks it as invalid.1

Therefore, any output with a NULL DATA locking script on it is unspendable:

There is no way you can unlock this locking script.

So what’s the use of the NULL DATA locking script?

You can use NULL DATA for data storage, because the standard script allows for a data push at the end.

So if you want to add some arbitrary data to a transaction; include an extra (empty) output, and place a NULL DATA locking script on it:

A transaction can only include one NULL DATA locking script for it to be considered a standard transaction (meaning that it will be relayed by nodes).

What data can you store in the NULL DATA script?

You can store up to 80 bytes2 of any data you want. But most people just encode text strings in to it. For example:

scriptPubKey 6a0b68656c6c6f20776f726c64
OP_RETURN 68656c6c6f20776f726c64
hex | opcodes inline | stack

How is that a text string?

Transaction data is typically represented in hexadecimal format, so it’s not always immediately obvious what the data is by looking at it.

But if it’s text, so you can read it by converting each byte from hexadecimal to its ASCII character code:

hexadecimal = 68656c6c6f20776f726c64
ascii       = h e l l o   w o r l d
ASCII Character Code Chart

Of course, you can store up to 80 bytes of any data you want (not just text in the form of ASCII character codes). You just need to know how to decode it to see what it is.

Where can you find NULL DATA scripts?

Anyone can use a NULL DATA script to add some arbitrary data to a transaction, so you can find them scattered around the blockchain.

Look for empty outputs when browsing the blockchain, as NULL DATA scripts are almost always placed on empty outputs (because the outputs are made unspendable by the lock).

Here are some examples of people using the script to store strings of text (hover over the data push to see the ASCII text):

Example 1 - “hello world”

scriptPubKey 6a0b68656c6c6f20776f726c64
OP_RETURN 68656c6c6f20776f726c64
hex | opcodes inline | stack

Example 2 - “charley loves heidi”

scriptPubKey 6a13636861726c6579206c6f766573206865696469
OP_RETURN 636861726c6579206c6f766573206865696469
hex | opcodes inline | stack

Example 3 - “家族も友達もみんなが笑顔の毎日がほしい”

scriptPubKey 6a39e5aeb6e6978fe38282e58f8be98194e38282e381bfe38293e381aae3818ce7ac91e9a194e381aee6af8ee697a5e3818ce381bbe38197e38184
OP_RETURN e5aeb6e6978fe38282e58f8be98194e38282e381bfe38293e381aae3818ce7ac91e9a194e381aee6af8ee697a5e3818ce381bbe38197e38184
hex | opcodes inline | stack

Why was NULL DATA introduced as a standard script?

The NULL DATA locking script was introduced in Bitcoin 0.9.0 as a compromise to allow people to include arbitrary data inside transactions.

You see, before the NULL DATA script came about, people were adding data to transactions by using the existing standard locking scripts. For example, you could always use a P2PKH script and put your arbitrary data inside where the hashed public key should go:

scriptPubKey 76a91400000000006c6561726e6d6561626974636f696e88ac
OP_DUP OP_HASH160 00000000006c6561726e6d6561626974636f696e OP_EQUALVERIFY OP_CHECKSIG
hex | opcodes inline | stack

However, the problem with this approach is that it looks like a standard locking script, so the output would be stored in the UTXO database, which is a waste of RAM as the output is effectively unspendable.

So this is where the NULL DATA comes in:

scriptPubKey 6a0f6c6561726e6d6561626974636f696e
OP_RETURN 6c6561726e6d6561626974636f696e
hex | opcodes inline | stack

This script contains OP_RETURN, which means it provably unspendable. Therefore, there is no need to store it in the UTXO database, which saves on precious RAM space.

Using the blockchain for data storage isn’t ideal, but you can’t stop people from doing it. Therefore, the NULL DATA script acts as a more reasonable alternative for data storage than previous methods.

On OP_RETURN: There was been some confusion and misunderstanding in the community, regarding the OP_RETURN feature in 0.9 and data in the blockchain. This change is not an endorsement of storing data in the blockchain. The OP_RETURN change creates a provably-prunable output, to avoid data storage schemes – some of which were already deployed – that were storing arbitrary data such as images as forever-unspendable TX outputs, bloating bitcoin’s UTXO database.

Bitcoin 0.9.0 Release Notes


OP_RETURN must be evaluated for a script to fail.

The presence of the OP_RETURN opcode in a script does not automatically render the script invalid.

For example, in the script below the OP_RETURN is in a branch that will never be evaluated, and so the script is valid:


You can see an example of this script in action (wrapped inside a P2SH) here.

Thanks to Vincenzo Iovino for pointing this out.

  1. https://bitcoin.stackexchange.com/questions/49303/op-return-marks-transaction-or-output-as-invalid↩︎

  2. https://bitcoin.org/en/release/v0.12.0#relay-any-sequence-of-pushdatas-in-opreturn-outputs-now-allowed↩︎

By Greg Walker,

Last Updated: 07 Jun 2022
  • 07 Jun 2022: Removed coinsecrets.org link. No longer online.
  • 04 Feb 2021: spelling fixes
  • 21 Jul 2020: redirected and renamed files from /guide/ to /technical/
  • 21 Jul 2020: renamed /guide/ to /technical/
Back to Top

Hey there, it's Greg.

I'll let you know about cool website updates, or if something seriously interesting happens in bitcoin.

Don't worry, it doesn't happen very often.