ERC-20 Token Due Diligence — Holders, Contract Risks, Liquidity avatar

ERC-20 Token Due Diligence — Holders, Contract Risks, Liquidity

Pricing

from $3.50 / 1,000 result items

Go to Apify Store
ERC-20 Token Due Diligence — Holders, Contract Risks, Liquidity

ERC-20 Token Due Diligence — Holders, Contract Risks, Liquidity

Token intelligence on Base, Ethereum, Arbitrum, Optimism, Polygon and 9 more Blockscout chains: supply, price, market cap, top holders with concentration metrics, verified-contract facts and owner powers (mint/pause/blacklist/fees), whale transfers, DexScreener liquidity and pair age, risk flags.

Pricing

from $3.50 / 1,000 result items

Rating

0.0

(0)

Developer

Samat Makatov

Samat Makatov

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Give it token contract addresses and get one due-diligence JSON per token: supply, price, market cap, top holders with concentration metrics (largest holder, top-10/20/50 share, burned share, contracts vs wallets), verified-contract facts and owner powers read from the ABI (mint, pause, blacklist, fee/max-tx setters, upgradeability, meme-token controls), whale transfers, DexScreener liquidity, volume and pair age, and a deterministic list of risk flags. Works on Base, Ethereum, Arbitrum, OP Mainnet, Polygon, Gnosis, ZKsync, Scroll, Celo, Unichain, Soneium, Mode, Ink, World Chain and two testnets (DexScreener market data on all of them except Gnosis, Mode and the testnets). Also finds contract addresses by token name. No API key, no proxy, no browser.

Built for agents and analysts who must decide "is this token safe to list / accept / hold?" in one call.

Use cases

  • Listing & treasury checks — before accepting a token as payment or listing it: verified? owner can mint or blacklist? top-10 own 90 %? liquidity younger than a week?
  • Rug-pull triage — flags such as single_holder_over_50pct, thin_liquidity_under_10k, owner_can_change_fees, meme_token_style_controls.
  • Whale watching — minTransferUsd: 100000 returns only large transfers with labelled sender/receiver (exchanges, pools).
  • Holder analytics — top 500 holders with labels and USD value for airdrop planning, competitor research, cap-table-like snapshots.
  • Market monitoring — daily run over your watchlist: price, 24h volume, liquidity, buys/sells per DEX pool.
  • Contract discovery — mode: "search" turns "aerodrome" into the right contract address (and shows look-alike spam tokens with likelySpam: true).

Input

FieldTypeDefaultNotes
modetokens / searchtokenstokens = full analysis per contract; search = find tokens by name/symbol.
tokensstring[]—Contract addresses (mode=tokens). Letter case does not matter; an address listed twice is analyzed (and charged) once. Values that are not 0x addresses are skipped and listed in SUMMARY.errors (not charged); a run with no 0x address at all is refused (use mode: "search" to find a token by name).
queriesstring[][]Names/symbols (mode=search).
searchLimitint 1–10010Results per query. Every search hit is one dataset item, charged like an analyzed token. Queries that differ only in letter case are searched once.
searchTokenTypeall / ERC-20 / ERC-721 / ERC-1155allSearch filter.
chainenumbaseOne key from Reference → Chains (ethereum, not eth): the platform refuses a value outside that list before the run starts.
holdersLimitint 0–50050Top holders (pages of 50). 0 = skip holders and concentration.
transfersLimitint 0–20020Recent transfers kept.
minTransferAmountnumber0Keep only transfers ≥ this many tokens. Filtered server-side by the explorer, so matches can be days old on busy tokens.
minTransferUsdnumber0Keep only transfers ≥ this USD value (explorer price, converted to a token amount for the server-side filter). Ignored with a warning if the token is unpriced.
transferScanPagesint 1–10010Most transfer pages (50 each) read per token when a size filter or time window is set.
transferScanHoursnumber0Only transfers from the last N hours (e.g. 24). 0 = no time limit.
includeContractbooltrueVerification, compiler, license, proxy, creator, tags, ABI capability scan.
includeDexPairsbooltrueDexScreener pools + market summary.
dexPairsLimitint 1–505Pools kept in dexPairs (by liquidity).
fieldsstring[][]Keep only these top-level fields, in this order. address, chain, symbol, found, fetchedAt (and query in mode=search) are always kept and come first unless you list them. Letter case does not matter; an unknown name is left out with a note in the status message ("did you mean …?"), and a run where none of the names exists in that mode's rows is refused before anything is charged.
requestDelayMsint 0–5000250Minimum gap between two requests to the same host (explorer, DexScreener); values below 250 are raised to 250 (both publish 300 requests/min per IP). At most 2 requests per host wait for an answer at once.

