Etherscan API
A way to access the etherscan.io api using promises. Fetch a diverse set of information about the blockchain.
Written in TypeScript, shipped as an ES module with bundled type declarations. Requires Node.js >= 20.
Mainnet
import { init } from 'etherscan-api';
const api = init('YourApiKey');
const balance = await api.account.balance('0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae');
console.log(balance);Example in the wild
Zero dependencies / custom HTTP transport
This library has no runtime dependencies — requests use Node's built-in
https module. If you need custom networking (a proxy, retries, a different
agent), pass your own transport as the 4th argument to init. It receives the
fully-qualified URL and must resolve with the parsed JSON body:
import { init } from 'etherscan-api';
// (url, { timeout, method, body }) => Promise<object>
// `method`/`body` are only set for the POST contract-verification endpoints;
// for read-only use you can ignore them.
async function request(url, { timeout, method = 'GET', body }) {
const res = await fetch(url, {
method,
body,
headers: body ? { 'Content-Type': 'application/x-www-form-urlencoded' } : undefined,
signal: AbortSignal.timeout(timeout),
});
return res.json();
}
const api = init('apikey', null, 10000, request);Security notes
- The API key travels in the request URL. Etherscan requires
apikeyas a query parameter, so it is part of every request URL (and of POST request URLs). Treat full request URLs as secrets: do not log them, and be careful with proxies, APM tools, and access logs that capture URLs. A custom transport receives the URL containing the key — never write it to logs verbatim. (The library itself never puts the URL or key into thrown errors.) - The default transport refuses cleartext
http://. Requests go tohttps://api.etherscan.ioover TLS with certificate validation on. If a request somehow targets anhttp://URL, the default transport rejects rather than sending the key unencrypted; pass{ allowInsecure: true }in the transport options only if you deliberately need cleartext (e.g. a local test server). - The default transport caps the response body at 50 MB to guard against a
memory-exhaustion response. Override with
maxResponseBytesin the transport options if you expect larger payloads.
Selecting a chain (Etherscan V2 / multichain)
Etherscan deprecated the V1 API on 2025-08-15. This library now talks to a
single base URL — https://api.etherscan.io/v2/api — and selects the network
with a chainid query parameter. One API key works across all chains.
Pass a chain name (or a numeric chainid) as the second argument to init:
import { init } from 'etherscan-api';
// apikey, chain, timeout
const api = init('YourApiKey', 'sepolia', 3000);Supported chain names:
| Name | chainid |
|---|---|
mainnet / homestead / ethereum |
1 |
sepolia |
11155111 |
holesky |
17000 |
arbitrum |
42161 |
optimism |
10 |
base |
8453 |
polygon |
137 |
bsc |
56 |
avalanche |
43114 |
Any other chain is reachable by passing its numeric chainid directly, e.g.
init('YourApiKey', 59144) for Linea.
Retired testnets (ropsten, rinkeby, kovan, goerli, morden,
arbitrum_rinkeby, avalanche_fuji) have been removed and now throw an
error with a helpful message — use sepolia or holesky instead.
Install
npm install etherscan-api --saveAPI Documentation
Development workflow
Source lives in ./src (TypeScript) and compiles to ./lib (ES modules + .d.ts).
npm run build- compilessrc→libwithtscnpm run typecheck- type-checks without emitting (replaces the old linter)npm test- builds, then runs the fully mocked test suite (no API key required)npm run test:live- runs the tests against the real Etherscan APInpm run docs- generates the API docs with TypeDocnpm run preversion- type-check + changelog before tagging a releasenpm run changelog- generates a changelog and pushes it