How to Get All Tokens Owned by an Address
Learn how to get balances of all tokens owned by an address using the Alchemy Token API.
Most dapps, whether they are exchanges, DeFi protocols, wallets, or analytics platforms, require that their users are able to view all their tokens and token balances at one place.
Digital asset wallet interface that shows the token balances of multiple cryptocurrencies.
To get all the tokens owned by a wallet on Ethereum, you would typically have to index the entire blockchain since genesis, track all ERC-20 contracts, and compute token balances of wallets.
This process typically requires a massive amount of engineering resources and time.
However, this effort can be bypassed by using Alchemy's Token API to get the balances of all tokens owned by a wallet address.

About this Tutorial

We will write a simple script in Node to get the balances of the top 100 tokens (by volume) on the Ethereum blockchain using a free Alchemy developer account and Alchemy's Token API.

Creating the Token Balances Script

Step 1: Install Node and npm

In case you haven't already, install node and npm on your local machine.
Make sure that node is at least v14 or higher by typing the following in your terminal:
1
node -v
Copied!

Step 2: Create an Alchemy app

In case you haven't already, sign up for a free Alchemy account.
Alchemy's account dashboard where developers can create a new app on the Ethereum blockchain.
Next, navigate to the Alchemy Dashboard and create a new app.
Make sure you set the chain to Ethereum and network to Mainnet.
Once the app is created, click on your app's View Key button on the dashboard.
Take a note of the HTTP URL.
The URL will be in this form: https://eth-mainnet.alchemyapi.io/v2/xxxxxxxxx
You will need this later.

Step 3: Create a node project

Let's now create an empty repository and install all node dependencies.
To make requests to the Token API, use the Alchemy web3 library.
You can also use axios or fetch alternatively.
Alchemy Web3 (Recommended)
Axios
Fetch
1
mkdir token-balances && cd token-balances
2
npm init -y
3
npm install --save @alch/alchemy-web3
4
touch main.js
Copied!
1
mkdir token-balances && cd token-balances
2
npm init -y
3
npm install --save axios
4
touch main.js
Copied!
1
mkdir token-balances && cd token-balances
2
npm init -y
3
touch main.js
Copied!
This will create a repository named token-balances that holds all your files and dependencies.
Next, open this repo in your favorite code editor.
We will be writing all our code in the main.js file.

Step 4: Get token balances of an address

To get token balances, you will use the getTokenBalances method.
This method takes in two arguments:
  1. 1.
    DATA: The wallet address of which we want to get token balances.
  2. 2.
    Either an Array of ERC-20 contract addresses or a String of value DEFAULT_TOKENS.
Since we are interested in getting the balances of all tokens, you will set the second argument to DEFAULT_TOKENS. This will give you the balances of the top 100 tokens on the Ethereum blockchain (by volume).
In other words, it will give you all the tokens you could possibly care about.
Add the following code to the main.js file.
Alchemy Web3 (Recommended)
Axios
Fetch
1
const { createAlchemyWeb3 } = require("@alch/alchemy-web3");
2
​
3
// Using HTTP
4
const web3 = createAlchemyWeb3(
5
"<--ALCHEMY APP HTTP URL-->",
6
);
7
​
8
const main = async () => {
9
// Wallet address
10
const address =
11
'0xd8da6bf26964af9d7eed9e03e53415d37aa96045'
12
​
13
// Get token balances
14
const balances = await
15
web3.alchemy.getTokenBalances(address, 'DEFAULT_TOKENS')
16
​
17
// Print token balances
18
console.log(balances)
19
}
20
​
21
const runMain = async () => {
22
try {
23
await main();
24
process.exit(0);
25
}
26
catch (error) {
27
console.log(error);
28
process.exit(1);
29
}
30
};
31
​
32
runMain();
Copied!
1
const axios = require('axios')
2
​
3
// Wallet address
4
const address = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'
5
​
6
// Alchemy URL
7
const baseURL = `<-- ALCHEMY APP HTTP URL -->`;
8
​
9
const data = JSON.stringify({
10
"jsonrpc": "2.0",
11
"method": "alchemy_getTokenBalances",
12
"headers": {
13
"Content-Type": "application/json"
14
},
15
"params": [
16
`${address}`,
17
"DEFAULT_TOKENS",
18
],
19
"id": 42
20
});
21
​
22
const config = {
23
method: 'post',
24
url: baseURL,
25
headers: {
26
'Content-Type': 'application/json'
27
},
28
data : data
29
};
30
​
31
// Make the request and print the formatted response:
32
axios(config)
33
.then(response => console.log(response['data']['result']))
34
.catch(error => console.log('error', error));
35
​
Copied!
1
// Wallet address
2
const address = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'
3
​
4
// Alchemy URL
5
const baseURL = `<-- ALCHEMY APP HTTP URL -->`;
6
​
7
var raw = JSON.stringify({
8
"jsonrpc": "2.0",
9
"method": "alchemy_getTokenBalances",
10
"headers": {
11
"Content-Type": "application/json"
12
},
13
"params": [
14
`${address}`,
15
"DEFAULT_TOKENS",
16
],
17
"id": 42
18
});
19
​
20
var requestOptions = {
21
method: 'POST',
22
body: raw,
23
redirect: 'follow'
24
};
25
​
26
// Make the request and print the formatted response:
27
fetch(fetchURL, requestOptions)
28
.then(response => console.log(response['data']['result']))
29
.catch(error => console.log('error', error));
Copied!
Run this script by typing:
1
node main.js
Copied!
You should see an output that looks like this:
1
{
2
address: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
3
tokenBalances: [
4
{
5
contractAddress:
6
'0xdac17f958d2ee523a2206206994597c13d831ec7',
7
tokenBalance: '100000',
8
error: null
9
},
10
{
11
contractAddress:
12
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
13
tokenBalance: '5000000',
14
error: null
15
},
16
...
17
]
18
}
Copied!

