Ethereum, as one of the most influential blockchain platforms, powers a vast ecosystem of decentralized applications (dApps), smart contracts, and digital assets. For developers and blockchain analysts, understanding how to interact with the Ethereum network at a foundational level is essential. One powerful capability is retrieving all Ethereum addresses and their corresponding balances using Web3.js — a popular JavaScript library for interacting with Ethereum.
This guide walks you through the technical process of scanning the Ethereum blockchain to collect wallet addresses and balance data, leveraging core Web3 functionalities. Whether you're building analytics tools, conducting research, or exploring blockchain data structures, this tutorial provides practical insights into Ethereum’s on-chain data retrieval.
Understanding the Core Approach
To extract all Ethereum addresses and their balances, we need to traverse the blockchain from the genesis block to the latest block. Each block contains transaction records that reveal sender (from) and receiver (to) addresses. By processing these transactions and checking for unique addresses, we can compile a comprehensive list of wallets and query their current ETH balances.
The methodology involves several key steps:
- Get the current block height – Identify how many blocks exist on the chain.
- Iterate through each block – Retrieve block data sequentially.
- Extract transactions – Pull transaction hashes from each block.
- Fetch transaction details – Obtain
fromandtoaddresses. - Differentiate contract vs. external accounts – Avoid redundant queries by identifying contract creation.
- Query ETH balance – Use
getBalance()for valid external addresses.
These operations are made possible via Web3.js methods such as getBlockNumber(), getBlock(), getTransaction(), and getCode().
Setting Up Web3.js Environment
Before writing any code, ensure your development environment supports Node.js and npm (Node Package Manager). Install Web3.js using the following command:
npm install web3For users in regions with restricted network access, consider using cnpm (Aliyun mirror) for faster downloads:
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install web3Once installed, initialize Web3 by connecting to an Ethereum node. Public endpoints like Infura or Alchemy provide reliable access without running a local node.
👉 Discover how to securely connect to Ethereum nodes with advanced API tools.
Step-by-Step Implementation
Below is a complete implementation in JavaScript using asynchronous Web3 calls:
const Web3 = require('web3');
const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'); // Replace with your Infura ID
let addressList = [];
async function getBlockNumber() {
const latestBlock = await web3.eth.getBlockNumber();
console.log("Latest Block Number:", latestBlock);
await throughBlocks(latestBlock);
}
async function throughBlocks(endBlock) {
for (let i = 0; i <= endBlock; i++) {
await getBlock(i);
}
}
async function getBlock(blockNumber) {
const block = await web3.eth.getBlock(blockNumber, true); // Include full transaction objects
if (block && block.transactions) {
for (const tx of block.transactions) {
await processTransaction(tx);
}
}
}
async function processTransaction(tx) {
if (tx.from) await checkAndStoreAddress(tx.from);
if (tx.to) await checkAndStoreAddress(tx.to);
}
async function checkAndStoreAddress(address) {
if (!address || addressList.includes(address)) return;
try {
const code = await web3.eth.getCode(address);
// If code is '0x', it's an externally owned account (EOA), not a contract
if (code === '0x') {
await getBalance(address);
addressList.push(address);
}
} catch (err) {
console.error("Error checking address:", address, err.message);
}
}
async function getBalance(address) {
try {
const balance = await web3.eth.getBalance(address);
const ethBalance = web3.utils.fromWei(balance, 'ether');
console.log(`Address: ${address} | Balance: ${ethBalance} ETH`);
} catch (err) {
console.error("Failed to get balance for", address, err.message);
}
}
// Start execution
getBlockNumber().catch(console.error);Key Notes:
- Replace
YOUR_INFURA_PROJECT_IDwith your actual Infura project key. - The
getCode()method checks whether an address is a smart contract. Only externally owned accounts (EOAs) should be stored and queried for balance unless contract balances are also needed. - This script logs results to the console but can be extended to save data into files or databases.
Optimizing Performance and Scalability
Scanning the entire Ethereum blockchain is computationally intensive and time-consuming due to over 20 million blocks (as of 2025). Consider the following optimizations:
- Use batch requests: Reduce HTTP overhead by batching multiple RPC calls.
- Parallelize block processing: Use worker threads or async pools to handle multiple blocks concurrently.
- Filter relevant transactions: Focus on specific contract interactions or time ranges instead of full scan.
- Leverage indexing services: Tools like The Graph offer pre-indexed Ethereum data for faster queries.
👉 Explore high-performance blockchain APIs designed for scalable dApp development.
Frequently Asked Questions (FAQ)
Q: Can I retrieve all Ethereum addresses in a reasonable time?
A: Technically yes, but scanning every block from genesis is extremely slow. As of 2025, Ethereum has over 20 million blocks. Full traversal may take days or weeks depending on infrastructure. For practical use, consider incremental scans or third-party APIs.
Q: Why do we check getCode() before getting a balance?
A: This determines if an address is a smart contract. Contracts often have zero balance and generate noise in analysis. Filtering them out improves efficiency unless contract funds are relevant.
Q: Is it safe to use public nodes like Infura?
A: Yes, for read-only operations. However, rate limits apply. For heavy usage, consider dedicated node services or running your own Geth/Besu node.
Q: How accurate is the balance data?
A: The getBalance() method returns the current balance at the time of query. Since blockchain state changes constantly, balances may differ slightly between scans.
Q: Can this method detect ERC-20 token balances?
A: No — this approach only retrieves ETH balances. To get token holdings, you must query individual token contracts using their ABI and balanceOf() function.
Q: What are alternatives to Web3.js?
A: Libraries like ethers.js offer similar functionality with a more modern API design. Ethers.js is often preferred for its lightweight footprint and better TypeScript support.
Practical Use Cases
This technique enables various real-world applications:
- Blockchain explorers analyzing wallet distributions.
- Security audits tracing fund flows.
- Research on wealth concentration in the Ethereum ecosystem.
- Building custom dashboards for on-chain analytics.
While full scans are resource-heavy, targeted versions (e.g., monitoring specific wallets or DeFi protocols) are highly efficient.
Final Thoughts
Understanding how to programmatically access Ethereum address and balance data opens doors to deeper blockchain analysis. With Web3.js, developers can build powerful tools that interact directly with the decentralized web.
However, scalability remains a challenge when dealing with large-scale data extraction. Combining Web3 with optimized infrastructure — such as high-throughput RPC providers or indexed data layers — enhances performance significantly.
Whether you're a beginner learning blockchain fundamentals or an experienced engineer building dApps, mastering these techniques strengthens your ability to innovate within the Web3 space.
👉 Unlock advanced blockchain development tools and elevate your Web3 projects today.