# Fetch logs

Source: https://docs.graphops.xyz/rpc/guides/fetch-logs

Build a transfer history, audit trail, or analytics table from contract events. This guide reads
the USDC `Transfer` logs emitted in Ethereum mainnet blocks `18000002` to `18000007`, then shows how
to keep larger log scans bounded and safe to resume.

## Prerequisites

* An API key that includes RPC.
* Ethereum mainnet endpoint access.
* An application path for storing or processing returned logs.

## Request

This request reads the USDC `Transfer` logs in blocks `18000002` to `18000007`, filtered by
contract and topic.

CLI · curl

Prerequisites

1. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

[Example project](/examples/rpc.guides.fetch-logs.sh-1.tar.gz)

```sh
# Block numbers are hex quantities: 0x112a882-0x112a887 is blocks 18,000,002-18,000,007.
# The topic is keccak256("Transfer(address,address,uint256)"), the Transfer event signature.
curl --fail-with-body --silent --show-error "https://rpc.graphops.xyz/v1/evm/1" \
  -H "Authorization: Bearer ${GRAPHOPS_API_KEY}" \
  -H "Content-Type: application/json" \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getLogs",
    "params": [
      {
        "fromBlock": "0x112a882",
        "toBlock": "0x112a887",
        "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "topics": [
          "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
        ]
      }
    ]
  }'

```

Output

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": [
    {
      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x000000000000000000000000e673bda19a529d9ff13aeddae0e08c0fda8b5488",
        "0x00000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640"
      ],
      "data": "0x00000000000000000000000000000000000000000000000000000000401332c0",
      "blockHash": "0x5b94c39ad7eecbf043f62a4a76c5abee87195207df98ae16eb3f289b2267f141",
      "blockNumber": "0x112a882",
      "blockTimestamp": "0x64ea26a7",
      "transactionHash": "0x29ec08dc5eed0e1cd411b29c52607661155087ffa107bae7f5e4a79f5306be1d",
      "transactionIndex": "0x2b",
      "logIndex": "0xac",
      "removed": false
    },
    {
      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x000000000000000000000000a40bb1c47f6dd27142a2bd7c93bfa98db9d1f5c5",
        "0x000000000000000000000000b4e16d0168e52d35cacd2c6185b44281ec28c9dc"
      ],
      "data": "0x0000000000000000000000000000000000000000000000000000000011348e5d",
      "blockHash": "0x5b94c39ad7eecbf043f62a4a76c5abee87195207df98ae16eb3f289b2267f141",
      "blockNumber": "0x112a882",
      "blockTimestamp": "0x64ea26a7",
      "transactionHash": "0xa8b07b56f7bb4ea52eecf5a125c75f143955a8e57e1ea17d2d8a48830e7d67db",
      "transactionIndex": "0x71",
      "logIndex": "0x13b",
      "removed": false
    },
    {
      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x000000000000000000000000180cd4303582d348a54fcb0436d5665f082a23d1",
        "0x000000000000000000000000a9d1e08c7793af67e9d92fe308d5697fb81d3e43"
      ],
      "data": "0x00000000000000000000000000000000000000000000000000000000aad0a340",
      "blockHash": "0x90c06a9fad66de217ce5862a92a2d45a8f42f9abf8ec17d5bfb85ffdc7836ca4",
      "blockNumber": "0x112a883",
      "blockTimestamp": "0x64ea26b3",
      "transactionHash": "0x05c9c59145387faa91370e56d717d42856bd20f8f19306814d5b7afbe837efe3",
      "transactionIndex": "0x66",
      "logIndex": "0xde",
      "removed": false
    },
    {
      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x0000000000000000000000001c727a55ea3c11b0ab7d3a361fe0f3c47ce6de5d",
        "0x000000000000000000000000c3dcc088aef4373e665b00fc8be45a4b6a4b24a6"
      ],
      "data": "0x000000000000000000000000000000000000000000000000000000000686bcda",
      "blockHash": "0x90c06a9fad66de217ce5862a92a2d45a8f42f9abf8ec17d5bfb85ffdc7836ca4",
      "blockNumber": "0x112a883",
      "blockTimestamp": "0x64ea26b3",
      "transactionHash": "0xeb8505dd3dc2964c1b43ed40371fb9c907b751ccb9294b99db032270889edc42",
      "transactionIndex": "0x72",
      "logIndex": "0xe6",
      "removed": false
    },
    {
      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x0000000000000000000000000000000000000000000000000000000000000000",
        "0x00000000000000000000000043954785980c50768373dc1dafd7ba3a2052036f"
      ],
      "data": "0x000000000000000000000000000000000000000000000000000000e8d433aa6e",
      "blockHash": "0x7f7889c3686d7f560dd690aeb2a10b49e3a76844543cf78cc0dfe4687e2985d2",
      "blockNumber": "0x112a884",
      "blockTimestamp": "0x64ea26bf",
      "transactionHash": "0xb2c1d8c8e7989adab51dafdc9be24fd05243342b8d08828c4325662de629c690",
      "transactionIndex": "0x48",
      "logIndex": "0xbf",
      "removed": false
    },
    {
      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x000000000000000000000000c880d8be4e94f644f1daa7d3558b50ff5a1c2db7",
        "0x000000000000000000000000ae2d4617c862309a3d75a0ffb358c7a5009c673f"
      ],
      "data": "0x0000000000000000000000000000000000000000000000000000002e90edd000",
      "blockHash": "0x127c6b9794874d7011770b3aa2a0a640e1db201c2d677d01b2b3b19e7ad427c7",
      "blockNumber": "0x112a885",
      "blockTimestamp": "0x64ea26cb",
      "transactionHash": "0x1691b8e89e13f483c549d9b61efbc54ecc54015b8186726911c8458f0993e13d",
      "transactionIndex": "0x1e",
      "logIndex": "0x40",
      "removed": false
    },
    {
      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x000000000000000000000000b86fc5e985facdcae6034beefc6cbdcd8bbd8cb4",
        "0x00000000000000000000000027f713adefc708469d826ab8f5b1e4672f1a070e"
      ],
      "data": "0x0000000000000000000000000000000000000000000000000000000059682f00",
      "blockHash": "0x127c6b9794874d7011770b3aa2a0a640e1db201c2d677d01b2b3b19e7ad427c7",
      "blockNumber": "0x112a885",
      "blockTimestamp": "0x64ea26cb",
      "transactionHash": "0x440106b494b7eb657d19e5f82a164ce4cc62e5252058fab5fb4ee6b92600543c",
      "transactionIndex": "0x6d",
      "logIndex": "0xcb",
      "removed": false
    },
    {
      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x000000000000000000000000b4eae88d1643e172518dde0ef213c20628798c65",
        "0x00000000000000000000000038c5a4f22e2e290ba9bbb9e3d9aaf8582f79f4d1"
      ],
      "data": "0x0000000000000000000000000000000000000000000000000000000006b78840",
      "blockHash": "0xdb63e26b655ad31d60b2173c02127180ed46b28506f785a2682e058ca61afdc1",
      "blockNumber": "0x112a887",
      "blockTimestamp": "0x64ea26e3",
      "transactionHash": "0x21d8e836f79606db39fcd51f7e563ea9c12cfb7a2bb3e36f23f4eb89b93045ea",
      "transactionIndex": "0x1f",
      "logIndex": "0x5e",
      "removed": false
    },
    {
      "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "topics": [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x000000000000000000000000579752cff8fee7af09446b2133ee2f9ff10c4fbf",
        "0x0000000000000000000000001715a3e4a142d8b698131108995174f37aeba10d"
      ],
      "data": "0x000000000000000000000000000000000000000000000000000000001d0221cd",
      "blockHash": "0xdb63e26b655ad31d60b2173c02127180ed46b28506f785a2682e058ca61afdc1",
      "blockNumber": "0x112a887",
      "blockTimestamp": "0x64ea26e3",
      "transactionHash": "0xd78a180e669534a650d842f13d032610e29bf4a7731fb90a6dff73d752ac049c",
      "transactionIndex": "0x57",
      "logIndex": "0xb3",
      "removed": false
    }
  ]
}
```

Every matching log in the requested block range

USDC contract

Transfer event signature

Transfer amount: 1,075,000,000 base units, 1,075 USDC

Block in decimal: 18,000,002

TypeScript · viem

Prerequisites

1. Install Node.js.

2. Install tsx and viem. `npm install tsx viem`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Node.js 24.22.1, tsx 4.23.15, viem 2.57.10.

[Example project](/examples/rpc.guides.fetch-logs.ts-2.tar.gz)

```typescript
import { createPublicClient, http, parseAbiItem } from "viem";
import { mainnet } from "viem/chains";

const client = createPublicClient({
  chain: mainnet,
  transport: http("https://rpc.graphops.xyz/v1/evm/1", {
    fetchOptions: {
      headers: {
        Authorization: `Bearer ${process.env.GRAPHOPS_API_KEY}`,
      },
    },
  }),
});

const logs = await client.getLogs({
  address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  event: parseAbiItem(
    "event Transfer(address indexed from, address indexed to, uint256 value)",
  ),
  fromBlock: 18_000_002n,
  toBlock: 18_000_007n,
});

console.log(logs.length);

