> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# JSON-RPC Overview

> JSON-RPC methods, differences from Ethereum, rate limits, and error codes

Monad supports a [JSON-RPC](https://www.jsonrpc.org/specification) interface for interacting with the blockchain. Monad aims to match the RPC behavior of [Geth](https://geth.ethereum.org/docs/interacting-with-geth/rpc) as closely as possible, but due to fundamental architectural differences, some behaviors deviate from Ethereum.

{/*
This page contains low-level reference information. For higher-level documentation, visit these other pages.

<CardGroup cols={2}>
<Card title="Public RPC endpoints" href="/developer-essentials/network-information">
  Find public RPC URLs and block explorers
</Card>
 <Card title="Data & indexing guide" href="/build/applications/data-and-indexing">
  Solve data and indexing problems in your app
</Card>
</CardGroup>
*/}

## Supported methods

| Method                                                                                                       | Notes                                                                                      |
| ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
| [`eth_blockNumber`](/reference/json-rpc/api#eth_blocknumber)                                                 |                                                                                            |
| [`eth_call`](/reference/json-rpc/api#eth_call)                                                               | [Gas limits](#eth_call--eth_estimategas), [state availability limits](#state-availability) |
| [`eth_chainId`](/reference/json-rpc/api#eth_chainid)                                                         |                                                                                            |
| [`eth_createAccessList`](/reference/json-rpc/api#eth_createaccesslist)                                       |                                                                                            |
| [`eth_estimateGas`](/reference/json-rpc/api#eth_estimategas)                                                 | [Gas limits](#eth_call--eth_estimategas)                                                   |
| [`eth_feeHistory`](/reference/json-rpc/api#eth_feehistory)                                                   | [Difference from Ethereum](#fee-estimation)                                                |
| [`eth_fillTransaction`](/reference/json-rpc/api#eth_filltransaction)                                         |                                                                                            |
| [`eth_gasPrice`](/reference/json-rpc/api#eth_gasprice)                                                       |                                                                                            |
| [`eth_getBalance`](/reference/json-rpc/api#eth_getbalance)                                                   |                                                                                            |
| [`eth_getBlockByHash`](/reference/json-rpc/api#eth_getblockbyhash)                                           |                                                                                            |
| [`eth_getBlockByNumber`](/reference/json-rpc/api#eth_getblockbynumber)                                       |                                                                                            |
| [`eth_getBlockReceipts`](/reference/json-rpc/api#eth_getblockreceipts)                                       |                                                                                            |
| [`eth_getBlockTransactionCountByHash`](/reference/json-rpc/api#eth_getblocktransactioncountbyhash)           |                                                                                            |
| [`eth_getBlockTransactionCountByNumber`](/reference/json-rpc/api#eth_getblocktransactioncountbynumber)       |                                                                                            |
| [`eth_getCode`](/reference/json-rpc/api#eth_getcode)                                                         |                                                                                            |
| [`eth_getLogs`](/reference/json-rpc/api#eth_getlogs)                                                         | [Block range limits](#eth_getlogs)                                                         |
| [`eth_getStorageAt`](/reference/json-rpc/api#eth_getstorageat)                                               |                                                                                            |
| [`eth_getTransactionByBlockHashAndIndex`](/reference/json-rpc/api#eth_gettransactionbyblockhashandindex)     |                                                                                            |
| [`eth_getTransactionByBlockNumberAndIndex`](/reference/json-rpc/api#eth_gettransactionbyblocknumberandindex) |                                                                                            |
| [`eth_getTransactionByHash`](/reference/json-rpc/api#eth_gettransactionbyhash)                               | [Does not return pending txs](#transaction-lifecycle)                                      |
| [`eth_getTransactionCount`](/reference/json-rpc/api#eth_gettransactioncount)                                 |                                                                                            |
| [`eth_getTransactionReceipt`](/reference/json-rpc/api#eth_gettransactionreceipt)                             |                                                                                            |
| [`eth_maxPriorityFeePerGas`](/reference/json-rpc/api#eth_maxpriorityfeepergas)                               | [Returns hardcoded value](#fee-estimation)                                                 |
| [`eth_sendRawTransaction`](/reference/json-rpc/api#eth_sendrawtransaction)                                   | [Async validation behavior](#transaction-lifecycle)                                        |
| [`eth_sendRawTransactionSync`](/reference/json-rpc/api#eth_sendrawtransactionsync)                           | [Async validation behavior](#transaction-lifecycle)                                        |
| [`eth_syncing`](/reference/json-rpc/api#eth_syncing)                                                         |                                                                                            |
| `eth_subscribe`                                                                                              | WebSocket only, see [WebSocket subscriptions](#websocket-subscriptions)                    |
| [`debug_getRawBlock`](/reference/json-rpc/api#debug_getrawblock)                                             |                                                                                            |
| [`debug_getRawHeader`](/reference/json-rpc/api#debug_getrawheader)                                           |                                                                                            |
| [`debug_getRawReceipts`](/reference/json-rpc/api#debug_getrawreceipts)                                       |                                                                                            |
| [`debug_getRawTransaction`](/reference/json-rpc/api#debug_getrawtransaction)                                 |                                                                                            |
| [`debug_traceBlockByHash`](/reference/json-rpc/api#debug_traceblockbyhash)                                   | [Trace options required](#debug--trace)                                                    |
| [`debug_traceBlockByNumber`](/reference/json-rpc/api#debug_traceblockbynumber)                               | [Trace options required](#debug--trace)                                                    |
| [`debug_traceCall`](/reference/json-rpc/api#debug_tracecall)                                                 | [Trace options required](#debug--trace)                                                    |
| [`debug_traceTransaction`](/reference/json-rpc/api#debug_tracetransaction)                                   | [Trace options required](#debug--trace)                                                    |
| [`admin_ethCallStatistics`](/reference/json-rpc/api#admin_ethcallstatistics)                                 | Monad-specific                                                                             |
| [`net_version`](/reference/json-rpc/api#net_version)                                                         |                                                                                            |
| [`txpool_statusByAddress`](/reference/json-rpc/api#txpool_statusbyaddress)                                   | Monad-specific                                                                             |
| [`txpool_statusByHash`](/reference/json-rpc/api#txpool_statusbyhash)                                         | Monad-specific                                                                             |
| [`web3_clientVersion`](/reference/json-rpc/api#web3_clientversion)                                           |                                                                                            |

## Differences from Ethereum

Monad is Geth-compatible, but its architecture — including [asynchronous execution](/monad-arch/consensus/asynchronous-execution) and sub-second block times — introduces behavioral differences in several areas.

### Transaction lifecycle

**Deferred nonce/balance validation.** `eth_sendRawTransaction` may not immediately reject transactions with a nonce gap or insufficient gas balance. Because Monad's RPC server is designed for asynchronous execution, it may not have the latest account state at the time of submission. These transactions are initially accepted because they may become valid during block creation.

**No pending transaction queries.** `eth_getTransactionByHash` only returns transactions that have been included in a block. Querying a transaction that is still in the mempool returns `null`.

### State availability

`eth_call` invocations that reference old state (i.e. with an old block number) may fail, because full nodes do not provide access to arbitrary historic state. See [Historical Data](/developer-essentials/historical-data) for details on what state is available and how to access it.

### Fee estimation

**`eth_maxPriorityFeePerGas`** currently returns a hardcoded suggested fee of 2 gwei. This is temporary.

**`eth_feeHistory`** with `newest_block = latest`: by convention, this method returns the fee history for the requested range *plus* one extra projected fee for the next block. Monad does not have all the inputs required to compute the next block's base fee, so when the newest requested block is `latest`, the latest `baseFeePerGas` is returned twice.

### Debug / tracing

**Trace options parameter is required.** `debug_traceCall`, `debug_traceTransaction`, and related `debug_trace*` methods require the trace options object to be explicitly provided. Unlike standard EVM clients where this parameter is optional, Monad RPC returns error `-32602 Invalid params` if it is omitted. Always include the parameter, even if empty:

```json theme={null}
{
  "method": "debug_traceCall",
  "params": [
    {
      "to": "0x6b175474e89094c44da98b954eedeac495271d0f"
    },
    "latest",
    {}
  ]
}
```

**Default tracer is `callTracer`.** When an empty trace options object `{}` is provided, Monad defaults to the `callTracer` instead of the struct logs tracer typical in other EVM clients. Monad does not currently support opcode-level struct logs at the VM level.

### Unsupported features

| Feature                                 | Affected methods                                        | Details                           |
| --------------------------------------- | ------------------------------------------------------- | --------------------------------- |
| EIP-4844 (blob transactions)            | `eth_sendRawTransaction`, `eth_call`, `eth_estimateGas` | Blob transaction type is rejected |
| `"syncing"` subscription                | `eth_subscribe`                                         | Not supported                     |
| `"newPendingTransactions"` subscription | `eth_subscribe`                                         | Not supported                     |

## Block tags

Monad blocks progress through four [commitment states](/monad-arch/consensus/block-states): `Proposed`, `Voted`, `Finalized`, and `Verified`. The JSON-RPC API exposes these through standard Ethereum-compatible block tags.

| Block tag     | Monad state | Guidance                                                                                                                                                                                                                    |
| ------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"latest"`    | `Proposed`  | Lowest-latency view, but backed by [speculative execution](/monad-arch/consensus/asynchronous-execution#speculative-execution) — no consensus vote yet. Use for read-heavy UIs where freshness matters more than certainty. |
| `"safe"`      | `Voted`     | Backed by a supermajority vote. Reverts require extremely [unlikely conditions](/monad-arch/consensus/monad-bft#the-only-loophole).                                                                                         |
| `"finalized"` | `Finalized` | Irreversible without a hard fork. Use for value settlement: bridges, deposits, payment crediting.                                                                                                                           |

<Note>The `"pending"` tag is supported but behaves the same as `"latest"`. [Learn more](/monad-arch/consensus/local-mempool).</Note>

### Unfinalized data

Any RPC response that includes data from a non-finalized block can change on a subsequent identical request.

* **Methods with a block number/tag parameter** (`eth_call`, `eth_getBalance`, `eth_getLogs`, etc.) — can return non-finalized data when called with `"latest"` or a non-finalized block number.
* **Transaction-hash lookups** (`eth_getTransactionByHash`, `eth_getTransactionReceipt`) — can match a transaction in a non-finalized block. The returned `blockNumber`, log indices, or even the result itself (`null`) can change.
* **Implicit-latest methods** (`eth_gasPrice`, `eth_maxPriorityFeePerGas`) — always return non-finalized data using the `"latest"` tag.

<Tip>
  Treat data from non-finalized blocks as provisional. For transaction-hash lookups, compare the returned `blockNumber` against the `"finalized"` block height (tracked client-side) before acting on the result.
</Tip>

## Limits

### `eth_call` / `eth_estimateGas`

#### Gas limit per call

| Provider         | Public RPC                   | Gas limit |
| ---------------- | ---------------------------- | --------- |
| QuickNode        | `rpc.monad.xyz`              | 200M gas  |
| Alchemy          | `rpc1.monad.xyz`             | 200M gas  |
| Ankr             | `rpc3.monad.xyz`             | 1B gas    |
| Monad Foundation | `rpc-mainnet.monadinfra.com` | 200M gas  |

<Note>
  **Node operators**. Use `--eth-call-provider-gas-limit` (default 30M) and `--eth-estimate-gas-provider-gas-limit` (default 30M) to configure these limits.
</Note>

#### Gas limit resolution

When the caller specifies a gas **price** (`gasPrice` or `maxFeePerGas`), the effective gas limit is `min(gas limit allowance, provider gas limit)`, where the gas limit allowance is the maximum gas given the caller's balance and specified price. When no gas price is specified, the provider gas limit applies directly. This is consistent with Geth's behavior.

#### Dual-pool execution model

`eth_call` and `eth_estimateGas` requests are routed to one of two execution pools based on the caller-specified gas limit:

| Pool     | Gas limit   | Purpose                                |
| -------- | ----------- | -------------------------------------- |
| Low-gas  | ≤ 8,100,000 | Most calls; higher throughput          |
| High-gas | > 8,100,000 | Large simulations; limited concurrency |

When the caller does not specify a gas limit, the request is first attempted in the low-gas pool. If it runs out of gas, it is automatically retried in the high-gas pool.

<Note>
  **Node operators**. Use `--eth-call-max-concurrent-requests` (default 1000) and `--eth-call-high-max-concurrent-requests` (default 20) to configure pool concurrency.
</Note>

### `eth_getLogs`

#### Block range limit per call

| Provider         | Public RPC                   | Block range limit                                             |
| ---------------- | ---------------------------- | ------------------------------------------------------------- |
| QuickNode        | `rpc.monad.xyz`              | 100 blocks                                                    |
| Alchemy          | `rpc1.monad.xyz`             | 1,000 blocks and 10,000 logs (whichever is more constraining) |
| Ankr             | `rpc3.monad.xyz`             | 1,000 blocks                                                  |
| Monad Foundation | `rpc-mainnet.monadinfra.com` | 100 blocks                                                    |

<Note>
  **Node operators**. Use `--eth-get-logs-max-block-range` to configure the block range limit.
</Note>

#### Why are block range limits low?

Monad produces a block every 400ms and can accommodate up to 5,000 transactions per block with computation up to 200M gas. Blocks are both extremely frequent and significantly larger than Ethereum blocks, which is the main motivation for keeping per-call block range limits low.

{/*
#### Recommended query strategy

Based on recent internal testing, when indexing the chain we recommend adjusting your pipeline to
use a 100-block range with high concurrency (for example, 100 workers). This configuration should
give you extremely fast results.

Further improvements to `eth_getLogs` are being explored for the near future.
*/}

## Errors

Monad's JSON-RPC error codes aim to be equivalent to Ethereum's, but some codes deviate due to lack of standardization across Ethereum clients.

### Request-level errors (-32601)

| Message              | Explanation                                                     | Common cause                    |
| -------------------- | --------------------------------------------------------------- | ------------------------------- |
| Parse error          | Unable to parse the JSON-RPC request                            | Malformed JSON                  |
| Invalid request      | The request is structurally invalid                             | Request exceeds size limit      |
| Method not found     | The method is not part of the JSON-RPC spec                     | Typo in method name             |
| Method not supported | The method exists in the spec but is not yet supported by Monad | Calling an unimplemented method |

### Parameter errors (-32602)

| Message             | Explanation                                                        | Common cause                                                |
| ------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------- |
| Invalid block range | The requested `eth_getLogs` block range exceeds the provider limit | See [block range limits](#block-range-limit-per-call)       |
| Invalid params      | Incorrect parameters for the method                                | Wrong types, missing required fields, omitted trace options |

### Execution errors (-32603)

| Message                    | Explanation                              | Common cause                            |
| -------------------------- | ---------------------------------------- | --------------------------------------- |
| Internal error             | The request could not be fulfilled       | Server-side failure                     |
| Execution reverted         | The simulated transaction reverted       | Failed `eth_call` or `eth_estimateGas`  |
| Transaction decoding error | The raw transaction could not be decoded | Invalid RLP in `eth_sendRawTransaction` |

## WebSocket subscriptions

Monad's RPC server supports JSON-RPC over WebSocket connections, enabling persistent connections and real-time data via `eth_subscribe`. See the [Geth documentation](https://geth.ethereum.org/docs/interacting-with-geth/rpc/pubsub) for general `eth_subscribe` behavior.

Monad extends the standard subscription types with two speculative variants (`monadNewHeads` and `monadLogs`) that publish data sooner — approximately one second earlier on average — on a speculative basis. See [Speculative Real-Time Data](/monad-arch/realtime-data/spec-realtime) for background on speculative execution and [Block States](/monad-arch/consensus/block-states) for the full block lifecycle.

### Subscription types

| Type            | Fires when                                                                                                                      |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `newHeads`      | A new header is appended, once the block is `Voted`                                                                             |
| `logs`          | Matching logs appear in a new block, once the block is `Voted`                                                                  |
| `monadNewHeads` | A new header is available, once the block is `Proposed` and [speculatively executed](/monad-arch/realtime-data/spec-realtime)   |
| `monadLogs`     | Matching logs are available, once the block is `Proposed` and [speculatively executed](/monad-arch/realtime-data/spec-realtime) |

The subscription types `syncing` and `newPendingTransactions` are not supported.

### Speculative subscription behavior

`monadNewHeads` and `monadLogs` updates include two additional fields not present in the standard variants:

* **`blockId`** — a unique identifier for this specific block proposal (distinct from block number, since multiple proposals can exist for the same height).
* **`commitState`** — the block's current [commit state](/monad-arch/consensus/block-states): `Proposed`, `Voted`, `Finalized`, or `Verified`.

The same block will typically produce multiple updates as its `commitState` advances through the lifecycle. A block may skip `Voted` and go directly from `Proposed` to `Finalized` when consensus is ahead of execution. When a block fails to finalize, it is abandoned implicitly — the finalization of a different block at the same height supersedes it, but no explicit abandonment event is published.

{/*
### Code examples

You can access real-time data feeds via the [public RPC endpoints](/developer-essentials/network-information#public-rpc-endpoints). Below are examples using web3.py (Python) and ethers.js (JavaScript).

<CodeGroup>

```python web3.py
import asyncio

from web3 import AsyncWeb3
from web3.providers.persistent import WebSocketProvider

ws_url = 'wss://testnet-rpc.monad.xyz'

async def print_latest():
async with AsyncWeb3(WebSocketProvider(ws_url)) as w3:
  subscription_id = await w3.eth.subscribe('newHeads', {})
  async for payload in w3.socket.process_subscriptions():
    print(f"New block received: {payload['result']['number']}")

if __name__ == "__main__":
asyncio.run(print_latest())
```

```javascript ethers.js
import { WebSocketProvider } from "ethers/providers";

const wsUrl = "wss://testnet-rpc.monad.xyz"

const provider = new WebSocketProvider(wsUrl);

provider.on("block", (blockNumber) => {
console.log("New block received:", blockNumber);
});
```

</CodeGroup>

Note that the Python example explicitly uses the subscription name `'newHeads'` — this low-level style is also what you need if you want to use the Monad-specific `monadNewHeads` and `monadLogs` feeds, since those extensions work without any library changes.
*/}

{/*
### Checking connectivity

WebSocket support is an extra feature which may not be enabled on an RPC server. A quick way to check if WebSocket connectivity is working is to use [`websocat`](https://github.com/vi/websocat), a command-line WebSocket client. If it is not available through your system's package manager, install it with `cargo install websocat`.

```shell
> websocat -v wss://testnet-rpc.monad.xyz
[INFO  websocat::lints] Auto-inserting the line mode
[INFO  websocat::stdio_threaded_peer] get_stdio_peer (threaded)
[INFO  websocat::ws_client_peer] get_ws_client_peer
[INFO  websocat::net_peer] Connected to TCP 208.115.212.142:8081
[INFO  websocat::ws_client_peer] Connected to ws
```

To subscribe, type the subscription JSON-RPC call into stdin and press enter:

```json
{ "id": 1, "jsonrpc": "2.0", "method": "eth_subscribe", "params": ["newHeads"] }
```

Every half-second or so, you should see updates about new blocks.
*/}
