Skip to content

ERC-721 NFT Inspector

Paste an ERC-721 contract and token ID. Get name, symbol, tokenURI, and owner in one call, with the metadata resolved and previewed.

EthereumBaseBNB Smart ChainPolygonno signup · no wallet connect · free

Result

Fill in the form above and click "Inspect token" to see results here.

The one query that powered this

{
  "name":     dyn(nft.name()),
  "symbol":   dyn(nft.symbol()),
  "tokenURI": dyn(nft.tokenURI(id)),
  "owner":    dyn(nft.ownerOf(id))
}

One expression. Auto-resolved ABI, EIP-1967 unwound, Multicall3 batched. Run this in your own code →

What this tool does

The ERC-721 Inspector reads any ERC-721 NFT contract and returns the name, symbol, tokenURI, and current owner from one expression. It is built for developers and collectors who need to inspect a specific token without writing ABI files or chasing IPFS gateways by hand.

Key facts

  • Reads an ERC-721 token’s name(), symbol(), tokenURI(id), and ownerOf(id) in one expression, batched into a single round trip via Multicall3.
  • Unlike ERC-1155’s uri(), tokenURI(id) returns the final metadata URL already resolved by the contract, with no {"{id}"} placeholder substitution needed.
  • Resolves EIP-1967 transparent and beacon proxies automatically; roughly a third of production contracts use proxies, including most upgradeable ERC-721 collections.
  • Covers Ethereum, Base, BNB Smart Chain, and Polygon, with more EVM chains being added.

How to use it

  1. Paste the ERC-721 contract address into the form above.
  2. Enter the token ID you want to inspect, then pick a chain.
  3. Run the query and read the name, symbol, owner, tokenURI, and metadata in the result panel.

The result panel shows the collection name and symbol, the current owner address, the raw tokenURI(id) returned by the contract, the resolved metadata URL, and the read block number. Everything happens in one round trip to the contract.

What is happening under the hood

ERC-721 is simpler to query than ERC-1155: every token ID has its own owner and its own tokenURI, already resolved by the contract with no {id} placeholder to substitute. evmquery handles the contract reads in one expression. The frontend handles the gateway fetch for the metadata JSON.

{
"name": dyn(nft.name()),
"symbol": dyn(nft.symbol()),
"tokenURI": dyn(nft.tokenURI(id)),
"owner": dyn(nft.ownerOf(id))
}
  • name() and symbol() read the collection-level metadata exposed by the ERC-721 Metadata extension.
  • tokenURI(id) returns the final metadata URL for that specific token. evmquery resolves the contract ABI from verified source and decodes the typed result.
  • ownerOf(id) returns an address, while the other fields are strings. CEL maps need a single value type, so every field is wrapped in dyn(...), which yields a map<string, dyn> where each value serializes as its natural type (the owner comes back as a hex address).
  • Multiple reads are auto-batched by Multicall3, so the cost is one round trip regardless of how many fields you ask for.

Build this yourself

Each of the snippets below makes the same POST call to the evmquery REST API. The expression is the one shown above, with your contract address and inputs filled in.

REST (curl)

curl -X POST https://api.evmquery.com/api/v1/query \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chain": "evm_ethereum",
"schema": {
"contracts": { "nft": { "address": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D" } },
"context": { "id": "sol_int" }
},
"expression": "{ \"name\": dyn(nft.name()), \"symbol\": dyn(nft.symbol()), \"tokenURI\": dyn(nft.tokenURI(id)), \"owner\": dyn(nft.ownerOf(id)) }",
"context": { "id": 1 }
}'

Python

import requests
resp = requests.post(
"https://api.evmquery.com/api/v1/query",
headers={"x-api-key": "YOUR_API_KEY"},
json={
"chain": "evm_ethereum",
"schema": {
"contracts": {"nft": {"address": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D"}},
"context": {"id": "sol_int"},
},
"expression": (
'{ "name": dyn(nft.name()), "symbol": dyn(nft.symbol()),'
' "tokenURI": dyn(nft.tokenURI(id)), "owner": dyn(nft.ownerOf(id)) }'
),
"context": {"id": 1},
},
timeout=10,
)
print(resp.json()["result"])

TypeScript

const resp = await fetch("https://api.evmquery.com/api/v1/query", {
method: "POST",
headers: {
"x-api-key": process.env.EVMQUERY_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
chain: "evm_ethereum",
schema: {
contracts: {
nft: { address: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D" },
},
context: { id: "sol_int" },
},
expression:
'{ "name": dyn(nft.name()), "symbol": dyn(nft.symbol()), "tokenURI": dyn(nft.tokenURI(id)), "owner": dyn(nft.ownerOf(id)) }',
context: { id: 1n },
}),
});
const { result } = await resp.json();

The free tier has no monthly cap. Get a free API key to drop these snippets into your project.

When you would use this

  • Verifying provenance. Confirm who currently owns a specific token before you buy, accept as collateral, or feature it.
  • Auditing a new collection. Quickly verify a contract really implements ERC-721 and inspect the metadata URI before you list or integrate it.
  • Debugging an indexer. Compare the on-chain tokenURI(id) and ownerOf(id) results with what your indexer cached to find where it drifted.
  • Writing ERC-721 docs. Show your readers a working tokenURI and ownerOf example without making them set up a Hardhat console.

FAQ

What is ERC-721?

ERC-721 is the standard for non-fungible tokens. Each token ID on a contract is unique, has its own owner tracked by ownerOf(id), and typically points to its own metadata URI via tokenURI(id).

What is the difference between ERC-721 and ERC-1155?

ERC-721 gives every token ID its own owner and its own tokenURI, with no placeholder substitution needed. ERC-1155 lets one contract hold many token IDs that can be fungible or non-fungible, and its uri(id) returns a template with a literal {id} placeholder the client must substitute.

Why does tokenURI have no {id} placeholder to substitute?

The EIP-721 metadata extension defines tokenURI(uint256) as returning the final URL for that specific token, already resolved server-side by the contract. There is no client-side substitution step like the {id} template in EIP-1155.

Which chains are supported?

Ethereum, Base, BNB Smart Chain, and Polygon today. More EVM chains are being added on the evmquery backend. If you need a specific chain prioritized, contact support.

Does evmquery work with proxy contracts?

Yes. evmquery resolves EIP-1967 transparent and beacon proxies to their implementation automatically, so you call nft.tokenURI(id) against the proxy address and it works. Roughly a third of production contracts use proxies, including most upgradeable ERC-721 collections.

What if the metadata URI uses an IPFS gateway that times out?

The Inspector tries the URI as returned by the contract first. For ipfs:// URIs it falls back through a small list of public gateways. If none respond, the resolved URL is shown so you can open it directly or point your own application at a gateway you control.

Can I use this from my own application?

Yes. The same expression and contract address work against the public REST API. The free tier has no monthly cap, and a single inspection counts as one read because Multicall3 batches all the underlying calls into one round trip. Bring your own API key and the rate limit applied to this page no longer applies.

Limits and accuracy

  • The result reflects the latest block at the time of the read. There is no historical replay.
  • The demo is rate limited per browser. If you hit the limit, grab a free API key and the limit goes away.
  • Image previews are loaded directly from the metadata image URL. If the gateway throttles or the image is missing, the preview is silently hidden.
  • USD pricing, marketplace floor data, and royalty configuration are out of scope. evmquery returns raw on-chain values, not aggregated marketplace data.

The metadata fetch runs from your browser. Some collections gate metadata behind authenticated origins, in which case only the on-chain values are shown.

Run this query in your own code

No monthly cap on the free tier. No credit card needed.