I'm looking to do it programmatically, I've looked into my token contract and some events that could be helpful now I'm confused on how to call certain events if anyone could give me examples using web3.py. For example:
– Parth PatelApr 13 '18 at 16:08

tx_list is the list of transactions with participating defined ERC20 — iterate it to extract addresess and timestamp (time when they made it). Note: transaction entire doesn't contain timstamp, but you can get it through timestamp of block this transaction.

(Almost all) ERC-20 token contracts do not maintain a list of iterable token holders, but you need to build a database offchain yourself. mapping in EVM is not iterable, you can only check for a known key value.

I have created a standalone tool which collects ERC-20 token holders and transactions to SQLite database and using web3.py library.

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)

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.

You should checkout TrueBlocks. It can do exactly this. Unlike above answers this will report on every transaction including mint events (even if the token contract doesn't generate mint events. If you're not running your own node, it can fall back on getting the same data as is available with EtherScan. If you are running your own node, it will build a queriable index which you can then query for a full list of every transaction on any address. From there, you can build your own list of token holders.