What this tool does
The Chainlink Price Feed Reader reads any Chainlink aggregator contract and returns the feed description, the latest answer scaled to a human-readable price, and the raw decimals value from one expression. It is built for developers and analysts who need a current price without shipping the Chainlink ABI or hand-rolling the formatUnits math.
How to use it
- Paste the Chainlink aggregator address into the form above.
- Pick the chain the aggregator is deployed to.
- Run the query and read the pair description, latest answer, and decimals in the result panel.
The result panel shows the pair description (for example “ETH / USD”), the latest price formatted with the aggregator’s own decimals, and the raw decimals value for reference.
What is happening under the hood
Every Chainlink aggregator exposes description(), latestAnswer(), and decimals(). They are independent reads, so a naive client makes three sequential eth_call round trips. evmquery batches them into one Multicall3 call and decodes the typed results in a single response.
cel.bind(d, feed.decimals(), {
"description": feed.description(),
"answer": string(formatUnits(feed.latestAnswer(), d)),
"decimals": string(formatUnits(d, 0))
})
cel.bind(d, feed.decimals(), …)readsdecimals()once and reuses it. We need it twice: once to display, once to scalelatestAnswer()into a human-readable price.description()returns the pair label directly, such as “ETH / USD”.formatUnits(feed.latestAnswer(), d)divides the raw integer answer by10 ** decimalsserver-side, so a raw answer of350012000000at 8 decimals returns as"3500.12"ready for display.- All three results are returned as strings so they fit in the same map. CEL maps require their values to share a type, and
string(formatUnits(…))is the conversion path that works for both the smalldecimalsint and the largeanswervalue. - Multiple reads are auto-batched by Multicall3, so the cost is one round trip regardless of how many fields you ask for.
Build this yourself
Each of the snippets below makes the same POST call to the evmquery REST API. The expression is the one shown above with your aggregator address filled in. The example targets the ETH / USD feed on Ethereum.
REST (curl)
curl -X POST https://api.evmquery.com/api/v1/query \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chain": "evm_ethereum",
"schema": {
"contracts": { "feed": { "address": "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419" } }
},
"expression": "cel.bind(d, feed.decimals(), { \"description\": feed.description(), \"answer\": string(formatUnits(feed.latestAnswer(), d)), \"decimals\": string(formatUnits(d, 0)) })"
}'
Python
import requests
resp = requests.post(
"https://api.evmquery.com/api/v1/query",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"chain": "evm_ethereum",
"schema": {
"contracts": {"feed": {"address": "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"}},
},
"expression": (
"cel.bind(d, feed.decimals(), {"
' "description": feed.description(),'
' "answer": string(formatUnits(feed.latestAnswer(), d)),'
' "decimals": string(formatUnits(d, 0))'
" })"
),
},
timeout=10,
)
print(resp.json()["result"])
TypeScript
const resp = await fetch("https://api.evmquery.com/api/v1/query", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.EVMQUERY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
chain: "evm_ethereum",
schema: {
contracts: { feed: { address: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419" } },
},
expression:
'cel.bind(d, feed.decimals(), { "description": feed.description(), "answer": string(formatUnits(feed.latestAnswer(), d)), "decimals": string(formatUnits(d, 0)) })',
}),
});
const { result } = await resp.json();
The free tier has no monthly cap. Get a free API key to drop these snippets into your project.
Example aggregators
- ETH / USD (Ethereum) —
0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419 - ETH / USD (Base) —
0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70
Swap the address and chain in any of the snippets above to read a different pair or a different chain.
When you would use this
- Pricing on-chain positions. Pull a live reference price into a treasury dashboard, a liquidation monitor, or a portfolio tracker without running your own oracle client.
- Sanity-checking a price before a trade. Confirm what an aggregator is currently reporting before you rely on it in a script or a bot.
- Backtesting and analytics. Read the current answer and decimals to validate assumptions before wiring up historical
latestRoundData()queries. - Writing developer docs. Show readers a working Chainlink read example without making them set up a node, an ABI file, or a wallet connection.
FAQ
What is a Chainlink price feed?
A Chainlink price feed is an on-chain aggregator contract that a network of independent node operators updates with the current market price for an asset pair, such as ETH / USD. Any contract or off-chain client can read the latest value directly from the aggregator without trusting a single source.
What is an aggregator contract?
The aggregator is the specific contract address you query. Each pair, such as ETH / USD or BTC / USD, has its own aggregator per chain. Chainlink also publishes proxy addresses that forward to the current aggregator, so the address you paste can be either and the read still resolves correctly.
What is the difference between latestAnswer and latestRoundData?
latestAnswer() returns just the current price as a raw integer. latestRoundData() returns the same price alongside the round ID and timestamps for staleness checks. This tool reads latestAnswer() because it is the simplest path to a price; if you need staleness data, adjust the expression to call latestRoundData() instead.
How does the decimals scaling work?
Chainlink aggregators store the price as an integer scaled by decimals(), commonly 8 for USD pairs and 18 for ETH pairs. The expression reads decimals() once, reuses it to scale latestAnswer() with formatUnits, and returns both the human-readable price and the raw decimals value so you can verify the scaling yourself.
Where do I find aggregator addresses?
Chainlink publishes the full list of feed and proxy addresses per chain at data.chain.link. Search for the pair you need, copy the proxy or aggregator address for your target chain, and paste it into the form above.
Which chains are supported?
The reader currently runs against Ethereum, Base, and BNB Smart Chain. Additional EVM chains are being added on the evmquery backend. If you need a specific chain prioritized, contact support.
Can I use this tool from my own application?
Yes. The same expression and aggregator address work against the public REST API. The free tier has no monthly cap, and a single read counts as one call because Multicall3 batches all the underlying calls into one round trip. Bring your own API key and the rate limit applied to this page no longer applies.
Limits and accuracy
- The result reflects the latest answer reported on-chain at the time of the read. There is no historical replay; use
latestRoundData()with a specific round ID for that. - Chainlink feeds update based on deviation thresholds and heartbeat intervals, not every block. A “latest” answer can be minutes old depending on the feed’s configuration.
- The demo is rate limited per browser. If you hit the limit, grab a free API key and the limit goes away.
- Always verify the aggregator address against data.chain.link before relying on a feed in production code.
Related
- Multicall3 batching for EVM contract reads — why one expression can replace dozens of
eth_callround trips - Read smart contracts in n8n — wire the same query into a no-code workflow
- evmquery for developers — the full integration story