Logo
New RPC users get 35% off their first monthView the offer
OnFinality Learn
RPC Troubleshooting14 min read

Base RPC MetaMask Setup: Chain ID, RPC URL, and Connection Fixes

A technical walkthrough for adding Base to MetaMask correctly and diagnosing the five connection errors that follow.

TL;DR

Adding Base to MetaMask requires a NetworkName, an RPC URL, a Chain ID, a currency symbol, and a block explorer. MetaMask validates the RPC URL by calling eth_chainId and usually net_version, and it refuses to save the network if the call fails or the returned chain ID does not match the value you entered. The correct Base mainnet parameters are chain ID 8453 (0x2105) with native currency ETH; Base Sepolia uses 84532 (0x14a34). Most connection failures fall into five classes: unreachable or gated RPC URLs, chain-ID mismatches, CORS/referrer blocks, HTTP 429 rate limiting, and HTML error pages returned instead of JSON. This article shows how to test an endpoint independently with curl and Node.js, how to fill a reproducible results table, and why a public endpoint that works for a dapp can still fail under wallet polling.

What MetaMask Does When You Add a Custom Network

When you add a custom network in MetaMask, the wallet stores five fields: NetworkName, RPC URL, Chain ID, Currency Symbol, and Block Explorer URL. These are not just labels. The RPC URL is the HTTP endpoint MetaMask will use for every JSON-RPC request, and the Chain ID is the value MetaMask expects that endpoint to report. According to the MetaMask support documentation, the wallet validates the connection before saving the network.

The validation step is a JSON-RPC call. MetaMask sends eth_chainId to the RPC URL and compares the returned hexadecimal chain ID against the decimal value you entered. It usually also calls net_version as a secondary check. If either call fails, times out, or returns a mismatched chain ID, MetaMask aborts the save and shows an error. The Ethereum JSON-RPC specification defines eth_chainId as the method that returns the chain ID of the current network, which is why wallets rely on it for network detection.

This means the RPC URL must be reachable from the browser context, must speak JSON-RPC 2.0, and must return the chain ID you typed. A URL that works in a terminal but blocks browser origins will still fail in MetaMask. A URL that returns a valid chain ID for a different network will also fail. The wallet is not testing whether the endpoint is fast or reliable; it is testing whether the endpoint is the network you claim it is.

  • NetworkName: a label stored locally, not sent to the RPC endpoint.
  • RPC URL: the HTTP endpoint for all JSON-RPC calls.
  • Chain ID: the decimal value MetaMask expects eth_chainId to return as hex.
  • Currency Symbol: display only; it does not affect RPC calls.
  • Block Explorer URL: used for linking transactions, not for validation.

Correct Base Network Parameters for Mainnet and Sepolia

Base mainnet uses chain ID 8453, which is 0x2105 in hexadecimal. The native currency is ETH. Base Sepolia, the testnet, uses chain ID 84532, which is 0x14a34. These values are documented in the Base documentation. The chain ID must match exactly because MetaMask compares the decimal value you enter against the hex value returned by eth_chainId.

For the RPC URL, you can use a public endpoint or a provider endpoint. Public endpoints are convenient for light interactive use but are shared and often rate-limited. Provider endpoints, such as those described in the Base RPC endpoint (RPC Assistant) page, are designed for higher request volumes and may include WebSocket support. If you need WebSocket transport, see the Base RPC WebSocket connections guide.

The block explorer URL is optional but useful. For Base mainnet, the explorer is typically https://basescan.org. For Base Sepolia, it is https://sepolia.basescan.org. These do not affect RPC validation, but they make transaction links work correctly.

  • Base mainnet: Chain ID 8453 (0x2105), Currency ETH, RPC URL from a provider or public endpoint.
  • Base Sepolia: Chain ID 84532 (0x14a34), Currency ETH, RPC URL from a provider or public endpoint.
  • Block explorer mainnet: https://basescan.org
  • Block explorer Sepolia: https://sepolia.basescan.org