Original inputs (tokens, chain, holdersLimit, transfersLimit) keep their meaning.

Reference

Chains

chainNetworkChain IDDexScreener market data
ethereumEthereum mainnet1yes
baseBase8453yes
arbitrumArbitrum One42161yes
optimismOP Mainnet10yes
polygonPolygon PoS137yes
gnosisGnosis Chain100no (not indexed by DexScreener)
zksyncZKsync Era324yes
scrollScroll534352yes
celoCelo42220yes
unichainUnichain130yes
soneiumSoneium1868yes
modeMode34443no
inkInk57073yes
worldchainWorld Chain480yes
sepolia, base-sepoliatestnets11155111 / 84532no

Contract capabilities (contract.capabilities)

Derived from function names in the verified ABI (null when the contract is not verified).

FieldTrue when the ABI has…
canMintmint, mintTo, issue, mint* (state-changing)
canBurnOthersburnFrom, destroyBlackFunds, forceBurn…
canPausepause, unpause, setPaused
canBlacklistblacklist*, freeze*, blockAccount, setBots…
hasOwnerowner, transferOwnership, renounceOwnership
canSetFeesset*Fee, set*Tax
hasMaxTxLimitsset*MaxTx, set*MaxWallet…
hasPermitEIP-2612 permit
isUpgradeableupgradeTo, upgradeToAndCall, implementation
suspiciousFunctionsopenTrading, excludeFromFee, manualSwap, rescueTokens… (meme-token launch tooling)

Flags (flags[])

FlagMeaning
flagged_scam_by_explorerBlockscout reputation ≠ ok / is_scam.
unverified_contractNo verified source.
upgradeable_or_proxyProxy or upgrade functions — logic can change.
owner_can_mint / owner_can_pause / owner_can_blacklist / owner_can_change_fees / has_max_tx_or_wallet_limitsFrom the ABI scan.
meme_token_style_controls≥ 3 suspicious launch-tooling functions.
single_holder_over_50pct / single_holder_over_20pctLargest non-burn holder share (often a staking/escrow contract — check largestHolderLabel).
top10_hold_over_80pctConcentration.
under_100_holdersTiny holder base.
no_dex_liquidity_found / thin_liquidity_under_10k / liquidity_under_1pct_of_mcapMarket depth (skipped for tokens that are mostly quote assets like USDC/WETH).
pair_younger_than_7dNewest liquidity.
no_website_or_socialsDexScreener profile has no links.
verified_less_than_7d_agoFresh verification.

Flags are a triage checklist, not a verdict.

Examples

1. Vet a token before listing it (Base)

{ "tokens": ["0x940181a94A35A4569E4529A3CDfB74e38FD98631"], "chain": "base", "holdersLimit": 100, "transfersLimit": 20 }

2. Whale transfers ≥ $50k for PEPE (Ethereum)

{ "tokens": ["0x6982508145454Ce325dDbE47a25d4ec3d2311933"], "chain": "ethereum", "holdersLimit": 0, "transfersLimit": 50, "minTransferUsd": 50000, "transferScanHours": 72, "includeContract": false, "includeDexPairs": false }

3. Holder snapshot: top 500 holders with labels

{ "tokens": ["0x…"], "chain": "arbitrum", "holdersLimit": 500, "transfersLimit": 0, "includeContract": false, "includeDexPairs": false, "fields": ["holdersCount", "holderConcentration", "topHolders"] }

4. Daily market monitor over a watchlist, compact output

{ "tokens": ["0x…", "0x…", "0x…"], "chain": "base", "holdersLimit": 10, "transfersLimit": 0, "includeContract": false, "dexPairsLimit": 3, "fields": ["priceUsd", "marketCapUsd", "volume24hUsd", "market", "dexPairs", "flags"] }

