Troubleshooting

Set up a clean environment

Many things can cause a broken environment. You might be on an unsupported version of Python. Another package might be installed that has a name or version conflict. Often, the best way to guarantee a correct environment is with virtualenv, like:

# Install pip if it is not available:
$ which pip || curl https://bootstrap.pypa.io/get-pip.py | python

# Install virtualenv if it is not available:
$ which virtualenv || pip install --upgrade virtualenv

# *If* the above command displays an error, you can try installing as root:
$ sudo pip install virtualenv

# Create a virtual environment:
$ virtualenv -p python3 ~/.venv-py3

# Activate your new virtual environment:
$ source ~/.venv-py3/bin/activate

# With virtualenv active, make sure you have the latest packaging tools
$ pip install --upgrade pip setuptools

# Now we can install web3.py...
$ pip install --upgrade web3

Note

Remember that each new terminal session requires you to reactivate your virtualenv, like: $ source ~/.venv-py3/bin/activate

Why can’t I use a particular function?

Note that a web3.py instance must be configured before you can use most of its capabilities. One symptom of not configuring the instance first is an error that looks something like this: AttributeError: type object 'Web3' has no attribute 'eth'.

To properly configure your web3.py instance, specify which provider you’re using to connect to the Ethereum network. An example configuration, if you’re connecting to a locally run node, might be:

>>> from web3 import Web3
>>> w3 = Web3(Web3.HTTPProvider('http://localhost:8545'))

# now `w3` is available to use:
>>> w3.is_connected()
True
>>> w3.eth.send_transaction(...)

Refer to the Providers documentation for further help with configuration.

Why isn’t my web3 instance connecting to the network?

You can check that your instance is connected via the is_connected method:

>>> w3.is_connected()
False

There are a variety of explanations for why you may see False here. To help you diagnose the problem, is_connected has an optional show_traceback argument:

>>> w3.is_connected(show_traceback=True)
# this is an example, your error may differ

# <long stack trace output>
ProviderConnectionError: Problem connecting to provider with error: <class 'FileNotFoundError'>: cannot connect to IPC socket at path: None

If you’re running a local node, such as Geth, double-check that you’ve indeed started the binary and that you’ve started it from the intended directory - particularly if you’ve specified a relative path to its ipc file.

If that does not address your issue, it’s probable that you still have a Provider configuration issue. There are several options for configuring a Provider, detailed here.

How do I get ether for my test network?

Test networks usually have something called a “faucet” to help get test ether to people who want to use it. The faucet simply sends you test ether when you visit a web page, or ping a chat bot, etc.

Each test network has its own version of test ether, so each one must maintain its own faucet. Faucet mechanisms tend to come and go, so a web search for “ethereum testnet faucet” should give you the most up-to-date options.

How do I use my MetaMask accounts from web3.py?

Export your private key from MetaMask, and use the local private key tools in web3.py to sign and send transactions.

See how to export your private key and Accounts.

How do I create an account?

In general, your options for accounts are:

  • Import a keystore file for an account and extract the private key.

  • Create an account via the eth-account API, e.g., new_acct = w3.eth.account.create().

  • Use an external service (e.g. Metamask) to generate a new account, then securely import its private key.

Warning

Don’t store real value in an account until you are familiar with security best practices. If you lose your private key, you lose your account!

Why doesn’t my transaction work on another network?

web3.py is an Ethereum-specific library, which defaults to “type 2” EIP-1559 transactions as of the London network upgrade. Some chains (including Ethereum L2s) do not support the same transaction types.

If your chain doesn’t support this transaction type, you likely need to create a “legacy” transaction, i.e., include gasPrice, but not type, maxFeePerGas, or maxPriorityFeePerGas in your transaction body.

If that doesn’t resolve your issue, open a GitHub issue or reach out for help in the community Discord server if you’re having trouble with an Ethereum-ecosystem chain. If you’re debugging in an alternative ecosystem, please find another appropriate forum to raise your question.

