CKB Address
An address is a long string of numbers and letters that is used to receive blockchain assets.
Accounts vs. Addresses on CKB
Bitcoin was the first blockchain to separate the concept of accounts from addresses. One account can be associated with multiple addresses, a design intended to improve privacy.
With the rise of Ethereum, many users became accustomed to a different model: one account = one address. Each account corresponds to a single address that is reused across applications. While this simplifies interaction, it also links all activity to the same address, which reduces privacy.
On CKB, the model follows more closely to Bitcoin: one account can be linked to multiple addresses.
Accounts and addresses are independent concepts. An account is derived from a key pair while an address is generated from the underlying Lock Script. Even under the same account, different Lock Scripts produce different addresses.
How CKB Addresses Are Generated
To understand how this model is implemented, we need to look at how a CKB address is constructed. A CKB address is more than a random string — it encodes the underlying Lock Script, adhering to Bitcoin's Bech32m address format (BIP-350). The Lock Script defines how ownership is verified and consists of three fields: code_hash
, hash_type
, and args
. For details on these fields, see Script.
Get Full Payload
To generate a CKB address, the Lock Script is encoded into a byte array, named "payload," which is then wrapped into the final address format.
The Full payload format encodes all data fields of the Lock Script using Bech32m encoding:
payload = 0x00 | code_hash | hash_type | args
Wrap Into Address
The payload is wrapped into an address following Bitcoin Bech32 address format (BIP-173) or Bitcoin bech32m address format (BIP-350), using Bech32/Bech32m encoding and a BCH checksum.
The original Bech32/Bech32m format limits strings to 90 characters. However, we have removed this length restriction, similar to BOLT. For strings longer than 90 characters, the error correction function is disabled to prevent the risk of incorrect corrections, which we do not intend to use.
A Bech32/Bech32m string consists of three parts, with the last 6 characters serving as a checksum:
- Human-readable part: "ckb" for CKB Mainnet and "ckt" for the Testnet
- Separator: always being "1"
- Data part: base32 encoded. The table below provides a translation for Base32 encoding:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
---|---|---|---|---|---|---|---|---|
+0 | q | p | z | r | y | 9 | x | 8 |
+8 | g | f | 2 | t | v | d | w | 0 |
+16 | s | 3 | j | n | 5 | 4 | k | h |
+24 | c | e | 6 | m | u | a | 7 | l |
The flow chart below outlines the process of encoding a Lock Script into a payload by adding a 6-byte BCH, followed by Base32 encoding, and finally a human-readable prefix and checksum are appended.

Example: Generating a Full Address
code_hash to encode: 9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8
hash_type to encode: 01
args to encode: b39bbc0b3673c7d36450bc14cfcdad2d559c6c64
---
full address generated: ckb1qzda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xwsqdnnw7qkdnnclfkg59uzn8umtfd2kwxceqxwquc4