Web3.py Tutorial: How to Transfer Tokens Using Python

·

Blockchain technology has revolutionized how we think about digital ownership, identity, and value transfer. For developers, interacting with blockchain networks like Ethereum has become increasingly accessible — especially with tools like Web3.py, a powerful Python library that enables seamless communication with the Ethereum blockchain.

In this comprehensive guide, you’ll learn how to use Web3.py to create accounts, connect to the Ethereum testnet, and transfer tokens — all using Python. Whether you're building decentralized applications (dApps), automating blockchain interactions, or exploring smart contracts, this tutorial lays the foundation.

We’ll walk through each step in detail, using the Rinkeby test network for safety and ease of learning. All concepts apply directly to Ethereum’s mainnet when you're ready to go live.


Prerequisites

Before diving in, ensure you have:

🔒 Security Note: We’ll generate a sample private key for demonstration. Never expose real private keys online.

Step 1: Install Web3.py

Start by installing the Web3.py library via pip:

pip3 install web3

If you have both Python 2 and 3 installed, confirm you’re using the correct pip version:

pip3 -V

To avoid dependency conflicts, consider using a virtual environment:

python3 -m venv web3env
source web3env/bin/activate  # On Windows: web3env\Scripts\activate
pip install web3

👉 Start building blockchain applications with Python today.


Step 2: Connect to the Ethereum Network

You don’t need to run your own node. Instead, use a node-as-a-service provider like Infura or Alchemy. In this tutorial, we’ll use Infura’s free tier.

  1. Sign up at infura.io and create a project.
  2. Copy your HTTPS endpoint for the Rinkeby testnet (e.g., https://rinkeby.infura.io/v3/YOUR_PROJECT_ID).

Now launch the Python interpreter:

python3

Import required modules:

from web3 import Web3, HTTPProvider
import json

Initialize the Web3 connection:

w3 = Web3(Web3.HTTPProvider("https://rinkeby.infura.io/v3/8e4cd4b220fa42d3ac2acca966fd07fa"))
✅ Always include https:// — omitting it will cause connection errors.

Since Rinkeby uses Proof-of-Authority (PoA), inject PoA middleware:

from web3.middleware import geth_poa_middleware
w3.middleware_onion.inject(geth_poa_middleware, layer=0)

Verify connectivity:

w3.isConnected()

If this returns True, congratulations — you're connected to the Ethereum blockchain!

Troubleshooting Tips:


Step 3: Create an Ethereum Account

Every transaction on Ethereum requires an account. Use Web3.py to generate one:

my_account = w3.eth.account.create('Nobody expects the Spanish Inquisition!')
print("Address:", my_account.address)
print("Private Key:", my_account.privateKey.hex())
⚠️ This private key is for educational purposes only. Never share or reuse keys in production.

The generated account includes:

For real-world use, store keys securely using wallets like MetaMask or hardware devices.


Step 4: Understand ENS (Ethereum Name Service)

Ethereum addresses are long and hard to remember (e.g., 0x5b58...6738). The Ethereum Name Service (ENS) maps human-readable names like alice.eth to addresses — similar to DNS for websites.

While .eth domains are only available on the mainnet, many dApps support ENS resolution. Future tutorials will cover ENS integration.


Step 5: Transfer Tokens Using a Smart Contract

Let’s send Dai, a stablecoin pegged to $1, from our newly created account.

What Is Dai?

Dai is a decentralized stablecoin built on Ethereum. Unlike volatile cryptocurrencies, Dai maintains price stability through smart contract mechanisms — making it ideal for predictable payments and transfers.

We’ll interact with the Dai smart contract on the Rinkeby testnet.


Contract Instantiation

To call functions on a smart contract, we need:

  1. The contract’s address
  2. Its ABI (Application Binary Interface)

Paste the following ABI (already formatted as JSON):

abi = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}, {"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}, {"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, {"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}, {"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"}, {"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}, {"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}, {"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, {"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}, {"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}, {"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}, {"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, {"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}, {"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"}, {"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"}]'

abi = json.loads(abi)

Set the contract address:

address = '0xc3dbf84Abb494ce5199D5d4D815b10EC29529ff8'

Instantiate the contract:

dai = w3.eth.contract(address=address, abi=abi)

Test it by checking total supply:

dai.functions.totalSupply().call()

Build the Transaction

Use the transfer function to send 10 Dai:

to_address = '0xafC2F2bBD4173311BE60A7f5d4103b098D2703e8'
amount = 0x10  # 16 in decimal = 10 Dai (adjust as needed)

Build transaction with required parameters:

transaction = dai.functions.transfer(
    to_address,
    amount
).buildTransaction({
    'chainId': 4,        # Rinkeby network ID
    'gas': 70000,
    'nonce': w3.eth.getTransactionCount(my_account.address),
})

Why These Fields Matter:

👉 Learn how to automate blockchain workflows with code.


Sign and Send the Transaction

Sign using your private key:

private_key = '0x265434629c3d2e652550d62225adcb2813d3ac32c6e07c8c39b5cc1efbca18b3'
signed_txn = w3.eth.account.signTransaction(transaction, private_key)

Broadcast to the network:

txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction)
print("Transaction Hash:", txn_hash.hex())

Success! You’ve just sent Dai using Python.

Check the transaction on Rinkeby Etherscan using the hash.


Core Keywords

This tutorial integrates the following SEO-optimized keywords naturally:


Frequently Asked Questions (FAQ)

Q: Can I use Web3.py on Ethereum mainnet?
A: Yes! Just replace the Infura URL with a mainnet endpoint and ensure your account has ETH for gas fees.

Q: Do I need real ETH to test?
A: No. Use testnet ETH from a faucet like Rinkeby Faucet to get free test ETH for gas.

Q: How do I check my token balance?
A: Call dai.functions.balanceOf(your_address).call() after instantiating the contract.

Q: What is gas in Ethereum?
A: Gas is the fee paid to miners for processing transactions. It's priced in ETH and varies based on network congestion.

Q: Can I automate multiple transactions?
A: Absolutely. Wrap logic in functions or loops, but manage nonces carefully to avoid failures.

Q: Is Web3.py secure for production apps?
A: Yes, but always protect private keys using environment variables or secure vaults — never hardcode them.


Final Thoughts

You now know how to use Web3.py to connect Python applications to Ethereum, create accounts, interact with smart contracts, and transfer tokens like Dai. This opens doors to building dApps, DeFi bots, NFT mints, and more.

As you advance, explore topics like event listening, wallet integration, and deploying your own contracts.

👉 Take your blockchain development skills further — explore advanced tools and APIs.