Raw Transaction Serialization

How to serialize a Bitcoin transaction into raw hex — version, inputs, outputs, and locktime in the correct byte order.

0steps ·

Progress 0/0

What You’ll Learn

  • The complete serialization format for a Bitcoin transaction
  • Little-endian encoding and why Bitcoin uses it
  • How to assemble every field into a single hex string

Transaction Format Overview

A serialized Bitcoin transaction is a sequence of bytes with a rigid structure. Here is the layout for a legacy (non-SegWit) transaction:

[Version] [Input Count] [Inputs...] [Output Count] [Outputs...] [Locktime]

For a SegWit transaction, two additional fields are inserted:

[Version] [Marker] [Flag] [Input Count] [Inputs...] [Output Count] [Outputs...] [Witness...] [Locktime]

Let’s walk through each field.

Version (4 bytes)

The transaction version number. Almost all modern transactions use version 2 (which enables relative timelocks via BIP68):

02000000

This is 0x00000002 in little-endian. Version 1 (01000000) is still valid but does not support BIP68 sequence-based timelocks.

Marker and Flag (SegWit only, 2 bytes)

SegWit transactions insert a marker byte (0x00) and a flag byte (0x01) after the version. These tell parsers that witness data follows:

0001

The marker must be 0x00. The flag must be non-zero (currently always 0x01).

Input Count (VarInt)

A variable-length integer indicating the number of inputs. For 1-252 inputs, this is a single byte:

01  →  1 input
02  →  2 inputs
fd  →  followed by 2-byte little-endian count (for 253+)

Serialized Inputs

Each input is serialized as we described in Step 3:

[Previous TX Hash: 32 bytes]
[Output Index: 4 bytes]
[ScriptSig Length: VarInt]
[ScriptSig: variable]
[Sequence: 4 bytes]

For a SegWit input before signing, the ScriptSig is empty (length = 00).

Output Count (VarInt)

Same encoding as input count. For our 2-output transaction:

02

Serialized Outputs

Each output as described in Step 4:

[Value: 8 bytes]
[ScriptPubKey Length: VarInt]
[ScriptPubKey: variable]

Witness Data (SegWit only)

The witness section appears after all outputs and before the locktime. Each input gets a corresponding witness stack. We will cover this in detail in Step 8, but the structure is:

[Stack item count: VarInt]
[Item 1 length: VarInt] [Item 1 data]
[Item 2 length: VarInt] [Item 2 data]
...

For a P2WPKH input, the witness contains two items: the signature and the public key.

Locktime (4 bytes)

The locktime field specifies the earliest time or block height at which the transaction can be included in a block:

00000000  →  No locktime (can be mined immediately)

If the value is below 500,000,000, it is interpreted as a block height. Otherwise, it is a Unix timestamp. Most transactions use 0 or the current block height (to prevent fee sniping — a miner incentive attack).

Little-Endian Encoding

Bitcoin serialization uses little-endian byte order for most multi-byte integers. This means the least significant byte comes first:

Decimal 500,000 = 0x0007A120

Big-endian:    0007A120
Little-endian: 20A10700

The exception is the previous transaction hash, which is stored as a raw 256-bit value — but because txids are traditionally displayed in big-endian, you must reverse the byte order when inserting them into the serialized transaction.

Complete Example

Here is our 1-input, 2-output SegWit transaction (before signing):

02000000                      # Version 2
0001                          # SegWit marker + flag
01                            # 1 input
  3f4fa198...7b1eabe0         # Previous TX hash (32 bytes, reversed)
  00000000                    # Output index 0
  00                          # Empty ScriptSig
  fdffffff                    # Sequence (RBF enabled)
02                            # 2 outputs
  e093040000000000            # Output 0: 300,000 sats
  160014<recipient-hash>      # P2WPKH ScriptPubKey
  b882020000000000            # Output 1: 198,590 sats (change)
  160014<change-hash>         # P2WPKH ScriptPubKey
                              # Witness data (empty until signing)
00000000                      # Locktime 0

This hex blob is not yet valid — it needs a signature. That’s next.

Next Step

Continue to Signing the Transaction to learn how to create the cryptographic proof that authorizes spending.