How to add messages in Bitcoin Transactions

On-chain or Lightning

Translations: German 🇩🇪

To do this, we need to use an opcode called “OP_RETURN”. There are probably many ways to do it, but I will demonstrate the only way I know, which is using the Electrum Desktop Wallet (Learn how to use this amazing wallet with my guides). This technique is just another reason why Electrum is my favourite Bitcoin Wallet. Thank you to @D_plus__plus who very kindly alerted me to this feature in Electrum.

As we all know, Craig Wright is a liar and a fraud, so that statement is about to be published on the Bitcoin Blockchain forever.

Step 1 – Encode the message

This message used here will be “Craig Wright is a liar and a fraud”. Each character, including the spaces, are mapped to an 8-bit binary number (a byte) as per the ASCII protocol. Each byte can be represented by 2 hexadecimal numbers. You don’t have to understand all that, but if you want to, you can see the Appendix of my article explaining how to do a SHA-256 calculation with pen and paper.

For this guide, it will suffice to know that you just need to convert the text to a hexadecimal number, and you can use an online tool:

Make sure the “From” and “To” fields are correct and the “Character encoding” field is set to ASCII. Also the “Output delimiter string” should be changed to “None”.

Type your message then click “Convert”, then copy the number. (The output needs to be shorter than 160 hex characters, which is 80 bytes, or your message is too long.)

Step 2 – Spend from Electrum

First, select any UTXO you wish to spend (Learn more on what a UTXO is). In the address window (or coins window), right-click the particular UTXO (or address), and select “spend from”:

Then in the “Send” tab, enter an address you wish to send the UTXO balance to (Otherwise it all goes to the miner! Be very careful!).

Then a comma, no space, then the amount of bitcoin to send (put a little less than the total UTXO value otherwise you’ll get an error – you need to leave some for mining fees). Hit enter for a new line. Notice the “Amount” window should update – don’t try to modify that window/field; use the “Pay to” field to set the amounts.

On the second line, type “OP_RETURN” in uppercase (I think it must be uppercase, not sure), then a space, and then, in hexadecimal, paste the ASCII number values of the data you want to add (from step 1). Then a comma, then a zero (so we don’t burn any sats to this script).

Note, the OP_RETURN data must be under 80 bytes (160 hex characters) to be relayed by standard nodes (otherwise you have to mine it yourself or pay a miner directly to mine it.)

You can see my example below. I’ve got an address and a bitcoin amount, then on the next line an “OP_return” instruction and some hex text, then an amount (zero). (I have a space between the comma and amount on the second line but not on the first line, I guess it makes no difference.)

Now just proceed to “Pay…”, then click “advanced” in the next pop-up, and you’ll get to a summary of the transaction:

The UTXO to spend from is in the upper “Inputs” window. In the lower “Outputs” window, there are two outputs. The first is the “OP_RETURN” output called “SCRIPT”, and the second is the destination of the sats to an address. The mining fee is 500 sats, at a rate of 3.2 sats per byte (3.2 s/byte rounded off x 155 bytes = 496 sats). The sats/byte value and the total mining fee is in the top left corner. (The “Target fee” value of 2.3 sats/byte in the bottom left corner is not reflective of the fee and wasn’t applied.)

Be absolutely sure where the input UTXO funds are going. Make sure the total of the input adds up to the total of the outputs INCLUDING the mining fee. (Input amount = outputs amounts, plus mining fee). Also be aware that Electrum drops off any trailing zeros when displaying the total mining fee to be paid, so 0.000111 for example is not 111 sats as it might first look with a casual glance – there are two trailing zeros missing so it’s 11,100 sats.

Final warning: To spell it out further, if you have for example a 1.0 bitcoin UTXO to spend, and you set the OP_Return value to zero sats (good), and an payment of 0.1 bitcoin to an address, and nothing else specified, then the remainder (0.9 bitcoin) will be sent to the miner! Don’t do that.

Next, click “Finalise”, then “Sign”, then “Broadcast”:

The transaction will be sent to a node, and picked up by a miner and formed into a block. All miners will have similar transactions contained in the block they made; one miner will win, and send that block to the Bitcoin network of nodes. Once that happens, your wallet will see the transaction and update its records. Here is the transaction ID:


When pasted into, a blockchain viewer (you can use your own, or the public one that I linked), you’ll see the transaction with the text converted from hexadecimal, to ASCII, to text.

I’m so glad I didn’t make a spelling error; like Twitter, there are no takebacks.

Here is the same transaction expanded, with more details:

I don’t know about you, but I think that’s cool.

You can now go and practice and make your own messages, maybe even propose to your girlfriend. If you’re looking to dispose of some sats in the process, I’d be honored to receive them and will take good care of them. Just use my donations app below to generate an address. Please also let me know with an email or Nostr/Twitter message.


Static Lightning Address:

On-chain or Lightning

%d bloggers like this: