Guide · Python · SDK · REST API

Ethereum Address Validation in Python — EIP-55 Checksum Explained

Ethereum addresses are 20-byte hex strings with an optional mixed-case checksum defined by EIP-55. A simple regex won't catch wrong-case typos that could send funds to an unrecoverable address. Here's how to validate them properly.

1. What is an Ethereum address?

An Ethereum address is a 20-byte (160-bit) identifier that represents an account on the Ethereum network. It is derived from the public key of an elliptic-curve key pair: take the Keccak-256 hash of the uncompressed public key, then keep only the last 20 bytes.

When displayed, Ethereum addresses are encoded as 40 hexadecimal characters prefixed with 0x, giving a total length of 42 characters. For example:

0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
0x = hex prefixd8dA6B...96045 = 40 hex chars (20 bytes)

Ethereum addresses are used for two types of accounts:

Externally Owned Accounts (EOAs)

Controlled by a private key held by a person or application. EOAs can sign transactions, send ETH, and interact with smart contracts.

Smart contract accounts

Deployed at a deterministic address derived from the deployer's address and nonce. Smart contracts contain executable code but do not have a private key.

ℹ️Unlike IBANs or credit card numbers, Ethereum addresses have no built-in check digits in their basic form. The EIP-55 checksum was introduced later as an optional layer to catch transcription errors.

2. The EIP-55 checksum

EIP-55 (Ethereum Improvement Proposal 55) introduced a backwards-compatible checksum by encoding it in the capitalisation of the hex characters. The mixed-case encoding acts as a checksum without adding any extra characters to the address.

Here is how the algorithm works, step by step, for the address 0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359:

Step 1 — Remove the 0x prefix and lowercase everything

fb6916095ca1df60bb79ce92ce3ea74c37c5d359

Step 2 — Compute the Keccak-256 hash of the lowercase address string (as ASCII)

6b51d0a3ee(64 hex digits)

Each hex digit of this hash will control the case of the corresponding character in the address.

Step 3 — For each character at position i in the address

If the character is a digit (0-9), keep it as-is.

If the character is a letter (a-f), check the i-th hex digit of the hash:

  • If the hash digit is 8, 9, a, b, c, d, e, or f (i.e. ≥ 8), uppercase the letter
  • If the hash digit is 0, 1, 2, 3, 4, 5, 6, or 7 (i.e. < 8), keep it lowercase

Step 4 — Re-attach the 0x prefix

0xFb6916095cA1dF60bB79cE92cE3Ea74c37c5D359

Here is the EIP-55 algorithm in Python:

# eip55.py — implements EIP-55 checksum encoding
from Crypto.Hash import keccak  # pip install pycryptodome


def to_checksum_address(address: str) -> str:
    """Convert an Ethereum address to its EIP-55 checksummed form."""
    # Step 1: lowercase, strip 0x
    addr = address.lower().replace("0x", "")

    # Step 2: hash the lowercase address
    k = keccak.new(digest_bits=256)
    k.update(addr.encode("ascii"))
    addr_hash = k.hexdigest()

    # Step 3: capitalise where hash digit >= 8
    checksummed = "0x"
    for i, ch in enumerate(addr):
        if ch in "abcdef":
            checksummed += ch.upper() if int(addr_hash[i], 16) >= 8 else ch
        else:
            checksummed += ch  # digits stay as-is

    return checksummed


def is_valid_checksum(address: str) -> bool:
    """Check if the mixed-case encoding matches EIP-55."""
    return address == to_checksum_address(address)


print(to_checksum_address("0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359"))
# → 0xFb6916095cA1dF60bB79cE92cE3Ea74c37c5D359
ℹ️EIP-55 is backwards-compatible. All-lowercase and all-uppercase addresses are still valid — they simply do not carry a checksum. Only mixed-case addresses encode checksum information that can be verified.

3. Why simple hex regex isn't enough

A common first attempt at Ethereum address validation looks like this:

# naive approach — DO NOT use in production
import re

def is_eth_address(addr: str) -> bool:
    return bool(re.match(r"^0x[0-9a-fA-F]{40}$", addr))

is_eth_address("0x0000000000000000000000000000000000000000")  # True — but is it real?
is_eth_address("0xd8da6bf26964af9d7eed9e03e53415d37aa96045")  # True — but wrong checksum!

This regex confirms the string looks like an address, but misses critical problems:

The zero address passes

0x0000000000000000000000000000000000000000 is syntactically valid hex but is the Ethereum "burn address." Sending funds there is irreversible. A regex won't flag this.

Wrong-case mixed-case addresses slip through

A user copies an address and accidentally changes the case of one letter. The regex still matches, but the EIP-55 checksum is now broken. Without checksum verification, your application accepts a potentially garbled address.

Sending to the wrong address is irreversible

Unlike traditional banking where a wrong transfer can sometimes be reversed, sending ETH or tokens to an incorrect Ethereum address means the funds are gone forever. There is no chargeback, no dispute process, and no central authority that can intervene. Proper validation is your last line of defence.

No distinction between address types

A regex cannot tell you whether the address is an EOA or a smart contract. While this distinction does not change the address format, knowing the address type can be useful for user-facing warnings (e.g. "you are about to send tokens to a contract address").

⚠️On-chain transactions are irreversible. Proper EIP-55 checksum validation is not optional — it is a safety requirement for any application that handles Ethereum addresses.

4. The right solution

The IsValid Ethereum Address API performs full structural validation and EIP-55 checksum verification in a single GET request. The response includes the correctly checksummed address so you can store and display it confidently.

