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:
- Fetch normal transactions (ETH transfers).
- Fetch internal transactions (smart contract interactions).
- Combine and sort them by timestamp.
- 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 by replacing the API key
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
- Run the script → Enter a wallet address (e.g.,
0x742d35Cc...
)

- (Optional) Filter by a destination wallet to see only outgoing TXs.
- 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.)