eth_getLogs
https://api.triport.io/v1/polygonReturns the array of event logs on Polygon matching a filter — by block range, contract address, and indexed topics.
eth_getLogs returns all event logs emitted on Polygon that match a single
filter object. It is the primary event-indexing primitive: ERC-20
Transfers, DEX swaps, mints, bridge events — anything emitted with LOG0–LOG4
on Polygon mainnet (Bor consensus).
You select logs in one of two mutually exclusive ways:
- By block range — set
fromBlockandtoBlock(tags or hex block numbers). The range is inclusive on both ends. - By a single block — set
blockHashto pin the query to exactly one block.blockHashcannot be combined withfromBlock/toBlock.
Within that window you narrow further by address (one or many contracts) and
by topics (the indexed event signature and arguments). The result is a flat,
chronologically ordered array of log objects; an empty array means nothing
matched (this is not an error).
This is a read method available from the free tier. Polygon's block time is
~2.1 s, so a given wall-clock window covers roughly 6× more blocks than the same
window on Ethereum — keep ranges bounded. For high-frequency Polygon event
streams (e.g. Uniswap-style swaps can exceed 10,000 events/minute) prefer a
WebSocket subscription over polling eth_getLogs (see Notes).
Parameters
JSON-RPC params is a positional array with a single element: [filter].
filterobjectrequiredfromBlockstringoptional"0x3658060") or a tag: latest, earliest, pending, safe, finalized. Defaults to latest.toBlockstringoptionalfromBlock. Defaults to latest.addressstring | string[]optionaltopics(string | string[] | null)[]optionalblockHashstringoptionalfromBlock/toBlock.Topic AND/OR semanticsobjectResponse
Response fields
result is an array of log objects. Each object has:
| Field | Type | Description |
|---|---|---|
address | string | Contract that emitted the log. |
topics | string[] | Indexed topics; topics[0] is the event signature hash, the rest are indexed arguments. |
data | string | ABI-encoded non-indexed event arguments (0x-prefixed hex). 0x if there are none. |
blockNumber | string | Block number the log was included in (0x-prefixed hex). |
blockHash | string | Hash of the block containing the log. |
transactionHash | string | Hash of the transaction that produced the log. |
transactionIndex | string | Index of that transaction within the block (hex). |
logIndex | string | Index of this log within the block (hex). |
removed | boolean | true if the log was removed by a chain reorganization; false for a canonical log. |
Errors
Errors are returned in the standard JSON-RPC error envelope. See the shared errors reference for the full envelope shape and shared codes.
| Code | Meaning | When it happens |
|---|---|---|
-32001 | trial_expired | The API key's trial period has ended; upgrade to a paid tier to continue. |
-32002 | tier_insufficient | The key's tier is below what the method requires. eth_getLogs itself is free-tier, so this surfaces only when the key has no qualifying tier at all. |
-32003 | rate_limited | More than your tier's RPS for polygon_read_rpc (15 / 20 / 100 / 250). The error data carries limit_rps, retry_after_sec, and upgrade_url. |
-32004 | subscription_expired | The API key's subscription has lapsed. |
-32005 | unauthorized | Missing or invalid Authorization: Bearer key. |
-32601 | method_unknown | eth_getLogs was not recognized on the resolved Polygon route. |
A malformed filter — e.g. blockHash combined with fromBlock/toBlock, a
badly formatted address or topic, or a block range that exceeds the provider's
limit — is rejected with the standard -32602 invalid-params error.
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: "eth_getLogs",
params: [{
fromBlock: "0x3658060",
toBlock: "0x3658070",
address: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
topics: [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
],
}],
}),
});
const { result } = await res.json();
console.log(`Matched ${result.length} logs`);
for (const log of result) {
console.log(`${log.blockNumber} ${log.transactionHash} logIndex=${log.logIndex}`);
}TypeScript SDK (@triport/sdk)
import { Triport } from "@triport/sdk";
const client = new Triport({ apiKey: process.env.TRIPORT_API_KEY });
const TRANSFER =
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
const logs = await client.polygon.request("eth_getLogs", [{
fromBlock: "0x3658060",
toBlock: "0x3658070",
address: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
topics: [TRANSFER],
}]);
console.log(`Matched ${logs.length} logs`);Python (triport-sdk)
import os
from triport import Triport
client = Triport(api_key=os.environ["TRIPORT_API_KEY"])
TRANSFER = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
logs = client.polygon.request("eth_getLogs", [{
"fromBlock": "0x3658060",
"toBlock": "0x3658070",
"address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
"topics": [TRANSFER],
}])
print(f"Matched {len(logs)} logs")Notes
- Block range vs. block hash: supply either
fromBlock/toBlockorblockHash, never both.blockHashis the precise way to read all logs from one specific block regardless of reorgs. - Bound your ranges: a maximum block span per call applies, and very wide
windows (or unfiltered
address+topics) can return large result sets and are slow. For historic indexing, walk the chain in fixed-size windows (e.g. a couple of thousand blocks per call) and accumulate results. There is no daily quota — pacing is RPS-per-tier with burst. - Polygon block time: at ~2.1 s per block, ranges grow quickly in wall-clock terms — a one-hour window is roughly 1,700 blocks. Size windows by block count, not by time.
- High-frequency events: for real-time indexing of hot contracts (DEX swaps,
bridges) polling
eth_getLogswill lag and miss bursts. Use a WebSocketeth_subscribe/logssubscription instead and reserveeth_getLogsfor backfill and historic queries. - Reorgs: logs from recent, non-finalized blocks may later be reorged out;
such logs reappear in a subsequent query with
removed: true. Query against thefinalizedtag when you need stability — Bor finality lands a few epochs back. - Empty result: a filter that matches nothing returns
"result": [], which is a success, not an error. - Related methods: use
eth_getBlockReceiptsto pull every receipt (and its logs) for a block,eth_getTransactionReceiptfor the logs of a single transaction, andeth_blockNumberto discover the current head before paging.