5. Find the real contract behind a name

{ "mode": "search", "queries": ["aerodrome", "virtual"], "chain": "base", "searchLimit": 5, "searchTokenType": "ERC-20" }

Output

One item per token (trimmed real example, AERO on Base):

{
"address": "0x940181a94A35A4569E4529A3CDfB74e38FD98631", "chain": "base", "chainId": 8453,
"explorerUrl": "https://base.blockscout.com/token/0x940181a94A35A4569E4529A3CDfB74e38FD98631",
"found": true, "name": "Aerodrome Finance", "symbol": "AERO", "type": "ERC-20", "decimals": 18, "reputation": "ok",
"totalSupply": 1978450301.48, "holdersCount": 833725, "transfersCount": 23933,
"priceUsd": 0.566, "marketCapUsd": 559998827.4, "volume24hUsd": 18574709.8, "fdvUsd": 1120244065.1,
"contract": {
"isVerified": true, "verifiedAt": "2023-12-27T19:32:58Z", "contractName": "Aero", "compiler": "0.8.19+commit.7dd6d404", "license": "none",
"proxyType": null, "implementations": [], "creator": "0xe83f922C34A1962e9aE9F52B59e18239764f2818", "creationTxHash": "0x5727…", "isScam": false, "tags": [],
"capabilities": { "functions": 18, "canMint": true, "canBurnOthers": false, "canPause": false, "canBlacklist": false, "hasOwner": false, "canSetFees": false, "hasMaxTxLimits": false, "hasPermit": true, "isUpgradeable": false, "suspiciousFunctions": [] }
},
"holderConcentration": { "holdersAnalyzed": 50, "largestHolderShare": 0.5002, "largestHolderLabel": "VotingEscrow", "top10Share": 0.6675, "top20Share": 0.7578, "top50Share": 0.8341, "contractShareInTop": 0.5689, "burnedShare": 0, "eoaHoldersInTop10": 8 },
"topHolders": [{ "rank": 1, "address": "0xeBf418Fe2512e7E6bd9b87a8F0f294aCDC67e6B4", "label": "VotingEscrow", "isContract": true, "isBurn": false, "balance": 989616587.86, "share": 0.5002, "usdValue": 560343673.23 }],
"transfersScanned": 20, "largeTransferFilter": null,
"transferScan": { "method": "latest", "stopReason": "limit", "pagesScanned": 1, "transfersScanned": 20, "matched": 20, "coveredFrom": "2026-09-12T23:41:05Z", "coveredTo": "2026-09-12T23:43:20Z", "coveredHours": 0.04, "windowHours": null, "minAmountTokens": null },
"recentTransfers": [{ "hash": "0xa014…", "timestamp": "2026-09-12T23:43:17Z", "from": "0x3B86…", "fromLabel": "CL100-WETH/B3 Pool Gauge", "to": "0x6104…", "toLabel": "ERC1967Proxy", "amount": 0.135, "usdValue": 0.08, "method": "0x62402c0e", "isMint": false, "isBurn": false }],
"lastTransferAt": "2026-09-12T23:43:17Z",
"market": { "pairs": 30, "quotePairs": 12, "isMostlyQuoteAsset": false, "totalLiquidityUsd": 46109898.91, "totalVolume24hUsd": 7177661.31, "bestPriceUsd": 0.5629, "oldestPairAt": "2023-08-28T05:07:27Z", "websites": ["https://aerodrome.finance/docs"], "socials": [{ "type": "twitter", "url": "https://x.com/aerodromefi" }] },
"dexPairs": [{ "dexId": "aerodrome", "labels": [], "pairAddress": "0x6cDc…", "url": "https://dexscreener.com/base/0x6cdc…", "quoteSymbol": "USDC", "priceUsd": 0.5629, "liquidityUsd": 33953838.44, "volume24hUsd": 965075, "buys24h": 251, "sells24h": 1654, "change1h": -0.45, "change24h": -0.63, "pairCreatedAt": "2023-09-07T22:50:45Z", "ageDays": 1101 }],
"flags": ["owner_can_mint", "single_holder_over_50pct"],
"warnings": [],
"source": "blockscout+dexscreener", "sourceUrl": "https://base.blockscout.com/api/v2/tokens/0x9401…", "fetchedAt": "2026-09-12T23:43:20.620Z"
}
FieldDescription
foundAlways true on dataset items (rows have no error field). Addresses that are not a token on this chain, invalid addresses and lookups that failed are not dataset items (not charged): they are listed in the SUMMARY record (notFound, errors with the reason, notFoundCount, errorCount) and in the run's status message. The run fails only if every input failed.
name, symbol, type, decimals, icon, reputationToken metadata; type is ERC-20 / ERC-721 / ERC-1155.
totalSupply, holdersCount, transfersCountSupply in token units; explorer counters.
priceUsd, marketCapUsd, volume24hUsd, fdvUsdExplorer (CoinGecko-backed) price data; fdvUsd = supply × price.
contractVerification facts, proxy/implementations, creator, tags, capabilities (see Reference). null when includeContract:false.
holderConcentrationShares of total supply; burn addresses excluded from "largest". null when holders skipped/failed.
topHolders[]Rank, address, label, contract/burn flags, balance, share, USD.
transfersScanned, largeTransferFilter, recentTransfers[], lastTransferAtTransfers with labelled parties, isMint/isBurn. The Transfers dataset view shows them one row per transfer.
transferScanHow the transfers were found and which time range was checked: method (server-filter = explorer filtered by size over the whole history, client-scan = latest pages filtered locally, latest = no filter), coveredFrom/coveredTo/coveredHours, pagesScanned, transfersScanned, matched, stopReason (limit = enough matches, window = reached transferScanHours, history = no older transfers, pageCap = hit transferScanPages), minAmountTokens. Also in the SUMMARY record.
market, dexPairs[]DexScreener summary (pairs where the token is the base asset) and top pools.
flags[], warnings[]Triage flags; parts that could not be read (e.g. the holder list) and notes — the item is still delivered and charged, and the status message counts such items ("1 with warnings").

