I'm looking for a simple, easy to use Bitcoin library for Python.

What I want to do is verify I can enter a hex private key that I want, and get the expected pubkey in compressed format, and the 1Btc... address.

I've looked at cryptotools on github which looked promising, and easy to use, but it would not accept a hex value that wasn't a multiple of 2. I know that sounds odd, but I want to be able to enter a hex value like c12 and have it work as expected (unless I have to enter 0c12 and that will work, with the leading zero discarded). I expect than when I enter 0cfa721d that this will be interpreted as big endian.

bitcoinlib looks promising, but I find it confusing and I've tried for a couple of hours but unsure of how to get what I want.

  1. Input private key in hex
  2. Get back pub key in hash160 format, compressed
  3. Get the 1Btc... address as well.

I wonder if this is a strict mathematical relationship. For instance could there be an arbitrary or infinite number of pub keys from the private key? Is there a way to ensure I get the pubkey I want from the private key? I want to test known private keys with the pubkey and BTC address generated that corresponds to known private keys and addresses, so I can try and figure out how whoever generated these addresses from choices of private keys I can try to replicate and do the same thing myself.

Thank you for any help or suggestions.

  • Hi, author of cryptotools here. The reason it wont accept odd digits hex is that it will store the private key inteternally as Python bytes object and the bytes.fromhex method requires full bytes. I'll have a look at it. As a workaround you can simply pad with a zero if it has odd amount of digits.0x0cfa721d is exactly the same as 0xcfa721d. The other functionality is there, just do myprivatekey.to_public().to_address('P2PKH', compressed=True)
    – Mike D
    Commented Nov 18, 2018 at 16:51

2 Answers 2


For this very reduced case, you can take a look at https://github.com/circulosmeos/bitcoin-in-tiny-pieces

It has each operation coded for ease of understanding, isolated in a different file, but they're easy to join or to use directly from command line: for example:

$ echo 0x01 | ./bitcoin-public-from-private.py | ./bitcoin-address-from-public-key.py

And for the question:

For instance could there be an arbitrary or infinite number of pub keys from the private key?

In principle, from a private key only one public key is derived: but this can be coded in three different Bitcoin addresses. Normally only one or two of these formats are used.

This is in the most simple case, not considering more complex cases introduced later in Bitcoin (like HD keys, etc)...

  • Hey thank you! I forked your repository at github.com/jamesyoungdigital/bitcoin-in-tiny-pieces.git to add a new little tool that checks brainwallet address balances. I wasn't having much success with the shell script. It now depends on my fork of pybitcointools.git, which is really easy to use and depends on almost nothing. Hope you might like the little additions! :) Commented Nov 19, 2018 at 13:47
  • Glad it has been useful! As for the shell script just open an issue and I'll take a look: it'd work flawlessly! Commented Nov 19, 2018 at 17:25
  • Star given! I'd like to give a few more but they won't let me, haha. :-) With the shell script, I try like this: ./bitcoin-test-address-balance.sh satoshi but the output is always: ... 2 .... n and as far as I can tell, never ends. The problem seems to be in the address balance python script, lines 62 to 64, when an exception is caught. The URL should use the {} for interpolation. Please see my pull request. Thanks! :-) Commented Nov 19, 2018 at 17:35
  • Hi James, I think that the exception is correctly caught: the thing is that blockchain.info sometimes discard the petition, probably due to high traffic: in that case the script sleeps 1 to n minutes between retries: as it is done for running in batches, this is not considered a problem :-o but thanks for your pull! Commented Nov 20, 2018 at 20:33

I find the Bit module the easiest and most straight forward, albeit a tad, limited but with bit you can simply:

from bit import Key

# To generate private key
privKey= Key()

# Create Ripemd-160 Hash (address)

# or 

myAddress = privKey.address

# Segwit

MySegwitAddress = privKey.segwit_address

You can also import your own existing private keys like so:

# For wif format:
privKey = Key.('L1VotKmtZRLZSnSPhLhQxfts2aqBMru2APTs4Yuc8TYJ4jNhQoGB')

# For hex format:

privKey = Key.from_hex('ccb8c423403f4d5b6cde505d2a8f39d1d9399f6e06853339f5b11593cc502dc9')

# For int format:

privKey = Key.from_int('92598274663553697917256765988661195316245391320286084491562671024534692310473')

privKey = Key.from_byte('b'\xcc\xb8\xc4#@?M[l\xdeP]*\x8f9\xd1\xd99\x9fn\x06\x8539\xf5\xb1\x15\x93\xccP-\xc9')

Exporting works pretty much the same way as importing except you replace from.[format here] with to.[format here], you can even import or export a PEM file of your private key.

The documentation is enough for the library to give you the core functions, but is also somewhat lacking, for example you can't create compressed bitcoin addresses. But otherwise you can sign, send transactions, even select exactly which outputs you want to use .etc

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.