Providers

Etherscan

The v2 API with one key for ten EVM chains and every operation. Five requests a second on the free tier. First choice whenever ETHERSCAN_API_KEY is set.
IDetherscan01 / 19ETHERSCAN_API_KEY
Provider

Etherscan

  • ethereum
  • base
  • arbitrum
  • optimism
  • polygon
  • bsc
  • avalanche
  • gnosis
  • linea
  • berachain
Chains
10
Auth
key
Operations
8 of 10
served 8 / 10

Operations

  • balancegetBalanceserved
  • historygetTxHistoryserved
  • tx detailgetTxDetailserved
  • utxosgetUtxosabsent
  • pubkeygetPubkeyabsent
  • contractgetContractInfoserved
  • tokensgetTokenBalancesserved
  • transfersgetTokenTransfersserved
  • gasgetGasDataserved
  • blockgetBlockInfoserved

Access

Createcreate("etherscan")
Import@agntn/explorers/providers/etherscan
Hostapi.etherscan.io/v2/api
Statusproviders on the docs worker

Address it

ts
import { create } from "@agntn/explorers";

const etherscan = await create("etherscan"); // ETHERSCAN_API_KEY from the environment
await etherscan.getBalance("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "base");

One key, ten chains. The provider sends the chain id with every request to api.etherscan.io/v2/api, so Base, Arbitrum, Optimism, Polygon, BSC, Avalanche, Gnosis, Linea and Berachain go through the same endpoint as Ethereum. Without the key the constructor throws AuthError before any request goes out.

What it reads

OperationAction
balanceaccount.balance
historyaccount.txlist, with startblock, endblock, sort, page, offset
one transactionproxy.eth_getTransactionByHash plus the receipt for status and fee
contractcontract.getsourcecode, with proxy and implementation
token holdingsaccount.addresstokenbalance
token transfersaccount.tokentx, optionally one contractaddress
gasgastracker.gasoracle, in gwei
blockproxy.eth_getBlockByNumber

Gotchas

  • Five requests a second on the free tier, and Etherscan counts them. Past that you get a rate limit message dressed up as a normal answer; the provider waits and retries that same backend, then an automatic selection moves the read to Blockscout, once.
  • On BNB Chain, Base, OP Mainnet, Avalanche and Gnosis the free plan refuses every read except contract source, and you find out at runtime. Token holdings need API Pro even on Ethereum. That's a PlanRestrictedError, and the fallback pass tries Blockscout if it serves the chain, which for BNB Chain it doesn't. Automatic selection remembers the refusal for an hour, so on the chains Blockscout serves the next read of that kind goes there first instead of paying for the same no again.
  • "No transactions found" is an empty list, not an error. Etherscan phrases an empty page as a failure, which is silly, and the provider knows the phrasing.
  • Amounts arrive as decimal strings and stay strings. Token decimals come with each transfer row.

Where it lives

src/providers/etherscan.ts.