← Back to list

How to Generate Bitcoin Address (bech32 format)

Bitcoin addresses are used to receive and send transactions on the Bitcoin network, that’s not news.

Daniel Adesubomi Oniya · 2023-01-31 13:27 · 9 claps · 4.0 min read
#bitcoin #bech32 #bitcoinjs-lib #typescript #bitcoin-addresses
Open on Medium ↗
Wiki topics: CRY · Crypto & Web3 🌐 · Web Development

How to Generate Bitcoin Address (bech32 format)

Bitcoin addresses are used to receive and send transactions on the Bitcoin network, that’s not news.

To generate an address, you need to have a private key. This private key is converted using cryptographic magic to a public key, and the public key is hashed to produce the address. You can learn more about the relevance of these cryptographic processes from Abubakar.

But then, here is a little backstory;

Initially, Bitcoin addresses were based on a “Pay-to-Pubkey-Hash” (P2PKH) format, which used a public key hash as the address. These addresses began with the number “1.”

Later, a new address format called “Pay-to-Script-Hash” (P2SH) was introduced, which allowed for more complex scripts to be used in transactions. P2SH addresses begin with the number “3.” This format was created to enable the use of multi-signature and other advanced features.

Then, SegWit (short for Segregated Witness) was introduced, which was built on the merits of P2SH addresses. SegWit addresses, which also begin with the number “3”, use a different hash and allow for more efficient use of block space, increased transaction capacity, and malleability fix.

Finally, the Bech32 format was introduced, it’s a new format of SegWit address which has the prefix “bc1” and is more efficient in terms of space and offers error-checking capabilities.

These address formats are all still in use today, but Bech32 is considered the most recommended format, as it offers the most benefits.

In this article, we will demonstrate how to generate a SegWit address in the “Bech32” format using the bitcoinjs-lib and some other libraries that would help us achieve our goal. We are mostly writing TypeScript.

The first step is to install the library by running the following command:

npm i --save bip39 bip32 ecpair tiny-secp256k1 bitcoinjs-lib

Next…

Step 1: Generate a seed phrase

A seed phrase could also be referred to as a mnemonic. A seed phrase is just a set of words that can be rearranged randomly. These words have a range of allowed lengths (i.e. you can only use a seed phrase of a combination of 3, 6, 9, 12, 15, 18, 21, or 24 words). If these words are truly randomly generated, it is statistically impossible to generate identical sets of seed phrases twice.

This seed phrase should be kept safe because whoever has the seed phrase would have access to any address generated from that seed phrase.

Generate a seed phrase with this piece of code:

// imports
const bip39 = require("bip39");

// Step 1: Generate a seed phrase
const mnemonic bip39.generateMnemonic().toString();

Step 2: Convert the seed phrase to an xPub key (extended public key)

At this point, I’ll have to point out that a mnemonic could be used to generate multiple addresses; as many as 4 million. This was brought about by the introduction of the bip32 standard which espoused a set of cryptographic methods to obtain multiple addresses from a single private key via a derivative path (more about that later).

To convert our mnemonic to an xPub key:

// imports
const bip39 = require("bip39");
const ecc = require("tiny-secp256k1");
const { BIP32Factory } = require('bip32')

// Step 1: Generate a seed phrase
const mnemonic bip39.generateMnemonic().toString();

// Step 2: Convert the seed phrase to an xPub key
const seed = await bip39.mnemonicToSeed(mnemonic);
const bip32 = BIP32Factory(ecc);
const masterPrivateKey = bip32.fromSeed(seed, network);

const derivativePath = "m/84'/0'/0'/0";
const xPub = privateKey.derivePath(derivationPath).neutered();

Step 3: Derive “Child Public Key”

This is where the tree begins to diverge.

A derivative path is in the format — m’ / purpose’ / coin_type’ / account’ / change / address_index Marvellous Ibironke did a great job at explaining what derivative path is and how it works here.

From our previous step, you’ll notice that the derivative path is missing the address_index. It is this address_index that we increment to generate as many addresses as we want.

Generating addresses from a derivative path is deterministic (i.e. you’ll obtain the same address every time you generate an address from the same mnemonic and index).

For this example, we will generate a bech32 address at the zero (0) index alone. You can modify your code to generate addresses from other indexes.

// imports
const bip39 = require("bip39");
const ecc = require("tiny-secp256k1");
const {BIP32Factory} = require('bip32');
import {Network} from "ecpair/src/types";

// Step 1: Generate a seed phrase
const mnemonic bip39.generateMnemonic().toString();

// Step 2: Convert the seed phrase to an xPub key
const seed = await bip39.mnemonicToSeed(mnemonic);
const bip32 = BIP32Factory(ecc);
const masterPrivateKey = bip32.fromSeed(seed, network);

const derivativePath = "m/84'/0'/0'/0";
const xPub = privateKey.derivePath(derivationPath).neutered();

// Step 3: Derive "Child Public Key"
const network = Network.regtest;
const index = 0;
const node = bip32.fromBase58(xpub, network);
const childPubKey = node.derivePath(0);

Step 4: Get the Address from Child Public Key

In this final step, we will derive a payment address from the “child public key”. This seems to be the easiest and most straightforward of all.

// imports
const bip39 = require("bip39");
const ecc = require("tiny-secp256k1");
const {BIP32Factory} = require('bip32');
import {Network} from "ecpair/src/types";
import {payments} from "bitcoinjs-lib";

// Step 1: Generate a seed phrase
const mnemonic: string = bip39.generateMnemonic().toString();

// Step 2: Convert the seed phrase to an xPub key
const seed: Buffer = await bip39.mnemonicToSeed(mnemonic);

const bip32: typeof BIP32API = BIP32Factory(ecc);
const masterPrivateKey: BIP32Interface = await bip32.fromSeed(seed, network);
const derivativePath: string = "m/84'/0'/0'/0";
const xPub: BIP32Interface = privateKey.derivePath(derivationPath).neutered();

// Step 3: Derive "Child Public Key"
const network: any = Network.regtest;
const index: number = 0;
const node: BIP32Interface = bip32.fromBase58(xpub, network);
const childPubKey: BIP32Interface = node.derivePath(0);

// Step 4: Get Address from Child Public Key
const paymentAddress: payments.Payment = payments.p2wpkh({
    pubkey: child.publicKey,
    network: network,
});

console.log("  [✔] Address Genereated");
console.log("    Address ["+ index +"] -> "+ paymentAddress.address);

Above is the complete code, with type annotations.

And that’s it! With just a few lines of code, you can now generate SegWit addresses in the “bech32” format using the bitcoinjs-lib library. This can be useful for building Bitcoin-based applications or for testing purposes.

As a final note, it is very important to remember that the mnemonic should be kept secure, as it is needed to spend any funds received on any address associated with it.

There’s so much going on when it comes to Bitcoin, and you can only take it one step at a time. Happy coding 🎉.


메타데이터
post_id
68d5eee51d7c
slug
how-to-generate-bitcoin-address-bech32-format-68d5eee51d7c
url
https://medium.com/@Adesubomi/how-to-generate-bitcoin-address-bech32-format-68d5eee51d7c
canonical_url
https://medium.com/@Adesubomi/how-to-generate-bitcoin-address-bech32-format-68d5eee51d7c
author_url
https://medium.com/@Adesubomi
status
ok
fetched_at
2026-07-26 05:00:11