The Five Connection Errors and Their Root Causes

Most Base-to-MetaMask connection failures fall into five classes. The first is 'Could not fetch chain ID'. This happens when the RPC URL is wrong, dead, or gated. The endpoint may be offline, may require an API key, or may reject the request before it reaches the JSON-RPC layer. MetaMask cannot proceed because it cannot confirm the chain.

The second is a chain-ID mismatch. The wallet shows one chain, but the endpoint returns another. This occurs when you paste an RPC URL for a different network, such as Ethereum mainnet or a testnet, while entering Base's chain ID. MetaMask compares the returned hex chain ID against your decimal entry and refuses to save if they differ.

The third is a CORS or referrer block. Browser-based wallets call the RPC URL from a web origin. If the endpoint does not include the appropriate Access-Control-Allow-Origin header, the browser blocks the response before MetaMask can read it. This often looks like a generic network error in the wallet, but the browser console shows a CORS failure.

The fourth is HTTP 429 rate limiting. Public endpoints enforce request quotas. MetaMask polls the RPC URL frequently, especially when the wallet is open and tracking pending transactions. A public endpoint that works for a dapp with occasional calls can still return 429 under wallet polling. The Base RPC rate limits and reliability article covers quota behavior in more detail.

The fifth is an HTML error page or proxy interstitial returned instead of JSON. This happens when a proxy, captive portal, or misconfigured gateway intercepts the request and returns HTML. MetaMask expects a JSON-RPC 2.0 response and cannot parse HTML, so it reports a fetch failure. The fix is to verify the endpoint returns JSON with the correct Content-Type header.

  • Could not fetch chain ID: wrong, dead, or gated RPC URL.
  • Chain-ID mismatch: endpoint returns a different chain ID than entered.
  • CORS/referrer block: endpoint does not allow the browser origin.
  • HTTP 429: public endpoint rate-limited under wallet polling.
  • HTML instead of JSON: proxy or gateway interstitial breaks parsing.

Testing the Endpoint Independently with curl

Before changing anything in MetaMask, test the RPC URL outside the wallet. A single curl POST to the endpoint with eth_chainId tells you whether the endpoint is reachable and what chain ID it returns. For Base mainnet, the result should be 0x2105. If you get an HTTP error, an HTML body, or a different hex value, the problem is the endpoint, not MetaMask.

The JSON-RPC 2.0 specification requires a jsonrpc field set to "2.0", a method, params, and an id. The following curl command sends a minimal request. Replace the URL with your candidate Base endpoint. The -i flag includes response headers so you can inspect the Content-Type and any CORS headers.

  • Expected Base mainnet result: {"jsonrpc":"2.0","id":1,"result":"0x2105"}
  • Expected Base Sepolia result: {"jsonrpc":"2.0","id":1,"result":"0x14a34"}
  • Check the HTTP status: 200 is expected; 401, 403, or 429 indicate access or quota issues.
  • Check Content-Type: application/json; text/html indicates a proxy or error page.
curl -i -X POST https://mainnet.base.org \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'

Surfacing CORS Failures with a Browser Console Fetch

CORS failures are invisible in curl because curl does not enforce browser origin policies. To reproduce what MetaMask sees, open your browser console on any page and run a fetch against the candidate RPC URL. If the endpoint does not allow your origin, the browser will block the response and log a CORS error. This is the same failure MetaMask encounters when it calls the endpoint from the extension context.

The following snippet sends the same eth_chainId request from the browser. If it succeeds, you will see the JSON response. If it fails, the console will show a CORS or network error. This test distinguishes an endpoint that works server-side from one that works in a browser wallet.

  • If the console shows a CORS error, the endpoint does not allow your browser origin.
  • If the console shows a network error, the endpoint may be unreachable or blocked by an extension.
  • If the console shows a JSON parse error, the endpoint returned HTML or non-JSON content.
