Skip to content
Visit Covalent docs on GitHub
Set theme to dark (⇧+D)
Covalent docs

Working with NFTs


NFTs represent ownership over digital or physical assets. The standard ERC20 contract interface is insufficient for tracking NFTs because each asset is distinct (non-fungible) whereas in the case of ERC20, all tokens are identical (fungible).

Endpoints Summary:

There are three endpoints to work with NFTs:

  • v1/{chain_id}/address/{address}/balances_v2/

    • Get token balances for address. Return a list of all ERC20 and NFT token balances including ERC721 and ERC1155 along with their current spot prices.
  • v1/{chain_id}/address/{address}/transactions_v2/

    • For a given address, return the transactions involved with it. The transactions are returned alongwith the decoded log events. If you specify a NFT contract for the address, the log event will contain the token_ids being moved around.
  • v1/{chain_id}/tokens/{contract_address}/nft_metadata/{token_id}/

    • Given a NFT contract at contract_address and a token_id, fetch the external metadata along with their owners.

Address balance

nftfalseWhen this is set to true, the response returns ERC721 and ERC1155 tokens as well
no-nft-fetchfalseWhen this is set to true, the response does not return the metadata associated with each NFT.

Address transactions

block-signed-at-ascfalseWhen set to true, sort the transactions in chronological ascending order.

NFT metadata

This endpoint is helpful if you want to retrieve metadata for a particular NFT token. Take for example:


I wish I was understood

{  "data": {    "items": [      {        "contract_decimals": 0,        "contract_name": "Meme Ltd.",        "contract_ticker_symbol": "MEMES",        "contract_address": "0xe4605d46fd0b3f8329d936a8b258d69276cba264",        "logo_url": "",        "type": "nft",        "balance": null,        "quote_rate": null,        "quote": null,        "nft_data": [          {            "token_id": "123",            "token_balance": null,            "token_url": "",            "external_data": {              "name": "I wish I was understood",              "description": null,              "image": "",              "external_url": "",              "attributes": [                {                  "trait_type": "Set",                  "value": "Artist Drop 8 - Fewocious"                },                {                  "trait_type": "Artist",                  "value": "Fewocious"                },                {                  "trait_type": "Type",                  "value": "Pop Surreal"                },                {                  "display_type": "date",                  "trait_type": "birthday",                  "value": 1609267020                },                {                  "trait_type": "Max Supply",                  "value": "100"                }              ]            },            "owner": null          }        ]      }    ],    "pagination": null  },  "error": false,  "error_message": null,  "error_code": null}


1. How do I render an address with a large number of NFTs?

Take for example Pranksy who owns a large number of NFTs at the address 0xd387a6e4e84a6c86bd90c158c6028a58cc8ac459. If you were to call the balances_v2 endpoint with nft=true - the API will time out because there's a lot of off-chain metadata to fetch.

Our recommendation is the following:

The general idea is to have a two-level hierarchy of balances when rendering the NFTs. This is similar to how a music player like iTunes first shows a list of albums and then you can drill down to a specific album to see the tracks.

In a similar vein, first quickly return all the NFTs and render them as top-level collections. You can get this data with nft=true and no-nft-fetch=true. At this point, you don't actually know how many tokens are within a collection, just that there might be some.

Second, when the user choses to drill down to a collection, you can render the token_ids that the address owns. For this you'll have to call the NFT metadata endpoint to get the current owner. Ofcourse, you'll have to discard all token_ids that the address does not own.