PSBT
A PSBT, or partially signed Bitcoin transaction, carries an unsigned transaction and its signing data between wallets. Learn its BIP 174 format.
By Dimitar Zurnov · Updated 4 Nov 2026
Adapted from Learn Me a Bitcoin by Greg Walker.
A PSBT, or partially signed Bitcoin transaction, packages an unsigned transaction with the extra information each signer needs to sign it. Wallets and devices pass PSBTs back and forth until every input has its signatures. The format is defined in BIP 174, with a second version in BIP 370. A PSBT never contains a private key.
Why does a signer need more than the transaction?
An unsigned transaction holds the inputs and outputs, but not everything a signature depends on. To sign a SegWit input, a signer needs the amount and the locking script of the output being spent. Those details live in the earlier transaction that created the output, not in the transaction that spends it.
A wallet connected to the internet can fetch them. An offline signer, such as a hardware device or a cold wallet, cannot. For SegWit inputs the amount is part of what the signature covers, so a signer that cannot see it cannot sign correctly.
A PSBT solves this by carrying the missing details with the transaction. That lets an offline device sign, and it lets two wallets from different software work on the same transaction.
What is inside a PSBT?
A PSBT is a sequence of key-value pairs, grouped into maps. It can be stored as a binary file or encoded as base64 text, and both forms hold the same data.
The structure has four parts, in this order:
- Header. The five bytes
70736274ff: the ASCII letterspsbt, then a separator byteff. - Global map. Exactly one. It holds information about the whole transaction.
- Input maps. One for each input in the transaction, in the same order.
- Output maps. One for each output, in the same order.
A map is a list of entries, and it ends with a single 00 byte. A map with nothing to say is just that 00 byte.
Each entry has four fields:
| Field | Size | Meaning |
|---|---|---|
| Key length | compact size | the size of the key type and key data that follow |
| Key type | 1 byte, usually | which kind of data this entry holds |
| Key data | optional | extra information, such as a public key, that makes the key unique |
| Value length | compact size | the size of the value |
| Value | variable | the data itself |
Key lengths and value lengths use compact size numbers, so short fields take one byte. A key type is a number, and the same number can mean different things in different maps. Key type 0x00 in the global map is the unsigned transaction, while key type 0x00 in an input map is the previous transaction.
What does a real PSBT contain?
The BIP 174 test vectors include a valid PSBT with one P2PKH input, and both of its output maps are empty. Its first bytes show the structure in practice. The diagram below walks through them:
- Global map. Key
00holds the unsigned transaction, which is 117 bytes. It has version 2, one input and two outputs, of 99,999,699 and 100,000,000 satoshis. The inputs have empty unlocking scripts, because nothing is signed yet. - Input map. Key
00holds the full previous transaction, which is 421 bytes. Its ID matches the outpoint the input spends, so a signer can check the amount it is about to sign for. - Output maps. Two maps, both empty, so each contains only the
00terminator.
The test vector is a good example to decode yourself. Its base64 form begins cHNidP8, because that is the base64 encoding of the header bytes. Every PSBT in base64 starts that way.
How do PSBTs move between parties?
A PSBT passes through several roles. Each role adds one kind of information, and a single device or wallet often plays more than one.
- Creator. Builds the unsigned transaction and starts the PSBT.
- Constructor. Adds inputs and outputs before signing. This role exists only in version 2.
- Updater. Adds the data a signer needs, such as the previous transaction, the scripts and the key paths.
- Signer. Checks the transaction and adds its partial signatures. This is the step a hardware device performs, usually offline.
- Input Finalizer. Turns the partial signatures into the final unlocking data for each input.
- Extractor. Builds the finished transaction from the finalized inputs, ready to broadcast.
- Combiner. Merges copies of the same PSBT that different parties have signed in parallel.
A signer should always check the outputs, amounts and fee before it signs, because the PSBT is only as trustworthy as the wallet that made it.
Using Bitcoin Core
Bitcoin Core has RPC commands for each role. The PSBT guide in its repository lists them:
walletcreatefundedpsbtcreates a PSBT, adds inputs and change, and fills in the data it knows.walletprocesspsbtfills in more data and signs the inputs its keys can sign.combinepsbtmerges copies that different signers have processed.finalizepsbtfinalizes the inputs and, if all are complete, returns the signed transaction.decodepsbtprints a PSBT in readable form, which is useful for checking one before you sign it.
Bitcoin Core 32.0 and later read and create version 2 PSBTs. Its createpsbt, walletcreatefundedpsbt, converttopsbt and psbtbumpfee RPCs create version 2 by default, and their psbt_version argument picks another version. Releases before 32.0 reject version 2 PSBTs.
Which key types exist?
Every entry has a key type. BIP 174 defines the version 0 types below.
| Map | Type | Name | Holds |
|---|---|---|---|
| Global | 0x00 |
Unsigned transaction | the transaction, with empty scripts |
| Global | 0x01 |
Extended public key | an xpub and its derivation path |
| Global | 0xFB |
Version | the PSBT version number |
| Input | 0x00 |
Non-witness UTXO | the full previous transaction |
| Input | 0x01 |
Witness UTXO | the amount and script of the output spent |
| Input | 0x02 |
Partial signature | a signature and the public key it belongs to |
| Input | 0x03 |
Sighash type | the signature hash type the signer must use |
| Input | 0x04 |
Redeem script | the script behind a P2SH lock |
| Input | 0x05 |
Witness script | the script behind a P2WSH lock |
| Input | 0x06 |
BIP 32 derivation | the key path, so a device knows which key to use |
| Input | 0x07 |
Final scriptSig | the finished unlocking script |
| Input | 0x08 |
Final scriptWitness | the finished witness |
| Output | 0x00 |
Redeem script | the script behind a P2SH output |
| Output | 0x01 |
Witness script | the script behind a P2WSH output |
| Output | 0x02 |
BIP 32 derivation | the key path of the output's key, often a change output |
A simple wallet only needs a handful of these. For a P2PKH input, the unsigned transaction, the previous transaction, partial signatures and the final scriptSig are enough. The derivation paths are optional, but they help a device recognize its own outputs.
Version 0 also has input types 0x0a to 0x0d, which carry the preimages of hashes for scripts that check a hash. Type 0xFC in any map holds proprietary data that a wallet defines for itself.
What changed in version 2?
Version 0 stores the whole unsigned transaction in the global map. That makes it hard to add or remove inputs and outputs after the PSBT is made, because the whole transaction would have to be rebuilt.
BIP 370 defines version 2. It splits the transaction into separate fields, so each part can change on its own. Version 2 is marked by the global key 0xFB with the value 2, and it adds these keys:
| Scope | Type | Name | Holds |
|---|---|---|---|
| Global | 0x02 |
Transaction version | the transaction version number |
| Global | 0x03 |
Fallback locktime | the locktime used when no input sets one |
| Global | 0x04 |
Input count | how many inputs the transaction has |
| Global | 0x05 |
Output count | how many outputs the transaction has |
| Global | 0x06 |
Transaction modifiable | whether inputs or outputs may still be added |
| Input | 0x0e |
Previous TXID | the transaction holding the output being spent |
| Input | 0x0f |
Output index | which output of that transaction is spent |
| Input | 0x10 |
Sequence | the sequence number for the input |
| Input | 0x11 |
Required time locktime | a time the transaction must wait for |
| Input | 0x12 |
Required height locktime | a height the transaction must wait for |
| Output | 0x03 |
Amount | the value of the output |
| Output | 0x04 |
Script | the locking script of the output |
Version 2 also adds the Constructor role, which lets a party add inputs and outputs before anyone signs. The transaction's locktime is worked out from the inputs' required locktimes, or from the fallback locktime when no input sets one. The two versions are not compatible, so a parser must read the version first.
Version 1 is skipped. People already called the original format version 1, so BIP 370 numbers the new one 2 to avoid confusion.
How do you keep a PSBT safe?
A PSBT does not contain private keys, but it does reveal a lot. It can include extended public keys and derivation paths, which let anyone who has them see every address derived from them. Share a PSBT only with the parties who need it.
Before you sign, check three things on the signing device itself: the destination of each output, the amount, and the fee. The device is the last point where a mistake can be caught, because the signature is final once it is made. The fee page explains how to work out the fee from the inputs and outputs.
How did PSBTs begin?
Pieter Wuille suggested a standard format for unsigned transactions, and Ava Chow designed the format and wrote BIP 174. BIP 174 was assigned in 2017, and Bitcoin Core added PSBT RPCs in version 0.17. BIP 370 was assigned in 2021 and added version 2.
For a broader look at how PSBTs are used, Bitcoin Optech's PSBT topic collects the common workflows and the tools that support them. The input and output pages explain the fields a PSBT carries for each. The next section, Script, covers the locks that outputs carry.
Sources
- BIP 174: Partially Signed Bitcoin Transaction Format defines the format, the roles and the version 0 key types.
- BIP 370: PSBT Version 2 defines version 2 and its key types.
- Bitcoin Core PSBT guide lists the RPC commands for each role.
- Bitcoin Core 32.0 release notes make version 2 the default for PSBT creation.
- Bitcoin Core 32.0 source sets the highest PSBT version it reads to 2.
In this section: Transactions
Something look wrong? Tell us