fetch('https://mainnet.base.org', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'eth_chainId',
    params: []
  })
})
  .then(res => res.json())
  .then(data => console.log('Chain ID:', data.result))
  .catch(err => console.error('Fetch failed:', err));

Runnable Node.js Probe for eth_chainId, net_version, and eth_blockNumber

A more thorough probe checks three methods: eth_chainId, net_version, and eth_blockNumber. This gives you the chain ID, the network ID, and the latest block number. The script below prints PASS or FAIL for each method, along with the HTTP status and the first bytes of the response body. It uses the built-in fetch API available in Node.js 18 and later.

Run this script with node probe.js https://your-base-endpoint. Replace the URL argument with your candidate endpoint. The script exits with a non-zero code if any check fails, which makes it usable in CI or a quick terminal check.

  • eth_chainId should return 0x2105 for Base mainnet.
  • net_version should return 8453 for Base mainnet.
  • eth_blockNumber should return a hex block number that increases over time.
  • Any FAIL indicates the endpoint is not suitable for MetaMask.
const url = process.argv[2];
if (!url) {
  console.error('Usage: node probe.js <RPC_URL>');
  process.exit(1);
}

const methods = ['eth_chainId', 'net_version', 'eth_blockNumber'];

async function probe(method) {
  const body = JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method,
    params: []
  });
  try {
    const res = await fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body
    });
    const text = await res.text();
    const firstBytes = text.slice(0, 80).replace(/\n/g, ' ');
    let parsed;
    try {
      parsed = JSON.parse(text);
    } catch (e) {
      console.log(`FAIL ${method} | HTTP ${res.status} | non-JSON body: ${firstBytes}`);
      return false;
    }
    if (parsed.error) {
      console.log(`FAIL ${method} | HTTP ${res.status} | error: ${JSON.stringify(parsed.error)}`);
      return false;
    }
    console.log(`PASS ${method} | HTTP ${res.status} | result: ${parsed.result}`);
    return true;
  } catch (err) {
    console.log(`FAIL ${method} | network error: ${err.message}`);
    return false;
  }
}

(async () => {
  let allPass = true;
  for (const method of methods) {
    const ok = await probe(method);
    if (!ok) allPass = false;
  }
  process.exit(allPass ? 0 : 1);
})();

Reproducible Results Table for Your Own Endpoint

Use the table below to record your own measurements. Fill one row per endpoint you test. The goal is to compare endpoints objectively and identify which error class applies. Do not rely on memory; record the HTTP status, the chain ID returned, whether CORS passed, and the fix you applied.

If you are testing multiple endpoints, run the Node.js probe and the browser fetch for each one. The table makes it clear which endpoint is suitable for MetaMask and which one requires a different approach, such as a provider endpoint or a WebSocket connection.

  • Endpoint: the full RPC URL you tested.
  • HTTP status: the status code returned by the probe.
  • eth_chainId: the hex value returned, or the error message.
  • CORS ok?: yes if the browser fetch succeeded, no if it failed.
  • Error class: one of the five classes described above.
  • Fix applied: the change you made, such as switching endpoints or removing and re-adding the network.

Why MetaMask Caches Broken Network Entries

MetaMask stores custom network configurations locally. If you add a network with a broken RPC URL, the wallet may keep that entry even after you correct the URL elsewhere. In some cases, the fix requires removing the network entirely and adding it again with the correct parameters. This is documented behavior in the MetaMask support documentation.

The caching behavior means that editing the RPC URL in place may not be enough. If you see persistent errors after changing the URL, remove the network from MetaMask's network list and re-add it. This forces the wallet to re-run the eth_chainId validation against the new endpoint.

This is also why a network that worked previously can suddenly fail. If the endpoint changed its CORS policy or started rate-limiting, MetaMask may still have the old configuration cached. Removing and re-adding the network is the cleanest way to reset the validation state.

  • MetaMask stores custom networks locally and may not refresh validation automatically.
  • If errors persist after editing the RPC URL, remove and re-add the network.
  • Re-adding forces a fresh eth_chainId call against the new endpoint.