How do I conform to ABI types?

The web3 library follows the following conventions:

Bytes vs Text

  • The term bytes is used to refer to the binary representation of a string.

  • The term text is used to refer to unicode representations of strings.

Hexadecimal Representations

  • All hexadecimal values will be returned as text.

  • All hexadecimal values will be 0x prefixed.

Ethereum Addresses

All addresses must be supplied in one of three ways:

  • A 20-byte hexadecimal that is checksummed using the EIP-55 spec.

  • A 20-byte binary address (python bytes type).

  • While connected to an Ethereum Name Service (ENS) supported chain, an ENS name (often in the form myname.eth).

Disabling Strict Bytes Type Checking

There is a boolean flag on the Web3 class and the ENS class that will disable strict bytes type checking. This allows bytes values of Python strings and allows byte strings less than the specified byte size, appropriately padding values that need padding. To disable stricter checks, set the w3.strict_bytes_type_checking (or ns.strict_bytes_type_checking) flag to False. This will no longer cause the Web3 / ENS instance to raise an error if a Python string is passed in without a “0x” prefix. It will also render valid byte strings or hex strings that are below the exact number of bytes specified by the ABI type by padding the value appropriately, according to the ABI type. See the Disabling Strict Checks for Bytes Types section for an example on using the flag and more details.

Note

If a standalone ENS instance is instantiated from a Web3 instance, i.e. ns = ENS.from_web3(w3), it will inherit the value of the w3.strict_bytes_type_checking flag from the Web3 instance at the time of instantiation.

Also of note, all modules on the Web3 class will inherit the value of this flag, since all modules use the parent w3 object reference under the hood. This means that w3.eth.w3.strict_bytes_type_checking will always have the same value as w3.strict_bytes_type_checking.

For more details on the ABI specification, refer to the Solidity ABI Spec.

Types by Example

Let’s use a contrived contract to demonstrate input types in web3.py:

contract ManyTypes {
    // booleans
    bool public b;

    // unsigned ints
    uint8 public u8;
    uint256 public u256;
    uint256[] public u256s;

    // signed ints
    int8 public i8;

    // addresses
    address public addr;
    address[] public addrs;

    // bytes
    bytes1 public b1;

    // structs
    struct S {
      address sa;
      bytes32 sb;
    }
    mapping(address => S) addrStructs;

    function updateBool(bool x) public { b = x; }
    function updateUint8(uint8 x) public { u8 = x; }
    function updateUint256(uint256 x) public { u256 = x; }
    function updateUintArray(uint256[] memory x) public { u256s = x; }
    function updateInt8(int8 x) public { i8 = x; }
    function updateAddr(address x) public { addr = x; }
    function updateBytes1(bytes1 x) public { b1 = x; }
    function updateMapping(S memory x) public { addrStructs[x.sa] = x; }
}

Booleans

contract_instance.functions.updateBool(True).transact()

Unsigned Integers

contract_instance.functions.updateUint8(255).transact()
contract_instance.functions.updateUint256(2**256 - 1).transact()
contract_instance.functions.updateUintArray([1, 2, 3]).transact()

Signed Integers

contract_instance.functions.updateInt8(-128).transact()

Addresses

contract_instance.functions.updateAddr("0x0000000000000000000000000000000000000000").transact()

Bytes

contract_instance.functions.updateBytes1(HexBytes(255)).transact()

Structs

contract_instance.functions.updateMapping({"sa": "0x0000000000000000000000000000000000000000", "sb": HexBytes(123)}).transact()

How can I optimize Ethereum JSON-RPC API access?

