aiochainscan
Provides access to Ethereum blockchain data via supported explorer APIs, enabling queries for balances, transactions, blocks, contracts, token transfers, logs, gas prices, and network information.
Supports querying Optimism blockchain data through supported explorer APIs, including balances, transactions, blocks, contracts, tokens, and logs.
Supports querying Polygon blockchain data through supported explorer APIs, including balances, transactions, blocks, contracts, tokens, and logs.
aiochainscan
aiochainscan reads on-chain history from public block explorers across 85
chains through one async client — and hands it back usable, not raw. Ask for an
address's transactions and you get the complete history, not the first page of
provider JSON that you then have to stitch, decode and wrap in retries
yourself.
async with ChainscanClient.from_config('blockscout', 'ethereum') as client:
transactions = await client.get_all_transactions(address) # every page, or an exceptionThree things it does for you instead of leaving them as homework:
Pagination.
get_all_*walks to the end. By default the result is guaranteed complete: every matching record, or an exception — never a silently truncated page.Decoding. ABI decoding of calldata and event logs is built in and needs no extra dependency — no
eth-abi, noweb3.Failures. Rate limiting, retries, one shape across providers, and optional failover between them.
It runs on free access: 8 chains need no API key at all, BSC works on NodeReal's free tier, and the base install pulls four dependencies.
Status: stable public API (1.x). The public surface is
ChainscanClient; provider coverage differs by scanner and endpoint. Released changes are listed in the changelog.
Is this the right tool?
Reading history — every transaction, transfer, internal call or log an address ever touched, decoded, without running an indexer or paying for one: this library.
Reading live state or sending transactions — contract calls in a hot path, signing, nonces, mempool: use an RPC client such as
web3.py.eth_callexists here, but as a convenience on top of an explorer, not as a node client.Arbitrary queries over a whole chain — "every address that did X in 2024": that is an indexer or a warehouse, not an explorer API.
Related MCP server: DuckChain MCP Server
Installation
Python 3.12 or newer is required:
pip install aiochainscanThe base install is dependency-light (httpx, orjson, tenacity, aiolimiter) and needs no extras to decode ABI calldata, checksum addresses, or run the MCP server's default keyless scanner. Extras are installed only when needed:
Extra | Adds |
| Rust accelerator for bulk ABI decoding (separate distribution) |
| Polars DataFrame exports |
| MCP server integration |
| HTTP/2 support; disabled by default |
| Pure-Python Keccak fallback |
pip install "aiochainscan[data]"Try it in one command
The shortest end-to-end run — an address's transaction history to CSV, keyless, no checkout:
curl -O https://raw.githubusercontent.com/VaitaR/aiochainscan/main/examples/02_export_to_csv.py
python 02_export_to_csv.py 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 --allThe recipe says what it exports, what it does not, and how it behaves when a provider refuses.
Quick start
Blockscout is used without an API key. Its public instances are shared
infrastructure: they apply their own rate limiting and may answer a burst of
requests with 403 or a bot-protection page. For unattended or high-volume
work, configure Etherscan (or a self-hosted Blockscout instance) instead — or
put both behind a
failover pool.
import asyncio
from aiochainscan import ChainscanClient
async def main() -> None:
address = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' # vitalik.eth
async with ChainscanClient.from_config('blockscout_v2', 'ethereum') as client:
balance = await client.get_balance(address)
transactions = await client.get_transactions(address)
print(balance) # native balance as a base-unit string
print(transactions) # one provider page
asyncio.run(main())Etherscan requires an API key. Pass it explicitly or set ETHERSCAN_KEY:
export ETHERSCAN_KEY='your-api-key'async with ChainscanClient.from_config('etherscan', 'ethereum') as client:
block = await client.get_block(20_000_000)from_config also accepts a base URL instead of a chain name, which points the
client at a self-hosted Blockscout or an Etherscan proxy — see the
API reference.
Providers
Scanner | Default version | Authentication | Chains | Methods |
| v2 | API key | 61 | 33/33 |
| v1 | None for public instances | 32 | 31/33 |
| v2 | None for public instances | 32 | 11/33 |
| v1 | API key ( | BSC only | 25/33 |
Thirty-three chains need no API key at all — every Blockscout instance
(Ethereum, Optimism, Gnosis, Polygon, Base, Arbitrum, Scroll, Sepolia, Mode,
Astar, Rootstock, ZKsync Era and twenty more), plus BSC through NodeReal's free
tier. Etherscan's 61 are the chains its keyless GET /v2/chainlist registry
listed on 2026-09-11; aiochainscan.registry_sync.sync_etherscan_chains() is
an opt-in call that re-reads that registry at runtime, so a chain Etherscan
adds after a release is constructible without waiting for one.
On Etherscan a free key's reach depends on the endpoint rather than the chain,
and BSC has no Blockscout instance at all — the measured details, and the full method list, are in the
API reference.
aiochainscan scanners prints the same table for your own environment,
including which keys are configured.
Complete data, or an exception
Page-returning methods (get_transactions, get_logs, get_token_holders)
return one page. get_all_* collects every page and iter_*_streaming yields
batches without materializing the result.
Both take guarantee_complete, defaulting to True: every matching record, or
an exception. Explorers cap a result window and answer a capped query with a
short page indistinguishable from the end of the data — so the library detects
the cap and splits the block range until every part fits, instead of handing
you a partial history that looks complete.
# Complete, or an exception — the default.
transfers = await client.get_all_token_transfers(address)
# Opt out: fewer requests on wide ranges, truncation possible and silent.
transfers = await client.get_all_token_transfers(address, guarantee_complete=False)
# Constant memory for large histories.
async for batch in client.iter_transactions_streaming(address, batch_size=1_000):
await store(batch)When completeness cannot be reached the call raises PaginationDataLossError
or CompletenessUnavailableError rather than returning part of the data; the
second names the providers that can serve the request whole. Full contract,
failover-pool semantics and costs:
Pagination, completeness and failover.
One shape across providers
Provider payloads differ field by field (blockNumber vs block_number,
nested from objects vs flat strings). The normalized surface returns the same
frozen dataclasses whichever provider answered:
txs = await client.get_transactions_normalized(address)
txs[0].hash, txs[0].block_number, txs[0].value_wei # str, int, int (wei)get_*_normalized, get_all_*_normalized and iter_*_normalized exist for
transactions, token transfers, internal transactions and logs. Everything else
stays provider-native.
Every scalar an explorer returns is a string — wei amounts, hex numbers, unix timestamps. Module-level helpers convert them exactly, with no float step:
from aiochainscan import hex_to_int, to_decimal_amount, wei_to_ether
wei_to_ether('1500000000000000000') # Decimal('1.5') — exact, never float
to_decimal_amount('1500000', decimals=6) # Decimal('1.5') — USDC-style tokens
hex_to_int('0x1a') # 26 — hex string, decimal string or intDecoding calls and events
Explorers return calldata as an opaque hex blob. Decoding it into a function
name and named arguments is part of the base install — abi_pure.py implements
the whole ABI spec in pure Python, so nothing beyond the four runtime
dependencies is needed. pip install "aiochainscan[fastabi]" swaps in a Rust
backend for the same results, faster; it is worth it for bulk work and
irrelevant for single decodes.
With a contract address, the ABI is fetched for you:
contract = await client.get_contract(token_address)
async for event in contract.iter_events('Transfer', limit=100):
print(event.args['from'], event.args['to'], event.args['value'])With an ABI you already hold, decode directly — no client, no network:
from aiochainscan.decode import decode_transaction_input
decoded = decode_transaction_input(transaction, abi)
decoded['decoded_func'] # 'transfer'
decoded['decoded_data'] # {'to': '0x…', 'amount': 1000000000000}Two things worth knowing. get_transaction() returns the provider's raw
payload — it does not decode on its own. And a type this library cannot decode
raises AbiTypeNotSupportedError rather than returning an empty result, so a
gap never looks like undecodable calldata. See the
SmartContract guide.
ENS
ENS methods are available for Ethereum mainnet. Provider capabilities differ:
Blockscout v2 serves reverse lookup from its own address metadata, while
forward resolution reads the ENS registry over eth_call and therefore needs
a scanner that declares it (etherscan, blockscout v1). A scanner that does
not raises MethodNotDeclaredError rather than returning None — None
means the name (or the reverse record) does not exist.
name = await client.lookup_address(address)
address = await client.resolve_name('vitalik.eth')See the ENS guide.
For AI agents
An agent that should query chains runs the MCP server — 12 read-only tools over stdio, with an envelope that carries pagination and caveats the agent can act on:
uvx --from "aiochainscan[mcp]" aiochainscan mcpSetup, the tool table and the response contract: MCP server.
An agent that should write code against the library wants the packaged Agent Skill instead:
npx skills add VaitaR/aiochainscanThe skill (skills/aiochainscan/)
carries the rules that decide whether generated code is correct — single-page
versus complete history, exact Wei math, provider coverage — plus a provider
matrix and recipes. Agents that read Context7 get the
same guidance from
context7.json
without installing anything.
Errors
from aiochainscan import ChainscanRateLimitError, PaginationDataLossError
try:
transactions = await client.get_all_transactions(address)
except ChainscanRateLimitError:
raise # The configured retry policy was exhausted.
except PaginationDataLossError:
raise # The provider could not return a complete range safely.Most exceptions derive from ChainscanClientError, so one clause can bound a
call site; MethodNotDeclaredError and AbiTypeNotSupportedError subclass
ValueError instead, because both mean the caller asked for something this
configuration cannot serve. The full taxonomy is in the
API reference.
Documentation
Getting started — install, provider choice, recipes, limits
Examples — starting with a keyless recipe: an address's transaction history to CSV
API reference — providers, every call, conversions, error taxonomy
Development
git clone https://github.com/VaitaR/aiochainscan.git
cd aiochainscan
uv sync --extra dev
uv run pytest tests/ -q
uv run mypy aiochainscan --strict
uv run pre-commit run --all-filesSee CONTRIBUTING.md for the contribution workflow.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Blockchain analytics API for AI agents. Smart Money signals, wallet profiling, token analytics.
Blockchain analytics API for AI agents. Smart Money signals, wallet profiling, token analytics.
Read-only on-chain intelligence for AI agents on Base: balances, tokens, gas, tx status.
Read-only on-chain intelligence for AI agents on Base: balances, tokens, gas, tx status.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA comprehensive toolkit for building AI agents with blockchain capabilities, enabling interactions with multiple blockchain networks for tasks like wallet management, fund transfers, smart contract interactions, and cross-chain asset bridging.4GPL 3.0
- FlicenseNot gradedqualityDmaintenanceEnables comprehensive blockchain data analysis and exploration through the BlockScout API. Provides 56+ tools for transaction analysis, address exploration, token management, smart contract analysis, and market research across multiple blockchain networks.-
- AlicenseAqualityDmaintenanceDescription: EVM blockchain intelligence toolkit for AI agents. 20 tools for token prices, gas comparison, swap quotes, yield rates, honeypot detection, and transaction simulation across 5 EVM chains. Zero config, no API keys required.2630 npm3MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI models to interact with Blockscout API for blockchain data, including transactions, blocks, balances, and contract calls. Supports multiple endpoints for comprehensive blockchain exploration.4-