Bitcoin QR codes — addresses, BIP-21 URIs, and printed wallets
A bitcoin qr code encodes either a wallet address or a BIP-21 payment URI. Here's what each does, what wallets accept, and the print rules that actually matter.
A bitcoin qr code is one of two things and the difference matters more than most generators admit. Either it encodes a bare wallet address — bc1q... for a SegWit address or 1.../3... for a legacy one — and the receiving wallet has to figure out everything else from context, or it encodes a BIP-21 payment URI that pre-fills the amount, the label, and an optional message into the sender's wallet before they confirm. Both are valid. Both scan. Both fail in different ways when you get the print wrong, and the failure mode for a wallet QR is the unforgiving one — one swapped character on a printed receive address and the funds land somewhere that probably nobody owns.
This post covers what each QR encodes, what BIP-21 actually contains, how hardware wallets read these codes differently from phones, why error correction level isn't a stylistic choice when funds are involved, and the small set of decisions that separate a bitcoin qr code people scan happily from one that quietly costs someone real money.
A bitcoin qr code is either an address or a BIP-21 URI
There's no third option. Every Bitcoin payment QR you've ever scanned encodes one of those two formats. Knowing which one you're producing — and which one the sender's wallet is going to read — is the first decision, and the rest of the design follows from it.
The bare-address QR is the older format. The encoded string is just the address: bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq and nothing else. Every wallet on earth reads this — there's no parser to fail, no fields to misinterpret. The sender's wallet asks them to type the amount in manually. That's fine for "send me whatever you owe" but the receiver loses control over the amount, the reference, and any way to flag a specific invoice. It's also the format every cold-storage paper wallet uses, because a bare address is the smallest payload you can encode and it survives years of wallet-app updates without anyone needing to extend the format.
The BIP-21 URI is the modern format. The encoded string is a URI with the scheme bitcoin: followed by the address, an optional query string, and a defined set of parameters. The minimum:
bitcoin:bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq
That's just the address wrapped in the scheme, equivalent to the bare-address QR for any wallet that ignores the prefix. With parameters you start describing the payment:
bitcoin:bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq?amount=0.0025&label=Acme%20Ltd&message=Invoice%20117
That single string pre-fills four things in the sender's wallet — the address, 0.0025 BTC as the amount, "Acme Ltd" as the recipient label, and "Invoice 117" as the message attached to the outgoing transaction. The sender taps once to confirm. No typing, no transcription, no chance of a fat-fingered amount. The structure follows the same logic as the SEPA EPC and UPI payment-QR formats covered in the invoicing-QR post — one structured string the receiving app parses into a pre-filled transfer — except the rail underneath is Bitcoin instead of a bank network.
The four parameters defined by BIP-21 are amount, label, message, and any vendor-prefixed extension starting with req- (required) or any other name (optional). The lightning= parameter is a more recent convention — not formally in BIP-21 but supported by most modern wallets — used to attach a Lightning invoice alongside the on-chain address so the sender can pick the rail at confirmation time.
What wallets actually read
BIP-21 has been around since 2012. Every major Bitcoin wallet released after 2014 reads the format. The list isn't even close to exhaustive: Electrum, Sparrow, BlueWallet, Muun, Wasabi, Phoenix, Breez, the Trezor Suite, Ledger Live, Coinbase's app, Cash App's bitcoin section, Strike, Blockstream Green, and every full-node wallet pulled from Bitcoin Core's UI. Anything you'd hand to a non-technical recipient already speaks BIP-21.
The behavioural split worth knowing:
Pure on-chain wallets read the amount, label, and message parameters and pre-fill all three. The sender sees a screen with the parsed values and confirms. This is the cleanest BIP-21 experience and it's universal across desktop, mobile, and hardware-wallet companion apps.
Lightning-aware wallets read the same fields plus the lightning= extension. When both an on-chain address and a Lightning invoice are present, the wallet usually defaults to Lightning (lower fees, faster confirmation) and offers a "pay on-chain instead" toggle. Phoenix, Breez, and Muun are aggressive about this. Older wallets ignore the lightning= parameter and use the on-chain address, which is the polite fallback BIP-21 was designed for.
Hardware wallets read the address and show it on the device screen for the user to verify, character by character, against the printed code. The companion app (Ledger Live, Trezor Suite, Specter, Sparrow) parses the BIP-21 fields and constructs the transaction; the device confirms by showing the receiving address and the amount in coarse digits on its small screen. This split — companion app does parsing, device does final verification — is the whole point of a hardware wallet. The QR scan is just an input to the companion app.
Why hardware wallets show addresses character by character
Anyone who has set up a Trezor or a Ledger has watched the device walk through a long Bitcoin address one chunk at a time, asking the user to verify each segment against the address shown on the host computer's screen. That looks tedious. It exists because of one very specific attack: clipboard malware that swaps a copied receiving address for the attacker's, hoping the user doesn't notice the change before they paste-and-send.
The QR scan side has the same exposure. If you scan a printed Bitcoin QR with a phone wallet, the wallet reads the address from the pixels and shows it on screen. If a single character of the printed address has been altered — by a smudge, a sticker overlay, or a deliberately-corrupted print — the address that ends up in the wallet is not the address you intended to send to. There is no way to recover funds sent to a valid but unintended Bitcoin address. The blockchain doesn't care about intent.
Hardware wallets defend against this by showing the receiving address on the device's own screen, segment by segment, and requiring the user to confirm it matches the address shown in the companion app. The QR isn't trusted directly — only the device's own display is. The procedure is annoying. It's also the only defence that works against a fully-compromised host computer, which is the threat model hardware wallets are built for.
The consumer-facing version of the same advice: when scanning any Bitcoin QR for a non-trivial amount, verify at least the first four and last four characters of the address before confirming. Wallets that show the parsed address in a large font make this easier; wallets that hide the address behind a "confirm and send" button make it harder. Use a wallet that respects the verification step. Sparrow, Electrum, and BlueWallet all do this well; some custodial mobile apps do it less obviously.
Error correction is where most printed wallet QRs go wrong
QR codes have four error-correction levels — L (7%), M (15%), Q (25%), and H (30%). The numbers describe how much of the QR can be damaged or missing before the decoder can no longer recover the data. For a marketing QR pointing at a URL, level L is fine — a misread character changes nothing because the QR is regenerated next quarter and the URL is a redirect you control. The full trade-off is in the QR error correction levels breakdown.
For a printed Bitcoin address QR, the calculus is brutally different. A misread character doesn't change a URL — it changes the destination address. Bitcoin addresses are checksummed (legacy P2PKH and P2SH use a four-byte SHA-256d checksum; bech32 SegWit uses a BCH error-detecting code), and any wallet worth using will refuse to accept an address with an invalid checksum. That's the floor of safety. But a single-character flip in the right position can produce a different valid address — one with a valid checksum that belongs to nobody, or worse, to an attacker who pre-computed the collision. Bech32 was designed specifically to reduce this risk versus the older base58check format, but no encoding eliminates it entirely.
The rule that prevents the failure: print receive-address QRs at error correction level H (30%), full stop. The QR gets larger; you accept that. The probability of a printed code surviving years of UV, smudging, fold-line damage, and casual wear without producing a misread is the only number that matters. Level H absorbs single-module damage in three out of four positions and gives the wallet's checksum a chance to catch what error correction couldn't.
A second rule: never resize a printed Bitcoin QR after generation. Generate it at the size you'll print it, with the pixel grid aligned to whole pixels at the print resolution. Up-scaling a small SVG to a large printed sticker preserves the grid; bitmap up-scaling a 200px PNG to a 5cm-wide print introduces sub-pixel interpolation and can soften the module boundaries enough to push borderline reads over the edge. Print straight from the SVG.
On-screen wallet QRs vs printed wallet QRs
The two QRs serve different jobs and the design rules diverge.
On-screen receive codes are generated by the wallet on demand, live for thirty seconds while the sender scans, and are then discarded. The wallet generates a new address for each request (every modern wallet is HD — hierarchical deterministic — so new addresses are free) and bakes the amount and label into the QR as BIP-21. Error correction L or M is fine because the QR is on a glowing screen with perfect contrast and zero wear, scanned at arm's length within seconds. The screen brightness fights any ambient-light issues. Most wallets ship this at level L by default because the smaller QR is faster to render and the surface is forgiving.
Printed receive codes are the opposite. A printed donation QR on a flyer, a cold-storage paper wallet folded in a safety-deposit box, a sticker on the back of a laptop for "send me a few sats" — these QRs live for months or years, on substrates that wear, scanned by phones held at unpredictable distances under unpredictable light. Error correction must be H, the QR must be printed at a size that gives every module at least 4 pixels of resolution at the scanning phone's likely distance (so 2cm minimum for arm's-length close scans, 5cm or more for desk-distance scans), and the address inside must be one you've committed to receiving on for the life of the printed code.
That last constraint is the one that surprises people. HD wallets generate a fresh receive address every time you ask, partly for privacy (a single address with all your incoming payments reveals more about your wallet than separate addresses do) and partly because the protocol makes it free. If you print one address and use it as your only receive address for two years, every payment to that address is publicly correlated on the blockchain. Some donation pages and tip jars accept this trade-off; cold storage accepts it because the alternative — printing a new paper wallet every month — defeats the point of cold storage. The right answer depends on whether the use case values privacy or longevity more. The static vs dynamic QR-code trade-off maps the same decision for marketing QRs, and the logic carries over.
Build a BIP-21 URI
A working preview. Type the address, amount, and label, and the encoded string updates in real time. Paste the result into any QR generator. State saves locally — refresh the page and your last build comes back.
The output is the literal text a wallet reads. Drop it into the Bitcoin QR code generator to produce the actual code, or paste it into any generic QR tool — BIP-21 is plain text and any QR library encodes it correctly.
On-chain vs Lightning QRs
Lightning Network invoices encode differently. A Lightning invoice is a string starting with lnbc (mainnet) or lntb (testnet) followed by a base32-encoded bolt11 payload — amount, payment hash, route hints, and the recipient's signature. Lightning invoices are single-use, expire on a timeout (usually 60 minutes), and can't be reused for a second payment. A QR encoding a Lightning invoice is therefore a one-shot artefact, generated fresh per payment request, scanned within minutes, and discarded.
Lightning invoices are much shorter on average than an on-chain receive address with BIP-21 amount and label, which means they fit cleanly into a QR at error correction H without bloating the module count. They're not interchangeable with on-chain addresses — a Lightning-enabled wallet reads lnbc... and routes the payment over Lightning channels; an on-chain-only wallet sees lnbc... as gibberish and refuses to send.
The pattern most modern wallets settle on is the BIP-21 unified format: a single QR that contains both the on-chain address and a Lightning invoice, separated by the lightning= parameter. The sender's wallet picks the rail — Lightning for small fast payments, on-chain for large or cold-storage destinations — and the receiver doesn't have to know in advance which the sender will choose. The format is the de-facto standard but isn't formally in BIP-21 yet; a proposal called BIP-353 covers a more structured version using DNS payment instructions, but in practice the lightning= query parameter is what's deployed today.
The trade-off worth knowing: a unified QR is bigger than either format alone, so at the same printed size it has more, smaller modules. At small print sizes (under 2cm), unified QRs start hitting decode limits on lower-end phone cameras. For posters and tip jars where size isn't a constraint, unified works. For tiny printed stickers (laptop lid, name badge), pick one rail and stick to it.
The Bitcoin/Lightning split is the cleanest case of "one chain, two rails on the same QR." Stepping outside Bitcoin entirely is a different conversation — Ethereum and the EVM-compatible chains use a separate URI scheme called EIP-681, where the URI carries an explicit chain ID for Mainnet vs Optimism vs Polygon vs Base, and the same address can mean different things on different chains. None of that BIP-21 logic carries; the companion piece on Ethereum QR codes and EIP-681 walks through what changes when the rail underneath isn't Bitcoin at all.
Common mistakes worth not making
A handful of patterns that show up in the wild:
- Using a shortened URL instead of a bitcoin: URI. A QR encoding
https://bit.ly/sendtoacmeredirects to a web page that displays the address. The web page is a server you have to keep running, and a phone wallet that scans the redirect URL won't open the Bitcoin app — the camera opens the URL in a browser and the user copies the address by hand. Always encode thebitcoin:URI directly into the QR pixels. - Encoding an address that doesn't match the wallet you control. Sounds obvious; happens more than people admit. Generate the address from the wallet that will receive the payment, in the live network (mainnet, not testnet — confusingly the test-network addresses look almost identical). Send a small amount to test before publishing.
- Reusing the same address forever on a printed donation card. Privacy disappears completely — anyone watching the blockchain can see every donation and the running balance. The right call depends on the use case. For a transparent public charity, address reuse is fine and arguably preferred. For a personal tip jar, generate a new address every quarter and reprint the card. Most printed-wallet failures fall into one of the six fixes for QR codes that won't scan — most of them apply to wallet QRs verbatim.
- Skipping the verbal instruction next to the printed QR. "Scan with your Bitcoin wallet" or "Open your wallet, scan to send" printed near the QR catches the case where the recipient's phone camera doesn't recognise the
bitcoin:scheme. iOS and modern Android show a "Open in Bitcoin app" prompt when a known wallet is installed; without one installed, the user sees raw text in a notification and gives up. A two-word instruction doubles the success rate. The conversion-focused argument for clear scan instructions applies just as strongly here as in QR codes at trade-show booths — the user has a phone in their hand and three seconds of attention. - Printing at low error correction to keep the QR small. Already covered. Use H. Accept the size.
Generating Bitcoin QRs at scale? Linked.Codes outputs BIP-21 URIs with error correction defaults set for on-screen vs printed contexts, and the receiving address belongs to your wallet — we never see it.
Open the generatorSecurity context — the trust signal a Bitcoin QR can't provide
Worth being honest. A Bitcoin QR scanned in public has the same risks as any other QR scanned in public, plus one: Bitcoin transactions are irreversible. The wider risk surface — overlay stickers, lookalike URLs, the surface borrowing trust from a brand — is covered in the consumer-side guide to whether QR codes are safe to scan. For Bitcoin QRs specifically, the answer to "what if the QR is a sticker pasted over the legitimate one" is "the sender's funds go to the attacker's address, and there is no chargeback." The defence is the same as for any QR scan: read the address in the wallet's confirmation screen, verify it matches the address printed in human-readable text next to the QR (every well-designed Bitcoin donation page prints the address in plain text alongside the QR for exactly this reason), and reject the scan if the two don't match.
Hardware wallets close the last gap by showing the address on the device's own screen — the one display in the chain that a host-computer-resident attacker can't substitute. That's why hardware wallets exist and why the address-verification step is non-skippable on every reasonable device.
What we'd ship by default
For an on-screen receive code in a wallet app: BIP-21 URI with address, amount, and label. Error correction L or M. Regenerated per request. Standard, boring, and what every wallet already does.
For a printed donation card or tip jar: BIP-21 URI with address and label (no amount, so the sender picks). Error correction H. Printed at 4cm minimum so module size survives arm's-length scans. Address printed in plain text alongside for verification. Plan to rotate the address every six to twelve months by reprinting the card.
For a cold-storage paper wallet: bare address (no BIP-21 wrapper, for maximum wallet compatibility across the decades the paper might survive). Error correction H. Printed and laminated. Stored offline. Never reused for hot transactions. This is the most conservative format and it should be — the paper is the only record of the address, and the funds it holds may be untouched for years.
For a Lightning-only point-of-sale invoice: bolt11 invoice as a one-shot QR on the merchant's terminal screen. Error correction M. Expires per invoice. No reuse.
For a unified on-chain + Lightning donation page: BIP-21 URI with lightning= parameter. Error correction H. Printed at 5cm minimum because the unified format produces a denser QR. Worth the size when the receiving party wants to accept either rail without negotiation.
The infrastructure side — keeping the printed-QR link to your actual wallet safe across years, separate from the address itself — is its own discipline. The QR codes documentation covers the platform-level options for hosting receive pages, and the broader case for running your printed QRs on a domain you control applies to Bitcoin receive surfaces just as much as it does to marketing links — a printed QR pointing at your-domain.example/donate (which displays the BIP-21 URI for one-tap scanning) lets you rotate the underlying address without reprinting, at the cost of one extra hop the sender's wallet has to follow. For most use cases that hop is fine; for cold storage it's the wrong trade-off and the QR should encode the address directly.
What happens if the QR scans wrong on a printed Bitcoin address?
Most of the time the wallet refuses to accept the address because its checksum doesn't validate — Bitcoin addresses are checksummed (SHA-256d for legacy, BCH for bech32 SegWit) and any wallet worth using rejects an invalid checksum before letting you send. The edge case is a single-character misread that happens to produce a different valid checksummed address. That address almost certainly belongs to nobody, but funds sent to it are unrecoverable. Printing at error correction H plus verifying the first and last four address characters against printed plain text closes the realistic risk window.
Why do hardware wallets show addresses one segment at a time?
To defend against clipboard-swapping malware on the host computer. The companion app (Ledger Live, Trezor Suite, Sparrow) shows the address you intend to send to; the device shows the address it is actually about to sign for; the user confirms the two match before approving. The segment-by-segment display is the user-interface concession to a small screen that has to render a 42-character bech32 address legibly. The annoyance is the security.
Do all wallets read BIP-21 URIs?
Every major wallet released since around 2014 reads BIP-21. The behavioural variation is in which optional fields they parse — amount, label, message are universal; the lightning= unified extension is supported by most Lightning-aware wallets (Phoenix, Breez, Muun) and ignored gracefully by on-chain-only wallets, which fall back to the address. The exception worth flagging is custodial exchanges' built-in QR scanners — some parse only the address and silently drop the amount and label. Test with the recipient's actual wallet before relying on the parsed fields.
Can I print a permanent Bitcoin receive QR for a website or donation card?
Technically yes — print a single address with error correction H, and every donation to that address routes to your wallet for as long as you control the keys. The trade-off is privacy: every donation is publicly correlated on the blockchain because they all land at the same address, and a watcher can see your running balance. HD wallets are designed to generate a fresh address per request specifically to avoid this. The right answer depends on whether the use case prioritises privacy or print-once longevity. Transparent public charities can use one address forever; personal tip jars usually rotate.
Lightning QRs vs on-chain QRs — when does each make sense?
Lightning for small fast payments — coffee, tips, sub-dollar amounts — where the on-chain fee would exceed the payment itself and the few-second settlement matters. On-chain for amounts over a few hundred dollars, for any payment going to cold storage, or for any recipient who hasn't opened Lightning channels with sufficient inbound liquidity. The unified BIP-21 + lightning= format lets you offer both rails on one QR and let the sender pick — that's the right default for most public donation surfaces in 2026.
Is encoding a bitcoin: URI safe to do in any QR generator?
The encoding itself is. The QR encodes the literal text of the URI and any QR library produces the correct pixels for that text. What matters is whether the address inside is one you control — the QR generator has no way to know, and a careless paste from a wallet showing a testnet address (which looks almost identical to mainnet) produces a perfectly-valid QR that sends real funds to an address you can't access. Generate the address from the receiving wallet, on the live network, and send a small test amount before publishing.
Does a Bitcoin QR work without internet?
The scan itself does — the QR encodes the address and BIP-21 fields directly, no server lookup needed. Constructing and broadcasting the transaction does need internet (to fetch UTXOs, calculate fees, and send the signed transaction to the network), so the sender needs connectivity at the moment of payment. The receiver doesn't need internet to display the QR, which is why paper cold storage works — the address sits on paper, offline, until the day someone scans it and sends from a connected wallet.
Sourcesshow citations
- BIP-21 — URI Scheme (Bitcoin Improvement Proposal 21, the canonical specification): https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki
- ISO/IEC 18004:2024 — QR code bar code symbology specification (error correction levels L/M/Q/H defined): https://www.iso.org/standard/83389.html
- Bitcoin Core developer documentation — Transactions and Payment Processing: https://developer.bitcoin.org/devguide/payment_processing.html
- Electrum documentation — receiving payments and BIP-21 handling: https://electrum.readthedocs.io/en/latest/
- Sparrow Wallet documentation — receive addresses, hardware wallet verification, BIP-21 unified payment requests: https://sparrowwallet.com/docs/
- Trezor Knowledge Base — Verify a receiving address on your Trezor device: https://trezor.io/learn/a/how-to-verify-a-receiving-address-on-trezor
- Wikipedia — QR code (format, error correction, ISO reference): https://en.wikipedia.org/wiki/QR_code
- BOLT 11 — Lightning invoice format specification: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
Try it on your own domain
Branded short links and dynamic QR codes, on your subdomain or your own domain. One-time purchase, no per-click fees.