```

Output

```json
9
```

Matching Transfer logs in the requested block: 9

Go · ethclient

Prerequisites

1. Install Go.

2. Install github.com/ethereum/go-ethereum. `go get github.com/ethereum/go-ethereum`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Go 1.26.0, github.com/ethereum/go-ethereum v1.17.7.

[Example project](/examples/rpc.guides.fetch-logs.go-5.tar.gz)

```go
package main

import (
	"context"
	"fmt"
	"log"
	"math/big"
	"os"

	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/ethereum/go-ethereum/rpc"
)

func main() {
	ctx := context.Background()
	rpcClient, err := rpc.DialOptions(ctx, "https://rpc.graphops.xyz/v1/evm/1",
		rpc.WithHeader("Authorization", "Bearer "+os.Getenv("GRAPHOPS_API_KEY")))
	if err != nil {
		log.Fatal(err)
	}
	client := ethclient.NewClient(rpcClient)
	defer client.Close()

	logs, err := client.FilterLogs(ctx, ethereum.FilterQuery{
		FromBlock: big.NewInt(18_000_002),
		ToBlock:   big.NewInt(18_000_007),
		Addresses: []common.Address{common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")},
		// keccak256("Transfer(address,address,uint256)"), the Transfer event topic.
		Topics: [][]common.Hash{{
			common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
		}},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(len(logs))
}

```

Output

```json
9
```

Matching Transfer logs in the requested block: 9

Rust · alloy

Prerequisites

1. Install Rust.

2. Install alloy, reqwest, and tokio. `cargo add alloy reqwest tokio -F alloy/provider-ws -F alloy/sol-types -F alloy/contract -F reqwest/json -F tokio/macros -F tokio/rt-multi-thread`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Rust 1.98.1, alloy 2.5.0, reqwest 0.13.5, tokio 1.48.0.

[Example project](/examples/rpc.guides.fetch-logs.rust-6.tar.gz)

```rust
use alloy::primitives::address;
use alloy::providers::{Provider, ProviderBuilder};
use alloy::rpc::client::RpcClient;
use alloy::rpc::types::Filter;
use alloy::transports::http::Http;
use reqwest::header::{HeaderMap, AUTHORIZATION};
use std::{env, error::Error};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let mut headers = HeaderMap::new();
    headers.insert(
        AUTHORIZATION,
        format!("Bearer {}", env::var("GRAPHOPS_API_KEY")?).parse()?,
    );
    let http = reqwest::Client::builder()
        .default_headers(headers)
        .build()?;
    let provider = ProviderBuilder::new().connect_client(RpcClient::new(
        Http::with_client(http, "https://rpc.graphops.xyz/v1/evm/1".parse()?),
        false,
    ));

    let filter = Filter::new()
        .address(address!("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"))
        .event("Transfer(address,address,uint256)")
        .from_block(18_000_002)
        .to_block(18_000_007);
    let logs = provider.get_logs(&filter).await?;

    println!("{}", logs.len());
    Ok(())
}

```

Output

```json
9
```

Matching Transfer logs in the requested block: 9

Python · web3.py

Prerequisites

1. Install Python.

2. Install web3. `python -m pip install web3`

3. Set GRAPHOPS\_API\_KEY to your GraphOps API key.

Tested with Python 3.12.12, web3 8.0.0.

[Example project](/examples/rpc.guides.fetch-logs.python-4.tar.gz)

```python
import os
from web3 import Web3

w3 = Web3(
    Web3.HTTPProvider(
        "https://rpc.graphops.xyz/v1/evm/1",
        request_kwargs={
            "headers": {
                "Authorization": f"Bearer {os.environ['GRAPHOPS_API_KEY']}",
            },
        },
    )
)

logs = w3.eth.get_logs(
    {
        "fromBlock": 18_000_002,
        "toBlock": 18_000_007,
        "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        # keccak256("Transfer(address,address,uint256)"), the Transfer event topic.
        "topics": [
            "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
        ],
    }
)

print(len(logs))

```

Output

```json
9
```

Matching Transfer logs in the requested block: 9

## Read the output

The range has nine USDC `Transfer` logs. The CLI tab prints them with their fields annotated; the
TypeScript, Go, Rust, and Python tabs print the count.

## Before production

* Always bound historical `eth_getLogs` requests by block range.
* Filter by contract address and topic when possible.
* Store the last completed block range for backfills.
* Deduplicate logs by `(blockHash, transactionHash, logIndex)`.
* If a range times out or hits a response-size limit, retry smaller ranges.

## Next steps

* [Backfill historical events](./backfill-historical-events): Scan a long block range in bounded, resumable chunks.
* [Supported methods](../methods#logs-and-filters): Check `eth_getLogs` parameters and transport support.
* [Archive reads](../concepts/archive-reads): Know which ranges need archive access on your network.