Frontend URL Builder¶
Every client exposes a .urls property that generates human-facing explorer
links for addresses, transactions, tokens, and blocks.
async with AsyncBlockpartyClient(chain_id=8453) as client:
print(client.urls.address("0x88D19A...")) # https://basescan.org/address/0x88D19A...
print(client.urls.tx("0xabc123...")) # https://basescan.org/tx/0xabc123...
print(client.urls.token("0x4200...0006")) # https://basescan.org/token/0x4200...
print(client.urls.block(7796207)) # https://basescan.org/block/7796207
print(client.urls.blocks()) # https://basescan.org/blocks
.urls always returns URLs for the preferred (first) explorer in the
client’s provider list.
URLs from the actual provider¶
After a fallback, the preferred explorer may not be the one that answered.
Use .urls_for(resp.provider) to get URLs matching the explorer that
actually served the response:
resp = await client.get_internal_transactions(address="0x...", limit=10)
print(resp.provider) # "blockscout" (after Etherscan failed)
# Preferred explorer — stable, always the same
print(client.urls.tx(resp.result[0].hash))
# → https://basescan.org/tx/0xabc...
# Actual provider — matches who answered
print(client.urls_for(resp.provider).tx(resp.result[0].hash))
# → https://base.blockscout.com/tx/0xabc...
The pool version takes chain_id as the first argument:
resp = await pool.get_internal_transactions(chain_id=8453, address="0x...")
urls = pool.urls_for(8453, resp.provider)
Passing None (or an unrecognized type) falls back to the preferred
explorer, so client.urls_for(None) is equivalent to client.urls.
Routescan URL behavior¶
Routescan URLs prefer vanity hostnames (e.g. basescan.routescan.io) when
available in the chain registry. When no vanity hostname exists, URLs fall back
to the generic pattern (routescan.io/address/0x...?chainid=8453).
Block URLs (/block/N) always include chainid even on vanity hosts,
per Routescan’s requirements.
Testnet chains use testnet.routescan.io as the generic hostname.