Limitations of Client-Side Fixes and Public Endpoints

No client-side fix substitutes for a reliable endpoint. If you are using a public Base endpoint for anything beyond light interactive use, you will eventually hit rate limits or CORS restrictions. MetaMask polls the RPC URL frequently, and a public endpoint that works for a dapp with occasional calls can still return 429 under wallet polling. The Base RPC rate limits and reliability article explains the quota mechanics.

For production applications, use a provider endpoint with a documented service level. The RPC pricing page describes the available plans, and the API service page covers the broader API offering. If you need WebSocket transport for subscriptions, the Base RPC WebSocket connections guide covers that setup.

Another limitation is that MetaMask's validation only checks eth_chainId and net_version. It does not test eth_blockNumber or verify that the endpoint is synced. An endpoint can pass validation and still return stale block data. For applications that depend on finality, see the Base finality: safe and finalized blocks article.

  • Public endpoints are shared and rate-limited; they are not suitable for high-frequency polling.
  • MetaMask validation does not test block height or sync status.
  • Provider endpoints with documented SLAs are recommended for production use.
  • WebSocket transport requires a separate endpoint and configuration.

Troubleshooting Checklist for Persistent Connection Failures

If you have tested the endpoint with curl and the browser fetch, and MetaMask still fails, work through this checklist. Start by confirming the chain ID you entered matches the hex value returned by eth_chainId. For Base mainnet, the decimal value is 8453 and the hex value is 0x2105. For Base Sepolia, the decimal value is 84532 and the hex value is 0x14a34.

Next, check whether the endpoint requires an API key. Some provider endpoints return 401 or 403 without a key. If you are using a public endpoint, check whether it has a rate limit and whether you are hitting it. If the browser console shows a CORS error, the endpoint does not allow your origin; switch to a provider endpoint that supports browser origins.

If the endpoint returns HTML instead of JSON, you may be behind a proxy or captive portal. Try the endpoint from a different network or disable any proxy extensions. Finally, if nothing else works, remove the network from MetaMask and re-add it with the correct parameters. For a related walkthrough of chain ID fetch errors, see Base RPC timeouts and retry patterns.

  • Verify chain ID: 8453 (0x2105) for Base mainnet, 84532 (0x14a34) for Base Sepolia.
  • Check for API key requirements: 401 or 403 indicates a gated endpoint.
  • Check for rate limits: 429 indicates quota exhaustion.
  • Check CORS: browser console errors indicate origin restrictions.
  • Check for HTML responses: proxy or captive portal may be intercepting.
  • Remove and re-add the network if errors persist after fixing the endpoint.

Next Steps: Choosing a Reliable Base RPC Endpoint

Once you have confirmed the correct chain ID and tested your endpoint, the next step is to choose an endpoint that matches your usage. For light interactive use, a public endpoint may be sufficient. For anything that involves frequent polling, automated transactions, or production dapps, a provider endpoint is the better choice. The Base RPC endpoint (RPC Assistant) page helps you compare options.

If you are building on Base and need HTTP and WebSocket access, review the Base RPC WebSocket connections guide. For rate limit planning, see Base RPC rate limits and reliability. For finality considerations, see Base finality: safe and finalized blocks.

For a broader overview of RPC topics, visit the OnFinality Learn hub. If you are ready to move from a public endpoint to a managed service, the RPC pricing and API service pages describe the available options. The key takeaway is that MetaMask validation is a starting point, not a guarantee of reliability; choose an endpoint that matches your request volume and transport needs.

  • Use public endpoints for light interactive use only.
  • Use provider endpoints for production, automation, or high-frequency polling.
  • Consider WebSocket transport if you need subscriptions.
  • Review finality documentation if your application depends on block confirmation.

Never Worry about Infrastructure Again

OnFinality takes away the heavy lifting of DevOps so you can build smarter and faster.

Get Started