Sometimes, you see someone here asking for test bitcoins to try out some features. Often, the suggestion is made to use regtest instead of the test network. But what exactly is regtest and how do you make it work? That’s why I’m throwing together this guide to help you get started from the ground up.
About this guide:
This write-up is based on how I got regtest up and running. I’m not saying this is the only way or the best way, so feel free to use it as a base for your own experiments!
My setup:
This was written with the following:
Bitcoin Core v0.20.1
Python 3.8.2
bitcoinrpc library v1.0
The basics: What is regtest?
Basically, regtest is a Bitcoin blockchain that you create entirely by yourself but still follows all the rules of the Bitcoin network. The network's difficulty is set at the lowest possible level, so you can mine as many blocks as you want, giving you all the bitcoins you need.
Just keep in mind that regtest is your personal blockchain, which means you can’t look up transactions in your go-to block explorer like you would on mainnet or testnet. This also means you can play around and start over whenever you want without any issues. Regtest is a fantastic way to experiment without the fear of messing things up it’s really an awesome test environment for most cases.
So if you’re curious about whether this is something you want to try, read on and see for yourself.
Part Two:
In this part we are going to look into setting up the environment to get it ready for doing a transaction at the end. We could do all of this by continuing to use bitcoin-cli commands but instead we are going to do that from within Python-code. That's because I assume you want to setup the regtest environment so you can try-out some programs yourself in the long run.
Start from scratch
So let's dive right in with the python3 code used to initalize the network (I called "mini_inital.py"):
There isn't anything you need to change in the code if you setup the regtest environment as described in part 1. Be sure the settings used in the rpc_connection for port (18444), username (bitcoin), password (talk) match yours. If needed you can set the value of targetChainSize to a different value if you want the chain to consist of more or less blocks. But keep the value > 100 for now.
Check either bitcoind or bitcoin-qt are running in regtest mode, then run the program to get an output like this:
Now the most important thing to realize is that the mining rewards for a block need to be mature, 100 confirmations needed, before they can be spent. So whenever you set up a chain consisting of less than 101 blocks you will not be able to do any transactions at all since there are no coins available to move around.
The output mentions an address used for the mining reward, this address is used for payout in all the mined blocks. You could change that if you want, but that's how I currently set it up. The address itself will be different when you run the program. And finally: the address is available in your regtest wallet after running the program.
So there you have it: a whooping 2500 BTC (50 mature blocks, each with a mining reward of 50 BTC) to play with. You can go play around a bit, try making a transaction from within bitcoin-qt for now:
Confirmation needed
So whenever you do one or more transactions in your regtest environment they will be unconfirmed as long as you don't mine at least an extra block. Since there are no active miners on your private regtest chain you have to take care of that yourself. The good news is that means you also don't have to wait for an average of 10 minutes for a block to get mined.
Whenever you want to mine another block you could run the following program (I called "mini_extra.py"):
Please note: Either set a fixed value in mineAddres (in the above code I set it fixed to the same value as the payout address from before) or comment the line for setting the fixed value and uncomment the line where mineAddress gets the value of a new wallet address. In the last case the extra block will be mined to a new address, which will be available in your wallet but still needs to be matured before it van be used.
When running the program an extra block will be mined. If you want multiple blocks to be mined either run the program a few times in succession or change the value of blocks_to_mine to a value > 1.
Output:
If you would go check the transaction in bitcoin-qt you would see it now has 1 confirmation.
Ending of part two
This concludes the second part where we build a full regtest environment, managed to do a transaction and get it confirmed. In part three we are going to build a raw transaction ourselves.
Part Three:
If you followed part one and two you find yourself with a fully setup regtest environment. You now have anything in place to experiment with whatever crazy idea you come up with. I'm going to keep it straightforward by creating a raw transaction, siging the transaction and finally sending it all from within a python program.
Let's go program stuff
'm going to keep it straightforward by creating a simple python3 script that creates a raw transaction, signing the transaction and finally sending it all from within a python program:
The program looks for a suitable wallet address that has at least 1 unspent BTC. The first one that's found is used for obtaining the input for our transaction. The entire input is spent minus fees (set to a fixed value of 0.00000100 in this example)). The function "make_transaction" takes care of the signing and sending of the transaction and it returns the txid on success). Once again: this is meant as an example of how you can use the regtest environment yourself to programmatically experiment/test. I'm sure you can think of lots of things that are buggy in my example code, that's ok It's all about the concept of regtest not my poor programming skills!
When running the code you should get something like this in return:
And there you go, you just transferred 50 BTC (minus fees) to an address that's not yours or in your wallet. And if you come to regret your action, just start over your environment and start all over again.
As long as you don't mine another block the transaction you just did will stay in the mempool. So be sure to mineat least an extra block to get it confirmed and in your chain.
Ending of part three
So that concludes part 3 where we looked into making a transaction programmatically. The program itself was not to complicated but now that you know the way, knock yourself out! Maybe you want to build your own simple wallet to experiment? Go ahead! Always wanted to try how to set a higher fee for an RBF-enabled transaction? Now you can find out! Well you get the drift, you come up with an idea regtest might be the best environment to start chasing it!
Part 4: Some additional help
Diving in the internals of the regtest chain
One big difference between regtest and testnet/mainnet is you don't have a fancy blockexplorer to use. But that doesn't mean you sometimes need to check or confirm things on the regtest chain. So in order to do just that I use yet another python3 program to get some basic info on the regtest chain and transactions.
Here's the python3 program I used to create a transaction (conveniently named "info.py"):
This is the first program that you can run using using a startup parameter to do different things. I'll introduce them one by one:
Get information on blocks in the chain and the mempool
Running info with the chain argument (or since it's the default without any parameter) will give you general info on the regtest chain including all transaction id's per block and transactions in mempool (if any).
Hint: If you want this info in a text file you could just redirect it, so something like: python3 info.py chain > mychain.text
Only list blocks with user generated blocks
Especially when you are experimenting with transactions you might get lost which blocks contain your own generated transactions and not only coinbase transactions. So when you use the "blocktrans" parameter you can get a list of all blocks containg more than 1 transaction.
List all transactions in mempool
Pretty straightforward, when you use the mempool argument you will get all txid's (if any) currently in the mempool.
Get detailed info on a transaction
If you want detailed information on a transaction either included in a block or in the mempool you can use the argument trans alongside with the txid. If the transaction is found detailed information will be shown.
Final words
I hope this guide has given you a good impression on what regtest is and why it can come in very handy. Especially when you want to experiment with transactions, scripts, and what not this might be a much better starting place then testnet!
Hope you enjoyed this guide and let me know if you have any doubts/concerns/tips, hell maybe even compliments
I appreciate the guide, you even include example code on Python with it's output.
It would be great to write your environment such as version of Bitcoin Core, Python and bitcoinrpc library, since some parts of the guide might become obsolete in future and people who read your guide can make change easier.
Thank you for the research and information, for someone that doesn't have any background of coding, testnet is nice to test any project. Very fast to use and just user friendly too.
I'm confused.
There is a PyPI library today (2025) called bitcoinrpc: https://pypi.org/project/bitcoinrpc/
Its version is 0.7.0
It doens't have an "authproxy" module.
What was this bitcoinrpc used here?
It must be this library: github.com/jgarzik/python-bitcoinrpc
Here's its PyPI library link: pypi.org/project/python-bitcoinrpc
It has authproxy and created before this thread was posted.