trace_filter
https://api.triport.io/v1/polygonReturns all Polygon transaction traces (call frames) across a range of blocks that match an optional sender/recipient filter, with cursor-style pagination.
trace_filter scans a contiguous range of Polygon blocks and returns every
trace (internal call, create, or suicide frame) whose sender and/or
recipient match the supplied filter. Unlike trace_block —
which is keyed to a single block — or trace_transaction
— which is keyed to one transaction hash — trace_filter lets you sweep a window
of history and narrow it down by address. It is the right tool for building an
account's incoming/outgoing internal-transfer history, or for indexing all
activity that touched a particular contract.
This is the Parity-style tracer. Note that Polygon's Bor client can emit a
slightly different frame shape than vanilla Geth-Parity (for example call vs
delegatecall mapping), so an indexer should be tolerant of both. If you also
consume the Geth-style debug_traceBlockByNumber,
its output schema differs and your decoder must handle each shape separately.
Because a single block range can produce a very large number of traces, results
are paginated with the after (offset) and count (limit) fields and the
payload grows roughly linearly with the block range. Keep ranges modest and
page through large result sets rather than requesting a huge window in one call.
This method requires the Pro tier. Calls authenticated with a lower-tier key
are rejected with -32002 tier_insufficient.
Parameters
A single positional parameter: a filter object.
filterobjectrequiredfilter fieldsobjectfromBlockquantityoptional"0x2faf080"). Defaults to the latest block if omitted.toBlockquantityoptionalfromAddressarray of addressoptionaltoAddressarray of addressoptionalafterintegeroptional0.countintegeroptionalResponse
Response fields
result is an array of trace objects. Each object contains:
| Field | Type | Description |
|---|---|---|
action | object | Details of the call frame: from, to, value, gas, input, and callType (call / delegatecall / staticcall). For create traces, init and creationMethod appear instead; for suicide, address, refundAddress, and balance. |
result | object | Outcome of the frame: gasUsed and output (or address + code for a create). Absent when error is present. |
error | string | Present instead of result when the frame reverted (e.g. "Reverted", "out of gas"). |
blockHash | string | Hash of the block containing the trace. |
blockNumber | integer | Number of the block containing the trace. |
subtraces | integer | Number of child traces directly under this frame. |
traceAddress | array of integer | Path of the frame within the call tree (empty for a top-level call). |
transactionHash | string | Hash of the transaction that produced this trace. |
transactionPosition | integer | Index of that transaction within its block. |
type | string | Frame type: call, create, or suicide. |
Errors
| Code | Meaning | When it happens |
|---|---|---|
-32002 | tier_insufficient | Your API key's tier is below Pro; upgrade to call trace_filter. |
-32003 | rate_limited | You exceeded your tier's request rate (Pro 3 rps / Business 10 rps); retry after a short backoff. |
-32602 | invalid params | A block field used a tag ("latest" / "earliest" / "pending") instead of a numeric hex block, or the filter object was otherwise malformed. |
These follow the standard Triport JSON-RPC error envelope — see the shared errors reference for the full response shape, HTTP status mapping, and retry guidance.
Examples
JavaScript (fetch)
const res = await fetch("https://api.triport.io/v1/polygon", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRIPORT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "trace_filter",
params: [{
fromBlock: "0x2faf080",
toBlock: "0x2faf090",
toAddress: ["0x4f76e3b3cd2cf3a23e0c11a9f6f5f29c5e3f1f0a"],
after: 0,
count: 100,
}],
}),
});
const { result } = await res.json();
console.log(`${result.length} traces`);TypeScript SDK (@triport/sdk)
import { Triport } from "@triport/sdk";
const client = new Triport({ apiKey: process.env.TRIPORT_API_KEY! });
const traces = await client.polygon.traceFilter({
fromBlock: "0x2faf080",
toBlock: "0x2faf090",
toAddress: ["0x4f76e3b3cd2cf3a23e0c11a9f6f5f29c5e3f1f0a"],
after: 0,
count: 100,
});
for (const t of traces) {
console.log(t.transactionHash, t.action.value);
}Python (triport-sdk)
import os
from triport import Triport
client = Triport(api_key=os.environ["TRIPORT_API_KEY"])
traces = client.polygon.trace_filter({
"fromBlock": "0x2faf080",
"toBlock": "0x2faf090",
"toAddress": ["0x4f76e3b3cd2cf3a23e0c11a9f6f5f29c5e3f1f0a"],
"after": 0,
"count": 100,
})
for t in traces:
print(t["transactionHash"], t["action"]["value"])Notes
- Numeric blocks, not tags. This is the most common cause of a
-32602on Polygontrace_filter. Always resolve"latest"to a concrete block number (e.g. viaeth_blockNumber) and pass the hex value. - Chunk wide ranges. The response payload grows roughly linearly with the block range; a full-history filter in a single call can run to many megabytes. Iterate in fixed-size block windows (e.g. 100–1000 blocks) and paginate within each window rather than requesting one enormous range.
- Pagination. To page through a large result set, keep
countfixed and advanceafterbycounton each call (after: 0, thenafter: 100, …) until a page returns fewer thancounttraces. The result order is stable for a fixed block range. - Address filters are OR-within / AND-across. Multiple entries in
fromAddressmatch any of them; supplying bothfromAddressandtoAddressrequires a trace to satisfy both sides. - Related methods:
trace_blockfor a single block,trace_transactionfor one transaction,trace_callto trace a hypothetical call, andtrace_replayBlockTransactionsfor a full block replay with state diff. Alltrace_*methods require the Pro tier.