Your Ethereum node JSON-RPC API might be slow when fetching multiple and large requests, especially when running batch jobs. Here are some tips for how to speed up your web3.py application.

  • Run your client locally, e.g., Go Ethereum or TurboGeth. The network latency and speed are the major limiting factors for fast API access.

  • Use IPC communication instead of HTTP/WebSockets. See Choosing a Provider.

  • Use an optimised JSON decoder. A future iteration of web3.py may change the default decoder or provide an API to configure one, but for now, you may patch the provider class to use ujson.

"""JSON-RPC decoding optimised for web3.py"""

from typing import cast

import ujson

from web3.providers import JSONBaseProvider
from web3.types import RPCResponse


def _fast_decode_rpc_response(raw_response: bytes) -> RPCResponse:
    decoded = ujson.loads(raw_response)
    return cast(RPCResponse, decoded)


def patch_provider(provider: JSONBaseProvider):
    """Monkey-patch web3.py provider for faster JSON decoding.

    Call this on your provider after construction.

    This greatly improves JSON-RPC API access speeds, when fetching
    multiple and large responses.
    """
    provider.decode_rpc_response = _fast_decode_rpc_response

Why am I getting Visual C++ or Cython not installed error?

Some Windows users that do not have Microsoft Visual C++ version 14.0 or greater installed may see an error message when installing web3.py as shown below:

error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/

To fix this error, download and install Microsoft Visual C++ from here :

Microsoft Visual C++ Redistributable for Visual Studio

How do I convert currency denominations?

The following denominations are supported:

denomination

amount in wei

wei

1

kwei

1000

babbage

1000

femtoether

1000

mwei

1000000

lovelace

1000000

picoether

1000000

gwei

1000000000

shannon

1000000000

nanoether

1000000000

nano

1000000000

szabo

1000000000000

microether

1000000000000

micro

1000000000000

finney

1000000000000000

milliether

1000000000000000

milli

1000000000000000

ether

1000000000000000000

kether

1000000000000000000000

grand

1000000000000000000000

mether

1000000000000000000000000

gether

1000000000000000000000000000

tether

1000000000000000000000000000000

You can use the from_wei() method to convert a balance to ether (or another denomination).

>>> web3.from_wei(3841357360894980500000001, 'ether')
Decimal('3841357.360894980500000001')

To convert back to wei, you can use the inverse function, to_wei(). Note that Python’s default floating point precision is insufficient for this use case, so it’s necessary to cast the value to a Decimal if it isn’t already.

>>> from decimal import Decimal
>>> web3.to_wei(Decimal('3841357.360894980500000001'), 'ether')
3841357360894980500000001

Best practice: If you need to work with multiple currency denominations, default to wei. A typical workflow may require a conversion from some denomination to wei, then from wei to whatever you need.

>>> web3.to_wei(Decimal('0.000000005'), 'ether')
5000000000
>>> web3.from_wei(5000000000, 'gwei')
Decimal('5')

How do I adjust the log levels?

web3.py internally uses Python logging subsystem.

If you want to run your application logging in debug mode, below is an example of how to make some JSON-RPC traffic quieter.

import logging
import coloredlogs

def setup_logging(log_level=logging.DEBUG):
    """Setup root logger and quiet some levels."""
    logger = logging.getLogger()

    # Set log format to display the logger name to hunt down verbose logging modules
    fmt = "%(name)-25s %(levelname)-8s %(message)s"

    # Use colored logging output for console with the coloredlogs package
    # https://pypi.org/project/coloredlogs/
    coloredlogs.install(level=log_level, fmt=fmt, logger=logger)

    # Disable logging of JSON-RPC requests and replies
    logging.getLogger("web3.RequestManager").setLevel(logging.WARNING)
    logging.getLogger("web3.providers.HTTPProvider").setLevel(logging.WARNING)
    # logging.getLogger("web3.RequestManager").propagate = False

    # Disable all internal debug logging of requests and urllib3
    # E.g. HTTP traffic
    logging.getLogger("requests").setLevel(logging.WARNING)
    logging.getLogger("urllib3").setLevel(logging.WARNING)

    return logger