bitcoind.app
CommandsGuidesContact ↗
Home/Guides/Working with Raw Bitcoin Transactions
Transactions

Working with Raw Bitcoin Transactions

How to create, sign, decode, and broadcast raw Bitcoin transactions using Bitcoin Core RPC. A practical guide to manual transaction construction for developers.

In this guide
Why Build Raw Transactions?Transaction AnatomyCreating a Raw TransactionSigning and VerificationCommon Pitfalls

Why Build Raw Transactions?

Bitcoin Core's high-level send commands (sendtoaddress, sendmany) handle transaction construction automatically. But many applications need lower-level control: exchanges managing hot wallet UTXOs, payment processors building batched transactions, and protocols like Lightning Network that require specific transaction structures.

Raw transaction construction gives you complete control over inputs, outputs, fee allocation, lock times, and sequence numbers. The tradeoff is complexity — you're responsible for getting every detail right.

Transaction Anatomy

A Bitcoin transaction has four main components:

Version — currently version 1 or 2 (version 2 enables BIP 68 relative lock times).

Inputs — references to previous transaction outputs being spent. Each input specifies a txid, output index (vout), and a signature script proving authorization to spend.

Outputs — new UTXOs being created. Each output specifies an amount and a script defining the spending conditions (usually derived from the recipient's address).

Locktime — the earliest block height or timestamp at which the transaction can be mined. Zero means no lock.

The decoderawtransaction command breaks any transaction hex into these components, which is invaluable for debugging and verification.

Creating a Raw Transaction

The workflow for building a raw transaction:

1. Identify your inputs using listunspent — note the txid and vout of each UTXO you want to spend.

2. Calculate your outputs — recipient amount, change amount, and fee. The fee is implicit: it's the difference between total input value and total output value. Get this wrong and you'll overpay in fees or have your transaction rejected.

3. Call createrawtransaction with your inputs and outputs. This returns the unsigned transaction hex.

4. Sign with signrawtransactionwithwallet (wallet keys) or signrawtransactionwithkey (explicit private keys).

5. Verify with decoderawtransaction and testmempoolaccept.

6. Broadcast with sendrawtransaction.

Signing and Verification

signrawtransactionwithwallet signs a raw transaction using keys stored in the wallet. For each input, the wallet looks up the corresponding private key and produces the appropriate signature.

The result includes a complete field — if true, all inputs are signed and the transaction is ready to broadcast. If false, some inputs couldn't be signed (perhaps the keys aren't in this wallet), and you'll need to continue signing with other keys or on other machines.

signrawtransactionwithkey is the standalone version — you provide the private keys directly. This is used in applications that manage keys outside of Bitcoin Core.

Always decode and verify the signed transaction before broadcasting. Check that the outputs match your intent and the fee is reasonable.

Common Pitfalls

Fee calculation errors — the most dangerous mistake. If you forget a change output, the entire difference between inputs and outputs goes to the miner as a fee. Double-check your math before signing.

Spending unconfirmed outputs — you can chain transactions by spending unconfirmed UTXOs, but be aware that if the parent transaction gets dropped or replaced, all child transactions become invalid.

Dust outputs — Bitcoin Core rejects transactions with outputs below the dust threshold (currently 546 satoshis for P2PKH). Your application should handle this minimum.

Insufficient inputs — createrawtransaction doesn't validate that your inputs have enough value to cover the outputs. That check only happens when you try to broadcast.

RBF signaling — if you want the option to bump fees later, set the sequence number on at least one input to less than 0xfffffffe.

Related RPC Commands

createrawtransactionCreate a transaction spending the given inputs and creating new outputs. Returns hex-encoded raw transaction.decoderawtransactionReturn a JSON object representing the serialized, hex-encoded transaction.signrawtransactionwithkeySign inputs for raw transaction (serialized, hex-encoded) using given private keys.signrawtransactionwithwalletSign inputs for raw transaction (serialized, hex-encoded) using wallet keys.sendrawtransactionSubmit a raw transaction (serialized, hex-encoded) to local node and network.decodescriptDecode a hex-encoded script.getrawtransactionReturn the raw transaction data. By default returns hex. Use verbose for JSON.combinerawtransactionCombine multiple partially signed transactions into one transaction.
← Previous Guide
Bitcoin Mempool Monitoring and Analysis
Next Guide →
Setting Up Multisig Wallets with Bitcoin Core

bitcoind.app — Bitcoin Core RPC Reference

Contact ↗