Bitcoin Script Explained: The Language Behind Transactions
An introduction to Bitcoin Script, the stack-based language behind transactions, and common types like P2PKH and P2SH.
Bitcoin Script is the simple, stack-based programming language that defines the conditions under which a Bitcoin transaction output can be spent, evaluating a series of operations to a final true-or-false result rather than supporting general-purpose computation.
Why Bitcoin has a scripting language at all
Every Bitcoin transaction output includes a "locking script" specifying the conditions required to spend it, and every transaction input that spends that output must supply an "unlocking script" satisfying those conditions. This locking-and-unlocking pair is what makes Bitcoin programmable at a basic level: rather than hard-coding "only this specific public key can spend this," Bitcoin allows a range of possible conditions, from simple single-signature requirements to more complex multi-party or time-based arrangements.
Script is intentionally limited compared to general-purpose programming languages. It has no loops and cannot run indefinitely, which is a deliberate design choice: it guarantees that every node validating a transaction can evaluate its scripts in a small, predictable amount of time, avoiding the kind of unbounded computation problems that programmable smart contract platforms (see /blog/what-is-defi for how those work) have to solve with mechanisms like gas metering (see /glossary/gas).
How the stack-based model works
Script operates on a simple stack, a data structure where you can only add ("push") or remove ("pop") items from the top. A script consists of a sequence of operations (called "opcodes") that push data onto the stack, perform operations on it (like hashing or checking a signature), and ultimately leave either a "true" or "false" result. If the final result is true, the spending attempt is valid; if false, the transaction is rejected.
For example, a very basic locking script might push a public key hash onto the stack, and the corresponding unlocking script would provide a signature and public key. The combined script checks that the supplied public key hashes to the expected value and that the signature is valid for that public key — only then does the script evaluate to true.
Common script types
Pay-to-Public-Key-Hash (P2PKH)
The most historically common script type, P2PKH locks funds to the hash of a public key (this is what produces a standard Bitcoin address). Spending requires providing the actual public key and a valid signature matching it. This is the simplest and most widely understood Bitcoin script pattern, corresponding to legacy addresses starting with "1," as discussed in /blog/segwit-explained.
Pay-to-Script-Hash (P2SH)
P2SH generalizes the idea: instead of locking funds to a public key hash, it locks funds to the hash of an arbitrary script. The actual script (called the "redeem script") is only revealed when the funds are spent, not when they're received. This allows more complex spending conditions — like multi-signature requirements — without burdening every participant in the transaction with needing to know the full script details up front. P2SH addresses conventionally start with "3."
Multi-signature scripts
A common use of P2SH is multi-signature ("multisig") arrangements, where spending requires a certain number of signatures out of a larger set of possible signers — for example, a 2-of-3 arrangement where any two of three designated keys must sign. This is widely used for shared custody, business treasuries, and security setups that don't want to rely on a single point of failure, an important consideration covered more broadly in our /blog/defi-wallet-security guide.
Pay-to-Witness-Public-Key-Hash and Taproot outputs
SegWit and Taproot introduced newer script and output structures — described in detail in /blog/segwit-explained and /blog/taproot-upgrade-explained — that build on the same underlying script evaluation model but restructure how signature data is stored and, in Taproot's case, how complex conditions can be hidden until they're actually used.
Comparing common script types
| Script type | Address prefix | Typical use case | Reveals full condition upfront? |
|---|---|---|---|
| P2PKH | "1" | Simple single-key spend | Yes |
| P2SH | "3" | Multisig, complex conditions | No, only at spend time |
| Native SegWit (P2WPKH/P2WSH) | "bc1q" | Cheaper equivalents of above | Depends on script type |
| Taproot (P2TR) | "bc1p" | Simple and complex, indistinguishable | No, minimal reveal even at spend time |
What Script deliberately cannot do
Bitcoin Script has no loop constructs and limited arithmetic, and script execution is capped to prevent excessive computation. This is a deliberate trade-off: Bitcoin prioritizes predictable, lightweight validation across a fully decentralized network of nodes over expressive, Turing-complete programmability. Platforms designed for general-purpose smart contracts, discussed in /blog/what-is-defi and compared across chains in /blog/layer1-blockchains-compared, take a different approach, accepting more complex validation in exchange for far greater programmability — each design reflects different priorities rather than one being simply "better."
Why this matters for everyday users
Most people never need to write or read raw Bitcoin Script directly — wallets construct standard scripts automatically. But understanding that a Bitcoin address is really a compact representation of a locking script (with different prefixes signaling different script types) helps explain why certain addresses are cheaper to use, why multisig setups look the way they do, and why Bitcoin's programmability, while limited compared to smart-contract platforms, is still meaningfully flexible for its intended purpose as a settlement network.
Bottom line
Bitcoin Script is a deliberately simple, stack-based language that evaluates spending conditions to a true or false result, underlying every address type from basic single-key payments to multi-signature and Taproot outputs. Its limitations are intentional, trading general-purpose computation for predictable, efficient validation across a decentralized network — a foundational design choice that shapes much of how Bitcoin transactions, fees, and addresses work in practice.
Related articles
This article is for educational purposes only and is not financial advice. DeFi involves significant risk, including total loss of funds. Always do your own research.