Summary
Base is an Ethereum L2 built on the OP Stack, so its RPC surface looks familiar to any Ethereum developer: JSON-RPC over HTTP, the same eth_* methods, and chain ID 8453 for mainnet. This article covers the Base node RPC endpoint settings you need, how to add Base to a wallet, how to send your first request, and how to debug the failures that show up most often in production. It also explains when a public endpoint is enough and when a dedicated Base node is the better fit.
Base is an Ethereum Layer 2 built on the OP Stack, which means its node RPC interface is deliberately familiar: standard JSON-RPC over HTTP, the same eth_* method names you already use on Ethereum, and a small set of OP-Stack-specific methods on top. If you are wiring up a wallet, a backend indexer, or a test suite, you mostly need the right chain settings, a working endpoint, and a clear debugging path when a request fails.
This page is a working reference for Base node RPC. It covers the settings you paste into a wallet, how to send a request with curl and with viem, what to check when a call fails, and how to decide between a public endpoint and a dedicated Base node.
Chain settings at a glance
Before you write any code, confirm the network parameters. Base mainnet and Base Sepolia are separate networks with different chain IDs, so a wallet or SDK pointed at the wrong one will look like it is working while returning the wrong data.
| Setting | Base mainnet | Base Sepolia |
|---|---|---|
| Chain ID | 8453 | 84532 |
| Native currency | ETH (18 decimals) | ETH (18 decimals) |
| Block explorer | https://basescan.org | https://sepolia.basescan.org |
| RPC transport | HTTP (JSON-RPC) | HTTP (JSON-RPC) |
| Typical use | Production apps, real value | Development, testing, faucets |
A quick sanity check: call eth_chainId and confirm it returns 0x2105 for mainnet (8453 in decimal) or 0x14a34 for Sepolia (84532). If the value does not match the network you intended, stop and fix the configuration before debugging anything else.
Adding Base to a wallet
Most wallets accept a custom network. The fields map directly to the table above:
- Network name: Base
- RPC URL: your Base endpoint
- Chain ID: 8453
- Currency symbol: ETH
- Block explorer: https://basescan.org
For Base Sepolia, use chain ID 84532 and the Sepolia explorer. If you are building a wallet connection flow, you can request the network programmatically instead of asking users to type it in:
await window.ethereum.request({
method: "wallet_addEthereumChain",
params: [{
chainId: "0x2105",
chainName: "Base",
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
rpcUrls: ["https://base.api.onfinality.io/public"],
blockExplorerUrls: ["https://basescan.org"]
}]
});
If you are using OnFinality for Base, the public endpoint is https://base.api.onfinality.io/public and the Base Sepolia equivalent is https://base-sepolia.api.onfinality.io/public. For production traffic, a dedicated Base node gives you a private endpoint you can rotate without touching user configuration. See the Base network page and Base Sepolia network page for current details.
Sending your first Base RPC request
The fastest way to confirm an endpoint works is a single curl call. This checks connectivity, chain ID, and the latest block in one shot:
curl -s https://base.api.onfinality.io/public \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'
curl -s https://base.api.onfinality.io/public \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
A healthy response returns a JSON object with a result field. If you get an error object instead, the error.code and error.message tell you whether the problem is the request, the endpoint, or the network.
In application code, the same call looks like this with viem:
import { createPublicClient, http } from "viem";
import { base } from "viem/chains";
const client = createPublicClient({
chain: base,
transport: http("https://base.api.onfinality.io/public")
});
const blockNumber = await client.getBlockNumber();
const chainId = await client.getChainId();
console.log({ chainId, blockNumber });
Because Base follows Ethereum conventions, most Ethereum tooling works without a Base-specific adapter. The main differences are chain ID, explorer URLs, and a handful of OP-Stack methods.
Which Base RPC methods matter in practice
You do not need every method. Most applications lean on a small set, and knowing which ones are heavier helps you plan capacity.
| Method | What it does | Notes for Base |
|---|---|---|
eth_chainId | Returns the chain ID | Use to verify you are on 8453 or 84532 |
eth_blockNumber | Latest block height | Cheap, good for health checks |
eth_getBalance | Account balance | Common in wallet flows |
eth_call | Read-only contract call | Core of most dapp reads |
eth_getLogs | Query event logs | Heaviest common method; scope by block range |
eth_getTransactionReceipt | Transaction status | Poll after sending a tx |
eth_estimateGas | Gas estimate | Run before sending |
eth_sendRawTransaction | Broadcast a signed tx | Returns a tx hash, not a receipt |
eth_getLogs deserves special attention. Wide block ranges and broad topic filters can return large payloads and are a frequent cause of timeouts. Narrow the range, filter by address, and paginate where possible.
Debug path for common Base RPC failures
When something breaks, the error message usually points at the layer. Work through this table before assuming the endpoint is down.
| Symptom | Likely cause | First check |
|---|---|---|
chainId mismatch | Wrong network configured | Call eth_chainId, compare to 8453/84532 |
method not found | Typo or unsupported method | Confirm method name and endpoint transport |
Timeout on eth_getLogs | Block range too wide | Reduce range, add address filter |
nonce too low | Stale nonce after a stuck tx | Re-read eth_getTransactionCount with pending |
insufficient funds | Gas or value exceeds balance | Check balance and gas estimate |
Empty result on a read | Contract not deployed on this network | Verify address on the correct explorer |
| Intermittent 429 | Shared endpoint rate limits | Move heavy reads to a dedicated node |
Two patterns cause most confusion. First, mixing mainnet and testnet data: a contract address that exists on Base mainnet will not exist on Base Sepolia, and vice versa. Second, treating eth_sendRawTransaction as final: it returns a hash immediately, but you must poll eth_getTransactionReceipt to know whether the transaction succeeded.
Public endpoint or dedicated Base node?
This is the decision most teams face once an app moves past prototyping. The right answer depends on your workload shape, not on a single benchmark.
| Workload | Public endpoint | Dedicated Base node |
|---|---|---|
| Prototypes and demos | Usually fine | Not needed yet |
| Low-volume reads | Usually fine | Optional |
Heavy eth_getLogs indexing | Risky under load | Recommended |
| High-frequency trading or bots | Shared limits apply | Recommended |
| Compliance or data isolation needs | Not suitable | Recommended |
| Predictable production traffic | Shared capacity | Recommended |
A useful rule: if your application's reliability depends on a specific request pattern that a shared endpoint cannot guarantee, isolate that pattern onto a dedicated node and leave everything else on the public endpoint. This keeps cost proportional to actual need. OnFinality offers both shared RPC API access and dedicated Base nodes; see RPC pricing for the current options and supported RPC networks for the full list.
WebSocket and subscription considerations
Base supports JSON-RPC over HTTP, which is what most applications use. If you need push-style updates, check whether your provider exposes WebSocket transport for Base before designing around subscriptions. HTTP polling of eth_blockNumber or eth_getTransactionReceipt is a reliable fallback and is easier to reason about under failure.
If you do use subscriptions, plan for reconnection logic. Long-lived connections drop, and a subscription that silently stops delivering events is worse than one that fails loudly. Treat the connection as something that will need to be re-established.
Operational checklist before launch
Before you point production traffic at any Base endpoint, confirm the following:
- Chain ID is verified at runtime, not just in config.
- The endpoint is reachable from your deployment environment, not only from your laptop.
- Heavy methods such as
eth_getLogsare scoped and paginated. - You have a fallback endpoint or a plan for one.
- Errors are logged with the JSON-RPC error code, not just a generic message.
- You know which network each contract address belongs to.
A simple monitoring probe keeps you ahead of problems:
async function probe(endpoint) {
const res = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] })
});
const json = await res.json();
return { ok: res.ok && !!json.result, block: json.result };
}
Run this on a schedule and alert on repeated failures. It is a small amount of code that catches a large class of incidents early.
Key Takeaways
- Base uses standard Ethereum JSON-RPC; chain ID 8453 for mainnet and 84532 for Sepolia.
- Verify
eth_chainIdat runtime to avoid silently querying the wrong network. eth_getLogsis the most common source of timeouts; scope block ranges and filters.eth_sendRawTransactionreturns a hash, not a receipt; poll for the receipt to confirm success.- Public endpoints suit prototypes and light reads; dedicated Base nodes suit heavy, predictable, or isolated workloads.
- OnFinality provides Base RPC API access and dedicated nodes; check RPC pricing and supported networks.
Frequently Asked Questions
What is the Base chain ID?
Base mainnet uses chain ID 8453. Base Sepolia uses 84532. Always confirm with eth_chainId at runtime.
What is the Base RPC endpoint? Any JSON-RPC endpoint that serves the Base network. OnFinality exposes a public Base endpoint and dedicated options; see the Base network page for current details.
Can I use Ethereum tooling with Base? Yes. Base follows Ethereum conventions, so most Ethereum libraries and wallets work once you set the correct chain ID and endpoint.
Why does my Base transaction show as pending?
eth_sendRawTransaction returns a hash before the transaction is included. Poll eth_getTransactionReceipt until it returns a receipt, and check gas settings if it stalls.
Do I need a dedicated Base node? Only if your workload needs private capacity, isolation, or predictable behavior under heavy reads. Prototypes and light apps usually do not.
How do I debug a Base RPC timeout?
Start with the method. eth_getLogs with a wide range is the usual culprit; narrow the range and add filters before investigating the endpoint itself.