Execution trace of a transaction
Every call frame a transaction executed, in the order it ran: the caller and
target of each, the kind of call, the value and gas it moved, its own outcome,
and why it reverted where it did. A delegatecall names both the storage
context and the address whose code ran — which is what makes a proxy call
readable. create and create2 frames name the address they deployed. For the
EVM background, see the EVM on ethereum.org.
This method answers the whole tree in one response, up to 1 000 frames. For a larger tree, or when you need every frame's calldata and the event logs it emitted, page through call frames of a transaction.
GET https://tracefast.xyz/api/v1/chains/1/traces/{hash}
| Parameter | In | Type | Notes |
|---|---|---|---|
hash | path | string | 0x-prefixed, 64 hex characters, any case |
includeCalldata | query | boolean, optional | true adds each frame's calldata and output heads (first 260 bytes) with their full sizes. Default false. Only true and false are accepted |
limit | query | integer, optional | 1..1000, default 1000: at most this many frames, the first ones in the order they ran |
Access — an API key on the Investigation plan or higher (plans), or no key at all: pay per call with x402 at the same path on https://mpp.tracefast.xyz/api/v1, at the price its 402 states. As a tool for AI agents: get_transaction_trace on the MCP server. Stable — see stability.
chains/1 is a literal: the method serves Ethereum mainnet data. Other chain
ids answer 404 chain_not_supported. There are no other parameters — an
unknown one is refused rather than ignored.
What it covers, and what it does not
- At most
limitframes — 1 000 by default and at most.framesTruncatedsays when the tree is larger;framesis then its first frames in pre-order. A clipped tree never claims to be the whole one. Call frames, paged walks larger trees. - Each frame has its own outcome. A frame can revert while the transaction
succeeds, when a caller catches the revert.
statusis the frame's, not the transaction's. - A trace that is not available yet is refused, never answered empty.
Traces trail the chain by minutes to hours, sometimes longer. A transaction
in a block the traces have not reached answers
422 block_not_availablewithreason: coverage_gapand the last block traces are available for,maxAvailableBlock. That says nothing about the transaction's outcome — ask again later; the outcome itself is on one transaction. - Traces start at block 2 675 000. Older transactions are refused by name
(
422), not answered with an incomplete tree. - Calldata is opt-in and clipped.
inputHeadandoutputHeadare the first 260 bytes;inputSizeandoutputSizeare the full lengths.
Response
200 application/json, here with ?includeCalldata=true — a USDC transfer
through its proxy:
{
"data": {
"hash": "0xc41b41fb1c3eea59ea87b9e90edf476fb202e8daf02f19f469cdf497adbc76e0",
"blockNumber": 25920000,
"txIndex": 3,
"frameCount": 2,
"totalFrameCount": 2,
"framesTruncated": false,
"frames": [
{
"order": 0,
"depth": 1,
"callPath": "0000",
"callType": "call",
"from": "0x978e75381d64fb18af7112e42fa76a211a773456",
"to": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"valueWei": "0",
"gas": "78392",
"gasUsed": "40652",
"inputSelector": "0xa9059cbb",
"status": "success",
"revertDecodeStatus": "absent",
"codeAddress": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"inputHead": "0xa9059cbb000000000000000000000000f9dec5642e2b51ba67c695144d3360fab966f5a30000000000000000000000000000000000000000000000000000000029ba1944",
"inputSize": 68,
"outputHead": "0x0000000000000000000000000000000000000000000000000000000000000001",
"outputSize": 32
},
{
"order": 1,
"depth": 2,
"callPath": "00000000",
"parentPath": "0000",
"callType": "delegatecall",
"from": "0x978e75381d64fb18af7112e42fa76a211a773456",
"to": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"valueWei": "0",
"gas": "70036",
"gasUsed": "33363",
"inputSelector": "0xa9059cbb",
"status": "success",
"revertDecodeStatus": "absent",
"codeAddress": "0x43506849d7c04f9138d1a2050bbf3a0c054402dd",
"inputHead": "0xa9059cbb000000000000000000000000f9dec5642e2b51ba67c695144d3360fab966f5a30000000000000000000000000000000000000000000000000000000029ba1944",
"inputSize": 68,
"outputHead": "0x0000000000000000000000000000000000000000000000000000000000000001",
"outputSize": 32
}
]
},
"meta": {
"chain": "ethereum",
"timestamp": 1789063644200,
"cached": false,
"asOfBlock": 25920000,
"docs": "https://docs.tracefast.xyz/api/trace"
}
}Read the pair: frame 0 calls the USDC proxy; frame 1 is the proxy's
delegatecall. Its to stays the proxy — the storage that changes — while
codeAddress is the implementation whose code ran.
data
| Field | Meaning |
|---|---|
hash | the transaction, lowercase |
blockNumber, txIndex | its block and index within the block |
frameCount | frames in this response — the tree's size unless framesTruncated |
totalFrameCount | frames in the whole tree, whatever limit asked for — so a small limit still tells how large the trace is. Absent when the tree is larger than the 1 000-frame cap: its size is then not known here, only that it exceeds the cap |
framesTruncated | true when the tree holds more frames than this response |
frames[] | the frames in pre-order |
A frame — position and call
| Field | Meaning |
|---|---|
order | position in pre-order traversal; 0 is the transaction's own top-level call |
depth | depth in the tree; 1 is the top-level call |
callPath | the frame's address in the tree: four hex characters per level, root 0000 |
parentPath | the parent's callPath. Absent on the root |
callType | call, callcode, delegatecall, staticcall, create, create2, selfdestruct, eoa_transfer |
from | the frame's caller |
to | the frame's target — on a delegatecall, the storage context. Absent on a contract creation |
codeAddress | the address whose code runs in this frame. On a delegatecall this is the implementation. Absent where there is no callee code (create, create2, selfdestruct) |
valueWei | value the frame moved, wei |
gas, gasUsed | gas offered to the frame and gas it consumed, decimal strings |
inputSelector | the called function's four-byte selector |
createdAddress | the address a create or create2 frame deployed |
salt, initCodeHash | the create2 salt, and the keccak-256 of the init code on a creating frame |
selfdestructBeneficiary | who received the balance of a selfdestruct frame |
A frame — outcome
| Field | Meaning |
|---|---|
status | success, reverted or halted — the frame's own outcome |
errorKind | how it failed: Revert, Panic, CustomError, OutOfGas, … |
errorSelector | the custom error's four-byte selector — the error selector, not inputSelector |
revertReason | the decoded revert reason, or the custom error's name when its selector is known |
revertDecodeStatus | why revertReason is what it is: decoded, undecodable (a payload but no name found) or absent (no payload) |
revertData, revertDataSize | the raw ABI revert payload, lowercase hex, and its full length in bytes |
revertDataTruncated | true when the payload was cut. A cut payload decodes into a plausible but wrong argument list |
A frame — with includeCalldata=true
| Field | Meaning |
|---|---|
inputHead, outputHead | the first 260 bytes of the frame's calldata and output, lowercase 0x-hex |
inputSize, outputSize | their full lengths, bytes. Compare against 260, not against the hex string's length — the units differ |
Errors
| Status | code | When | details |
|---|---|---|---|
| 400 | bad_request | the hash is not 0x plus 64 hex characters | reason: tx_hash_invalid |
| 400 | bad_request | includeCalldata is neither true nor false | reason: include_calldata_invalid, includeCalldata |
| 400 | bad_request | limit outside 1..1000 | reason: limit_out_of_range, limit, maxLimit |
| 404 | not_found | no transaction with this hash is known | — |
| 422 | block_not_available | the transaction is below the height traces are served from | reason: block_not_available, minAvailableBlock |
| 422 | block_not_available | the traces have not reached the transaction's block yet; ask again later | reason: coverage_gap, maxAvailableBlock, coverageGapFromBlock — no coverageGapToBlock: the range is open-ended |
| 422 | block_not_available | the hash is unknown while recent blocks are in a coverage gap; ask again later | reason: coverage_gap, coverageGapFromBlock, coverageGapToBlock, maxAvailableBlock |
A transaction the traces have not reached yet:
{
"error": {
"code": "block_not_available",
"message": "the trace of block 25948674 is not available yet: it is available up to block 25925232. This says nothing about the transaction's outcome — retry later, or ask about a transaction at or below block 25925232.",
"details": {
"reason": "coverage_gap",
"maxAvailableBlock": 25925232,
"coverageGapFromBlock": 25925233
},
"requestId": "01a08c80-5ef3-76f1-acaf-fa7d749068cb"
}
}Malformed input, unknown parameters and the key check's 401/403/429 are the same for every method — see conventions and API keys.
Related pages
- Call frames of a transaction, paged — trees over 1 000 frames, calldata on every frame, the logs each frame emitted
- Why a transaction reverted — only the failed frames, with error names
- Storage writes of a transaction — what each frame wrote to contract storage
- One transaction — the transaction's own outcome
- Implementations of a proxy contract — the implementations behind a
delegatecall - Transactions: Trace — the same call tree in the app
Last updated 22 Oct 2026, 08:06 UTC · verified against TraceFast v1.0.261 · Markdown