mode: "search" items: query, address, chain, chainId, explorerUrl, found, name, symbol, type, decimals, icon, reputation, totalSupply, holdersCount, priceUsd, marketCapUsd, volume24hUsd, likelySpam, source, sourceUrl, fetchedAt. Search hits without a contract address are left out.

Dataset views: Overview, Risk & concentration, Top holders (one row per holder), Transfers (one row per transfer) and Transfer scan coverage. Every field has a title, description and example in the dataset schema, so agents can read the output shape.

Status message and SUMMARY. Every run ends with one status message, e.g. 3 token(s) saved · 1 with warnings (…) · 1 not found (see SUMMARY), and a SUMMARY record in the run's key-value store: delivered, items, itemsWithWarnings, notFound, errors, notAnalyzed (inputs a stop left out, with notAnalyzedReason), tokens (per token: symbol, transfers kept, transferScan, warnings), notes (corrected or ignored fields, duplicate inputs) and throttledResponses (HTTP 429 answers the actor waited out).

Use it from code / agents

curl -X POST "https://api.apify.com/v2/acts/yadroo~base-token-intel/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"tokens":["0x940181a94A35A4569E4529A3CDfB74e38FD98631"],"chain":"base"}'
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('yadroo/base-token-intel').call({ tokens: ['0x940181a94A35A4569E4529A3CDfB74e38FD98631'], chain: 'base' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
from apify_client import ApifyClient
client = ApifyClient(token)
run = client.actor("yadroo/base-token-intel").call(run_input={"tokens": ["0x940181a94A35A4569E4529A3CDfB74e38FD98631"], "chain": "base"})
items = client.dataset(run["defaultDatasetId"]).list_items().items

MCP: add https://mcp.apify.com to your MCP client and call the yadroo/base-token-intel tool with the same JSON.

Pricing

Pay per event: $0.001 per run start + $0.005 per token analyzed (mode=tokens) — search results are charged at the same per-item rate, so keep searchLimit small. Only tokens actually analyzed (and search hits) are charged — invalid addresses, tokens not found on the chain and failed lookups are free and listed in SUMMARY. Vetting 5 tokens costs $0.026; a daily watchlist of 50 tokens costs $0.251 per day.

Store discounts: Bronze −10 %, Silver −20 %, Gold and above −30 % on the per-item price; the start event is the same on every plan; platform usage is included.

Maximum cost per run is respected: the actor works out how many items your limit still pays for, stops starting new tokens when it is reached, and ends with Stopped at your spending limit: N rows delivered (the tokens it did not reach are counted in SUMMARY.notAnalyzed, not charged).

Limits & FAQ

  • Rate limits — Blockscout and DexScreener both publish 300 requests/min per IP. The actor keeps well under it per host: one request start per requestDelayMs (at least 250 ms), at most 2 requests waiting for an answer at once. An HTTP 429 pauses that host for as long as its Retry-After (or rate-limit reset header) asks — without one 10 s, then 20 s, 40 s, 60 s for 429s in a row — and halves the pace to that host (gap up to 2 s; it eases back as answers come in). A token still refused after 4 tries (about 70 s of pauses) is not delivered and not charged, and neither is a token one of whose parts was refused; after 3 refused tokens in a row the run stops asking, says so in the status message and lists the rest as not analyzed (not charged) — run them again later. 5xx answers and timeouts are retried with backoff. No proxies are used. Keyless Blockscout access can answer 429 well below its published limit: on 02.10.2026 a run from an Apify IP got 429s after about 3 minutes of continuous use (about 80 requests/min).
  • Giant tokens — the explorer does not return the holder lists of the very largest tokens in time: USDC on Base (13 M holders) failed on every daily run since 18.09 (25 s per try) and also with 45 s on 02.10; WETH on Base (5 M holders) too. Such rows are still delivered and charged, with topHolders: [], holderConcentration: null and a warning that says so, and the status message counts them ("1 with warnings"). Use holdersLimit: 0 for such tokens: it saves about 50 s per token and the rest of the row (price, supply, holder count, contract, market) is the same.
  • Capacity — with the defaults one token takes about 5 s (2–20 s; measured 02.10.2026 on 26 Base tokens), plus about 50 s for a token whose holder list times out. A large list is more likely to be cut by the explorer's rate limit (above) than by the 900 s default timeout: about 25–30 tokens per run is a safe size; split longer watchlists into several runs.
  • Concentration caveat — the largest holder is often a staking, escrow, bridge or CEX contract; read largestHolderLabel and contractShareInTop before concluding. When the listed holders (burn and zero addresses aside) together hold more than 101 % of the explorer's total supply — 7 of 26 Base tokens checked on 02.10.2026: vault tokens, bridged DAI, and look-alike tokens that fake balances — every share and the concentration shares are left empty with a warning that names both numbers, and no share-based flag is raised.
  • Capabilities are name-based — a verified ABI is scanned by function names; unusual naming can produce false negatives/positives. Unverified contracts get capabilities: null and the unverified_contract flag.
  • Quote assets — for tokens that are mostly the quote side of pools (USDC, WETH) liquidity flags are suppressed (isMostlyQuoteAsset).
  • Whale-filter coverage — size filters (minTransferAmount/minTransferUsd) use Blockscout's advanced-filter endpoint (amount_from), so the explorer returns only large transfers and the scan reaches back days, not minutes (PEPE ≥ $50k with transfersLimit: 50: 50 matches going back ~5 h, where scanning the latest 200 transfers found 1). If an explorer rejects that endpoint, or the token is an NFT, the actor falls back to reading the latest transferScanPages pages and filtering them itself. On USDT-class tokens 500 transfers are under a minute, so the output then says method: client-scan, stopReason: pageCap, and adds a warning with the time actually covered. Always read transferScan.coveredFrom before concluding that there were no whale moves.
  • NFTs — ERC-721/1155 contracts work for supply, holders and transfers (amounts are item counts / token ids).
  • Errors — input mistakes (no 0x address, no queries, unknown fields only) end the run at once with a clear status message, before any request; per-token failures never stop the run.
  • Run timeout — the actor saves each token as soon as it is analyzed and stops starting new tokens shortly before the run timeout: the run ends SUCCEEDED with Stopped before the run timeout: N rows saved, and the token in progress is not delivered or charged. A migration or restart of the run never stores or charges a token twice.
  • Roadmap — honeypot simulation, LP-lock detection, holder growth over time.

Made by Yadroo. Siblings: wallet-intel · dexscreener-tokens · ens-resolver · coingecko-markets · defillama-protocols