Summary
The Arbitrum RPC API is a JSON-RPC interface that lets your application read Arbitrum One state and submit transactions. You connect over HTTP or WebSocket to a node that is synced to the Arbitrum rollup, then call standard Ethereum methods such as eth_call, eth_getLogs, and eth_sendRawTransaction. This article covers the chain settings you need, the methods that behave differently on Arbitrum, and the failure modes that catch teams during integration.
If you are choosing where to send those requests, OnFinality provides Arbitrum RPC API access and dedicated node infrastructure so you can move from a public endpoint to a managed or private node as your workload grows. Use this page to configure your client correctly first, then decide whether a shared endpoint or a dedicated node fits your traffic pattern.
Arbitrum One is an optimistic rollup that settles to Ethereum, but it exposes an Ethereum-compatible JSON-RPC surface. That compatibility is convenient and also a trap: most Ethereum tooling works, yet a handful of methods, gas rules, and timing assumptions behave differently. This page gives you the settings to connect, the methods worth checking before you ship, and the failure modes that show up in production.
Chain settings at a glance
Start by confirming the values your client, wallet, or framework needs. Arbitrum One is the mainnet rollup; Arbitrum Sepolia is the testnet you use for staging.
| Setting | Arbitrum One (mainnet) | Arbitrum Sepolia (testnet) |
|---|---|---|
| Chain ID | 42161 | 421614 |
| Native currency | ETH (18 decimals) | ETH (18 decimals) |
| Block explorer | https://arbiscan.io | https://sepolia.arbiscan.io |
| HTTP endpoint | https://arbitrum.api.onfinality.io/public | https://arbitrum-sepolia.api.onfinality.io/public |
| WebSocket | Supported on Arbitrum One | Check availability on the testnet endpoint |
| Rollup type | Optimistic rollup | Optimistic rollup |
A wallet network config for Arbitrum One looks like this:
{
"chainId": "0x66eee",
"chainName": "Arbitrum One",
"nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 },
"rpcUrls": ["https://arbitrum.api.onfinality.io/public"],
"blockExplorerUrls": ["https://arbiscan.io"]
}
Note that 0x66eee is the hex form of 42161. Wallets reject a mismatch between the decimal chain ID you quote in docs and the hex value you send in wallet_addEthereumChain.
Decide how you will connect before you write code
The connection decision usually comes down to three questions: does your app need push updates, does it need historical state, and how bursty is your traffic?
- Read-only dashboards and wallets can usually run on a shared HTTP endpoint. Requests are short, stateless, and cacheable.
- Apps that react to new blocks or pending activity benefit from a WebSocket subscription so you are not polling
eth_getBlockByNumberin a loop. - Indexers, analytics, and backfills need archive access and often heavier
eth_getLogsqueries, which is where shared public endpoints start to strain. - High-volume or latency-sensitive workloads are better served by a dedicated node where your traffic is not sharing capacity with other tenants.
If you are unsure which category you fall into, the RPC provider selection guide walks through the evaluation criteria. For Arbitrum specifically, you can compare shared and dedicated options on the Arbitrum network page.
Calling the Arbitrum RPC API
A basic read request is identical to Ethereum. This curl call fetches the latest block number:
curl -s https://arbitrum.api.onfinality.io/public \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
In JavaScript with viem, the same call is a one-liner once the chain is configured:
import { createPublicClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
const client = createPublicClient({
chain: arbitrum,
transport: http('https://arbitrum.api.onfinality.io/public'),
});
const blockNumber = await client.getBlockNumber();
console.log(blockNumber);
For a WebSocket subscription to new block headers:
import WebSocket from 'ws';
const ws = new WebSocket('wss://arbitrum.api.onfinality.io/public/ws');
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'eth_subscribe',
params: ['newHeads'],
}));
});
ws.on('message', (data) => console.log(data.toString()));
Confirm the exact WebSocket path against the Arbitrum network page before hardcoding it, since transport support can differ between mainnet and testnet.
Methods that behave differently on Arbitrum
Because Arbitrum is a rollup, some methods return values that do not match an Ethereum L1 mental model.
| Method | What changes on Arbitrum | What to watch |
|---|---|---|
eth_gasPrice | Reflects L2 gas pricing plus an L1 data component | Do not hardcode a gas price; estimate per transaction |
eth_estimateGas | Accounts for L1 calldata cost | Estimates can be higher than a naive L2-only calculation |
eth_getLogs | Large block ranges are expensive | Paginate and constrain fromBlock/toBlock |
eth_getBlockByNumber | Block times are fast | Polling loops waste quota; prefer subscriptions |
eth_call | Works normally for view functions | State can change between call and transaction |
eth_sendRawTransaction | Standard signed transaction | Watch for nonce and gas errors, not format errors |
The gas difference is the one that surprises teams most. A transaction on Arbitrum pays L2 execution gas and a separate L1 data-availability cost, so a gas price that looks fine on Ethereum may underprice an Arbitrum transaction. Always estimate rather than assume.
Failure modes and how to debug them
Most Arbitrum RPC API problems fall into a small set of categories. Match the symptom to the likely cause before you change providers.
| Symptom | Likely cause | First check |
|---|---|---|
nonce too low | A previous transaction is already mined | Query eth_getTransactionCount with pending |
replacement transaction underpriced | Resubmitting with the same nonce and low gas | Raise the gas price for the replacement |
eth_getLogs times out | Block range too wide | Split the range into smaller windows |
| Requests intermittently fail | Shared endpoint under burst load | Add retries with backoff, or move to a dedicated node |
| WebSocket disconnects | Idle timeout or network drop | Implement reconnect and resubscribe logic |
execution reverted with no reason | Contract reverted without a message | Replay the call with eth_call at the failing block |
A practical debugging sequence: reproduce the failing call with curl so you remove your framework from the equation, confirm the block number you are querying against, then check whether the same call succeeds on a second endpoint. If it only fails on one endpoint, you have an infrastructure problem. If it fails everywhere, the issue is in the request itself.
Production readiness checklist
Before you point real traffic at an Arbitrum endpoint, confirm each of these:
- Failover: your client can switch to a second endpoint without a redeploy.
- Retries: transient 5xx and timeout responses are retried with exponential backoff, not immediately.
- Timeouts: request timeouts are set so a slow call does not block your whole request path.
- Log queries:
eth_getLogsranges are bounded and paginated. - Subscriptions: WebSocket clients reconnect and resubscribe automatically.
- Observability: you track error rate and latency per method, not just overall uptime.
- Capacity: you know your peak requests per second and whether a shared endpoint can absorb it.
If your peak load is steady and high, or you need archive and trace access, a dedicated node removes the noisy-neighbour variable. If your load is modest and bursty, a managed shared endpoint is usually the simpler choice. Pricing for both models is on the RPC pricing page.
Testnet workflow
Use Arbitrum Sepolia for staging so you do not burn mainnet ETH on integration tests. The chain ID is 421614 and the explorer is https://sepolia.arbiscan.io. Faucets for Arbitrum Sepolia are operated by ecosystem providers; fund a throwaway key and keep it out of production config. Because testnet state is not permanent, do not build assertions that depend on specific historical blocks persisting forever.
Monitoring signals worth tracking
Once you are live, the useful signals are method-level. Track the error rate for eth_sendRawTransaction separately from read methods, because write failures usually indicate nonce or gas problems rather than infrastructure problems. Track eth_getLogs latency separately, because it is the method most sensitive to query shape. And track WebSocket reconnect frequency, because a rising reconnect count is an early warning that your subscription handling needs attention.
Key Takeaways
- Arbitrum One uses chain ID 42161 and Arbitrum Sepolia uses 421614; both use ETH as the native currency.
- The JSON-RPC surface is Ethereum-compatible, but gas estimation and log queries behave differently because Arbitrum is a rollup.
- Always estimate gas rather than hardcoding it, and always bound
eth_getLogsblock ranges. - Match the connection type to the workload: HTTP for stateless reads, WebSocket for push updates, dedicated nodes for sustained or archive-heavy traffic.
- Build failover, retries, and reconnect logic before you scale traffic, not after an incident.
Frequently Asked Questions
Is the Arbitrum RPC API the same as Ethereum's? It is close. The method names and request format are the same, but gas pricing, log query cost, and block timing differ because Arbitrum is an optimistic rollup.
What chain ID does Arbitrum use? Arbitrum One uses 42161 and Arbitrum Sepolia uses 421614. In wallet configs, send the hex form.
Do I need a WebSocket endpoint? Only if your app needs push updates such as new block headers or event subscriptions. Read-only apps can use HTTP alone.
Why does my eth_getLogs call time out?
The block range is usually too wide. Split it into smaller windows and paginate.
When should I move from a shared endpoint to a dedicated node? When your sustained request volume, archive needs, or latency requirements exceed what a shared endpoint comfortably serves. Compare options on the Arbitrum network page and review RPC pricing for both models.
Where can I see which networks OnFinality supports? The full list is on the supported RPC networks page.