How to Track Ethereum Transactions Using Python (Etherscan API Guide)

If you’re dealing with Ethereum transactions—whether for security audits, tax reporting, or investigating suspicious activity—you need a reliable way to fetch transaction history. In this guide, I’ll show you how to build a Python script that pulls transaction details (TX hash, timestamp, and amount) from Etherscan for any wallet address.

Ethereum Transaction Extraction and Why Script is Useful

  • Audit wallets for incoming/outgoing transactions.
  • Track stolen funds in real time (useful for hackers exploiting DeFi protocols).
  • Monitor whale movements (large ETH transfers).
  • Automate transaction logging for accounting or legal purposes.

How the Script Works

The script uses Etherscan’s free API to:

  1. Fetch normal transactions (ETH transfers).
  2. Fetch internal transactions (smart contract interactions).
  3. Combine and sort them by timestamp.
  4. Filter by destination wallet (if needed).

Step-by-Step Setup

1. Get an Etherscan API Key

  • Go to Etherscan.io → Sign up (free).
  • Navigate to “API-Keys” → Create a new key.
  • Replace YOUR_ETHERSCAN_API_KEY in the script.

2. Install Required Libraries

Run this in your command prompt terminal:

pip install requests

3. Run the Script

import requests
import json
from datetime import datetime

# Etherscan API configuration
ETHERSCAN_API_KEY = "###"  # Replace with your Etherscan API key
ETHERSCAN_API_URL = "https://api.etherscan.io/api"

def get_transactions(wallet_address):
    """
    Fetch all normal transactions for a given Ethereum wallet address
    """
    params = {
        "module": "account",
        "action": "txlist",
        "address": wallet_address,
        "startblock": 0,
        "endblock": 99999999,
        "sort": "asc",
        "apikey": ETHERSCAN_API_KEY
    }
    
    response = requests.get(ETHERSCAN_API_URL, params=params)
    data = response.json()
    
    if data["status"] != "1":
        print(f"Error: {data.get('message', 'Unknown error')}")
        return []
    
    return data["result"]

def get_internal_transactions(wallet_address):
    """
    Fetch all internal transactions for a given Ethereum wallet address
    """
    params = {
        "module": "account",
        "action": "txlistinternal",
        "address": wallet_address,
        "startblock": 0,
        "endblock": 99999999,
        "sort": "asc",
        "apikey": ETHERSCAN_API_KEY
    }
    
    response = requests.get(ETHERSCAN_API_URL, params=params)
    data = response.json()
    
    if data["status"] != "1":
        print(f"Error: {data.get('message', 'Unknown error')}")
        return []
    
    return data["result"]

def format_transactions(transactions, internal=False):
    """
    Format transaction data into a more readable structure
    """
    formatted = []
    for tx in transactions:
        # Convert timestamp to readable date
        timestamp = int(tx["timeStamp"])
        date = datetime.utcfromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
        
        # Determine amount in Ether
        if internal:
            amount = int(tx["value"]) / 10**18
        else:
            amount = int(tx["value"]) / 10**18 if "value" in tx else 0
        
        formatted.append({
            "tx_hash": tx["hash"],
            "timestamp": timestamp,
            "date": date,
            "amount_eth": amount,
            "from": tx["from"],
            "to": tx["to"],
            "is_internal": internal
        })
    
    return formatted

def get_all_transactions(wallet_address):
    """
    Get both normal and internal transactions for a wallet
    """
    normal_txs = get_transactions(wallet_address)
    internal_txs = get_internal_transactions(wallet_address)
    
    all_txs = format_transactions(normal_txs) + format_transactions(internal_txs, True)
    
    # Sort all transactions by timestamp
    all_txs.sort(key=lambda x: x["timestamp"])
    
    return all_txs

def filter_by_destination(transactions, destination_wallet):
    """
    Filter transactions by destination wallet
    """
    return [tx for tx in transactions if tx["to"].lower() == destination_wallet.lower()]

def main():
    # Get user input
    wallet_address = input("Enter the source wallet address: ").strip()
    destination_wallet = input("Enter the destination wallet address (leave empty to see all transactions): ").strip()
    
    print(f"\nFetching transactions for wallet: {wallet_address}")
    
    # Get all transactions
    transactions = get_all_transactions(wallet_address)
    
    # Filter by destination if provided
    if destination_wallet:
        transactions = filter_by_destination(transactions, destination_wallet)
    
    # Display results
    if not transactions:
        print("No transactions found.")
        return
    
    print("\nTransaction Hash".ljust(66), "Timestamp".ljust(20), "Amount (ETH)".ljust(20), "Internal")
    print("-" * 120)
    
    for tx in transactions:
        print(
            tx["tx_hash"].ljust(66),
            tx["date"].ljust(20),
            str(tx["amount_eth"]).ljust(20),
            "Yes" if tx["is_internal"] else "No"
        )

if __name__ == "__main__":
    main()

How to Use It

  1. Run the script → Enter a wallet address (e.g., 0x742d35Cc...)
Ethereum Transaction
  1. (Optional) Filter by a destination wallet to see only outgoing TXs.
  2. See results in a clean table format like the above picture. Here i blurred the wallet address because of security.

Limitations & Improvements

  • Rate Limits: Etherscan’s free API allows 5 calls/sec.
  • ERC-20 Tokens: This script tracks only ETH—expand it to support tokens.
  • Large Data Handling: For wallets with 10,000+ TXs, use pagination.

Final Thoughts

This script is a powerful starting point for Ethereum transaction analysis. For advanced tracking (e.g., Tornado Cash withdrawals), you’d need to integrate Dune Analytics or Arkham Intelligence.

Need help customizing it? Drop a comment below! 🚀

(Disclaimer: This script is for educational purposes only. Always comply with local laws when tracking blockchain transactions.)

Scroll to Top