Step 5: Add metadata and parse API output

The output generated in the previous step is not very human-readable. It only gives us information that tells us the contract address of the token and balance in its smallest unit.
To get more relevant information about the token such as name, symbol, and number of decimals, we need to leverage another method called getTokenMetadata.
The getTokenMetadata method takes a single argument of the contract address and returns data in the following format.
1
{
2
decimals: 6,
3
logo: 'https://static.alchemyapi.io/images/assets/825.png',
4
name: 'Tether',
5
symbol: 'USDT'
6
}
Copied!
With this in mind, let's write code that does the following:
  1. 1.
    Remove all tokens with zero balances.
  2. 2.
    Loop through all tokens and extract metadata using the getTokenMetadata method.
  3. 3.
    Convert token balances to a human-readable number.
  4. 4.
    Print the token's name, balance, and symbol to the console.

The Calculation for token balance

The tokenBalance returned by the Token API is usually a number with several digits.
In this case 4929853276 for USDT.
Every ERC20 token has a metadata information called "decimals" which denotes the divisibility of a token (ranges from 0 to 18).
For USDT, the value of "decimals" is 6.
The response returned by Alchemy's getTokenBalances API is as below.
tokenBalance = no. of tokens (quantity) * Math.pow(10, 6) Hence, the actual quantity of the USDT token in this case will be 4929853276/10^6 = 4,929.853276 The same operation needs to be done to obtain the actual quantity for any token.
We show the calculation in the code below
Replace the contents of main.js with the following:
Alchemy Web3 (Recommended)
Axios
Fetch
1
const { createAlchemyWeb3 } = require("@alch/alchemy-web3");
2
​
3
// Using HTTP
4
const web3 = createAlchemyWeb3(
5
"<--ALCHEMY APP HTTP URL-->",
6
);
7
​
8
const main = async () => {
9
// Wallet address
10
const address =
11
'0xd8da6bf26964af9d7eed9e03e53415d37aa96045'
12
​
13
// Get token balances
14
const balances = await
15
web3.alchemy.getTokenBalances(address, 'DEFAULT_TOKENS')
16
​
17
// Remove tokens with zero balance
18
const nonZeroBalances =
19
balances['tokenBalances'].filter(token => {
20
return token['tokenBalance'] !== '0'
21
})
22
23
console.log(`Token balances of ${address} \n`)
24
25
// Counter for SNo of final output
26
let i = 1
27
28
// Loop through all tokens with non-zero balance
29
for (token of nonZeroBalances) {
30
31
// Get balance of token
32
let balance = token['tokenBalance']
33
34
// Get metadata of token
35
const metadata = await web3.alchemy.getTokenMetadata(token[
36
'contractAddress'
37
]);
38
39
// Compute token balance in human-readable format
40
balance = balance/Math.pow(10, metadata['decimals']);
41
balance = balance.toFixed(2);
42
43
// Print name, balance, and symbol of token
44
console.log(`${i++}. ${metadata['name']}: ${balance}
45
${metadata['symbol']}`)
46
}
47
}
48
​
49
const runMain = async () => {
50
try {
51
await main();
52
process.exit(0);
53
}
54
catch (error) {
55
console.log(error);
56
process.exit(1);
57
}
58
};
59
​
60
runMain();
Copied!
1
const axios = require('axios')
2
​
3
// Wallet address
4
const address = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'
5
​
6
// Alchemy URL
7
const baseURL = `<-- ALCHEMY APP HTTP URL -->`;
8
​
9
const data = JSON.stringify({
10
"jsonrpc": "2.0",
11
"method": "alchemy_getTokenBalances",
12
"headers": {
13
"Content-Type": "application/json"
14
},
15
"params": [
16
`${address}`,
17
"DEFAULT_TOKENS",
18
],
19
"id": 42
20
});
21
​
22
const config = {
23
method: 'post',
24
url: baseURL,
25
headers: {
26
'Content-Type': 'application/json'
27
},
28
data : data
29
};
30
​
31
// Make the request and print the formatted response:
32
axios(config)
33
.then(response => {
34
35
// Get balances
36
const balances = response['data']['result']
37
38
// Remove tokens with zero balance
39
const nonZeroBalances =
40
balances['tokenBalances'].filter(token => {
41
return token['tokenBalance'] !== '0'
42
})
43
​
44
console.log(`Token balances of ${address} \n`)
45
46
// Counter for SNo of final output
47
let i = 1
48
49
// Loop through all tokens with non-zero balance
50
for (token of nonZeroBalances) {
51
52
// Get balance of token
53
let balance = token['tokenBalance']
54
55
const metadataParams = JSON.stringify({
56
"jsonrpc": "2.0",
57
"method": "alchemy_getTokenMetadata",
58
"params": [
59
`${token['contractAddress']}`
60
],
61
"id": 42
62
});
63
64
const metadataConfig = {
65
method: 'post',
66
url: baseURL,
67
headers: {
68
'Content-Type': 'application/json'
69
},
70
data : metadataParams
71
};
72
73
// Get metadata of token
74
axios(config)
75
.then(metadata => {
76
// Compute token balance in human-readable format
77
balance = balance/Math.pow(10, metadata['decimals']);
78
balance = balance.toFixed(2);
79
80
// Print name, balance, and symbol of token
81
console.log(`${i++}. ${metadata['name']}: ${balance}
82
${metadata['symbol']}`)
83
})
84
.catch(error => console.log('error', error))
85
}
86
})
87
.catch(error => console.log('error', error));
Copied!
1
// Wallet address
2
const address = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'
3
​
4
// Alchemy URL
5
const baseURL = `<-- ALCHEMY APP HTTP URL -->`;
6
​
7
const raw = JSON.stringify({
8
"jsonrpc": "2.0",
9
"method": "alchemy_getTokenBalances",
10
"headers": {
11
"Content-Type": "application/json"
12
},
13
"params": [
14
`${address}`,
15
"DEFAULT_TOKENS",
16
],
17
"id": 42
18
});
19
​
20
const requestOptions = {
21
method: 'POST',
22
body: raw,
23
redirect: 'follow'
24
};
25
​
26
// Make the request and print the formatted response:
27
fetch(baseURL, requestOptions)
28
.then(response => {
29
30
// Get balances
31
const balances = response['data']['result']
32
33
// Remove tokens with zero balance
34
const nonZeroBalances =
35
balances['tokenBalances'].filter(token => {
36
return token['tokenBalance'] !== '0'
37
})
38
​
39
console.log(`Token balances of ${address} \n`)
40
41
// Counter for SNo of final output
42
let i = 1
43
44
// Loop through all tokens with non-zero balance
45
for (token of nonZeroBalances) {
46
47
// Get balance of token
48
let balance = token['tokenBalance']
49
50
const metadataRaw = JSON.stringify({
51
"jsonrpc": "2.0",
52
"method": "alchemy_getTokenMetadata",
53
"headers": {
54
'Content-Type': 'application/json'
55
},
56
"params": [
57
`${token['contractAddress']}`
58
],
59
"id": 42
60
});
61
62
const metadataOptions = {
63
method: 'POST',
64
body: metadataRaw
65
redirect: 'follow',
66
};
67
68
// Get metadata of token
69
fetch(baseUrl, metadataOptions)
70
.then(metadata => {
71
// Compute token balance in human-readable format
72
balance = balance/Math.pow(10, metadata['decimals']);
73
balance = balance.toFixed(2);
74
75
// Print name, balance, and symbol of token
76
console.log(`${i++}. ${metadata['name']}: ${balance}
77
${metadata['symbol']}`)
78
})
79
.catch(error => console.log('error', error))
80
}
81
})
82
.catch(error => console.log('error', error));
Copied!
Run the script again using:
1
node main.js
Copied!
You should obtain an output that looks something like this:
1
Token balances of 0xd8da6bf26964af9d7eed9e03e53415d37aa96045
2
​
3
1. Tether: 0.10 USDT
4
2. USD Coin: 5.00 USDC
5
3. WETH: 0.05 WETH
6
4. ApeCoin: 1.00 APE
7
5. Mirror Protocol: 0.00 MIR
8
6. Shiba Inu: 3.14 SHIB
9
7. Dai: 764324.64 DAI
10
8. Loopring: 1000.32 LRC
11
9. SushiSwap: 0.00 SUSHI
12
10. Axie Infinity: 0.02 AXS
13
11. Ethereum Name Service: 1143.54 ENS
14
12. OMG Network: 123638.06 OMG
15
13. Basic Attention Token: 17.47 BAT
16
14. dYdX: 0.52 DYDX
17
15. Mask Network: 1.00 MASK
18
16. 1inch Network: 5.00 1INCH
19
17. Livepeer: 2.26 LPT
20
18. Request: 126.00 REQ
21
19. HEX: 100.00 HEX
Copied!

Conclusion

Congratulations! You now know how to use the Alchemy Token API to get all tokens and token balances of any address on the Ethereum blockchain.
If you enjoyed this tutorial for how to get all tokens owned by an address, give us a tweet @AlchemyPlatform, or shoutout feedback to the authors @rounak_banik and @ankg404!
Don't forget to join our Discord server to meet other blockchain devs, builders, and entrepreneurs.
Ready to start using the Alchemy Token API?
​Create a free Alchemy account and share your project with us!