0x + 40 hex
Format check
prefix, length, charset
Keccak-256
EIP-55 checksum
mixed-case verification
address
Checksummed return
correctly cased address

Get your free API key at isvalid.dev. The free tier includes 100 calls per day — enough for most development and low-volume production use.

Full parameter reference and response schema: Ethereum Address Validation API docs →


5. Python code example

Using the IsValid Python SDK or the requests library.

from isvalid import create_client

iv = create_client(api_key=os.environ["ISVALID_API_KEY"])

# ── Example usage ────────────────────────────────────────────────────────────

result = iv.eth_address("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")

if not result["valid"]:
    print("Invalid Ethereum address")
else:
    print(f"Valid address: {result['address']}")
    print(f"EIP-55 checksum valid: {result['isChecksumValid']}")
    # → Valid address: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
    # → EIP-55 checksum valid: True

In a withdrawal handler, you might use it like this:

# views.py (Django)
from django.http import JsonResponse
from django.views.decorators.http import require_POST
import json


@require_POST
def withdraw(request):
    body = json.loads(request.body)
    address = body.get("address")
    amount = body.get("amount")
    token = body.get("token")

    try:
        addr_check = validate_eth_address(address)
    except requests.RequestException:
        return JsonResponse(
            {"error": "Address validation service unavailable"}, status=502
        )

    if not addr_check["valid"]:
        return JsonResponse({"error": "Invalid Ethereum address"}, status=400)

    if not addr_check["isChecksumValid"]:
        return JsonResponse(
            {
                "error": "Address has invalid EIP-55 checksum — please double-check",
                "expected": addr_check["address"],  # correctly checksummed version
            },
            status=400,
        )

    # Use the checksummed address from the API response for storage
    initiate_withdrawal(
        to_address=addr_check["address"],
        amount=amount,
        token=token,
    )

    return JsonResponse({"success": True, "toAddress": addr_check["address"]})
Always store the checksummed version of the address returned in the address field. This ensures consistency in your database and makes it safe to compare addresses using simple string equality.

6. cURL example

Validate a checksummed Ethereum address:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/eth-address?value=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"

Validate an all-lowercase address (no checksum encoding):

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/eth-address?value=0xd8da6bf26964af9d7eed9e03e53415d37aa96045"

An invalid address (wrong length):

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.isvalid.dev/v0/eth-address?value=0xd8dA6BF26964aF9D7eEd9e03E534"

7. Understanding the response

Valid checksummed address:

{
  "valid": true,
  "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
  "isChecksumValid": true
}

Valid all-lowercase address (no checksum to verify):

{
  "valid": true,
  "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
  "isChecksumValid": true
}

Invalid address:

{
  "valid": false
}
FieldTypeDescription
validbooleanWhether the address passes format validation (0x prefix, 40 hex characters)
addressstringThe address with correct EIP-55 checksummed capitalisation (only present when valid)
isChecksumValidbooleanWhether the EIP-55 mixed-case checksum is correct. Always true for all-lowercase or all-uppercase addresses because there is no checksum to verify (only present when valid)
⚠️A valid Ethereum address confirms the string is structurally correct — it does not guarantee the address has ever been used, holds any balance, or is controlled by anyone. On-chain lookups are required to determine account state.

8. Edge cases to handle

All-lowercase addresses are valid

An address like 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 is perfectly valid. Since it is all-lowercase, there is no mixed-case checksum to verify, so isChecksumValid returns true. The same applies to all-uppercase addresses (excluding the 0x prefix). The API returns the correctly checksummed version in the address field regardless.

ENS names are not Ethereum addresses

Names like vitalik.eth are Ethereum Name Service (ENS) domains that resolve to an address via on-chain lookups. They are not validated by this endpoint. If your application accepts ENS names, resolve them to an address first (using a library like web3.py or an ENS resolver API), then validate the resulting address.

# Resolve ENS name before validating
from web3 import Web3

w3 = Web3(Web3.HTTPProvider(os.environ["RPC_URL"]))

ens_name = "vitalik.eth"
resolved = w3.ens.address(ens_name)

if resolved is None:
    print("ENS name does not resolve")
else:
    # Now validate the resolved address
    result = validate_eth_address(resolved)
    print(result)

ICAP / IBAN-style Ethereum addresses

Ethereum defines an ICAP (Inter-exchange Client Address Protocol) encoding that represents addresses in an IBAN-like format, such as XE7338O073KYGTWWZN0F2WZ0R8PX5ZPPZS. ICAP addresses are rarely used in practice and are not validated by this endpoint. If you encounter them, convert to the standard 0x-prefixed format before validation.

The zero address (0x000...0)

0x0000000000000000000000000000000000000000 is structurally valid and will pass format validation. However, it is commonly used as a "burn address" — tokens sent there are irrecoverable. Consider adding an application-level check to warn users before sending to the zero address.

ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"

result = validate_eth_address(address)

if result["valid"] and result["address"] == ZERO_ADDRESS:
    print("Warning: this is the zero/burn address")

Summary

Do not validate Ethereum addresses with a hex regex alone — it misses checksum errors
Do not treat a valid address as proof the account exists or holds funds
Verify the EIP-55 mixed-case checksum to catch transcription errors
Store the checksummed version for consistent comparisons
Handle ENS names separately — resolve them before validation
Warn users before sending to the zero address (0x000...0)

See also

Validate Ethereum addresses instantly

Free tier includes 100 API calls per day. No credit card required. Full EIP-55 checksum verification with correctly cased address returned in the response.