I was wondering How does etherscan fetch the number of token holders from a smart contract? enter image description here


They keep track of Transfer events emitted by that smart contract. Most likely they record them in an SQL database and maintain a ledger based on these events. The event is defined in the ERC20 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md

There is no way to look up this information from the smart contract directly. Even though the balances variable is public, the mapping data type in Solidity doesn't support enumerating the keys. Reading the low level database of an Ethereum client wouldn't help either since all storage keys are hashed before they are persisted.

  • 1
    I actually tested Etherscan's token holder records the Transfer event on Ropsten. They indeed seem to rely on this event. Token transfer through changing the mapping only (i.e. without Transfer) doesn't appear to appear on Etherscan. – Linmao Song Mar 28 '18 at 17:51
  • Does this mean that the number that they are showing might be missing a few first events? – Hossein Mar 28 '18 at 19:04
  • Normally the contract would emit the Transfer event for everything that changes token balances. Not sure what you mean by a few first events? – medvedev1088 Mar 28 '18 at 19:36
  • @medvedev1088 Not always, if you transfer tokens using the approve/transferFrom mechanism it doesn't emit a Transfer() event. So in that case, Etherscan will miss the transfer – abed Dec 30 '18 at 23:11
  • @abed: The ERC20 standard does not state that you should emit a Transfer event every time you change the balanceOf mapping (and even if it did, there is no practical way to enforce it). Emitting this event is under the responsibility of the programmer. A good programmer would add it in every function which changes the mapping, and a bad programmer could even leave it out out every such function. – goodvibration Jul 21 '19 at 13:04

I have created a standalone tool which does the same.

  • Take a token contract address

  • Iterate over all Transfer events for token using eth_getLogs JSON-RPC API

  • Build a local database of these events

  • Allow you to use SQL to query any account balance on any point of time (block num)

You can find the command line application how to build the database here

The core Python logic is here.

There are some quirks here and there: for example detecting mint / creation event for some tokens is not straightforward. Thus, you will may negative balance on the account receiving initial total supply if you rely on Transfer event only.


As ERC20 tokens distribution is stored in balances variable inside the token smart-contract and as variable is public, by listing the transactions in and out you can then know all the holding token addresses. As reading a variable state doesn't cost any gas, you can perform this at almost no cost ( other than the power you need to perform the checkings )

Another solution is to host a synchronized node in which you could then check the state of the balances inside the EVM.

  • 1
    Although the balances mapping is public as you said, you can't loop through them all and check everyone's balance, this is not supported in the base ERC-20 contract – abed Dec 30 '18 at 23:14

There is a free API provider that contains this info (free api key needed): https://ethplorer.io/ https://github.com/EverexIO/Ethplorer/wiki/Ethplorer-API#get-token-info

  • Incorrect answer. – Mikko Ohtamaa Apr 16 at 8:01
  • Hi! You might be wondering why this answer got downvoted. Thanks for taking the time to answer, but if you look at the original question, you'll see that the asker wanted to know how Etherscan does something, not how to find that information elsewhere. – Linum Labs Apr 18 at 10:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.