Avalanche RPC: C-Chain, Subnets, and Endpoints
Most chains have one RPC endpoint and you're done. Avalanche has three chains with different APIs, endpoint URLs that look like /ext/bc/C/rpc, and a growing ecosystem of app-specific L1 subnets that each have their own RPC. So "what's the Avalanche RPC URL?" is a surprisingly loaded question, and the wrong answer means your wallet connects to the wrong chain or your eth_* calls bounce. Here's the map.
Avalanche is three chains, not one
The Avalanche Primary Network is made of three built-in blockchains, each with a different job:
| Chain | Name | Purpose | API |
|---|---|---|---|
| C-Chain | Contract Chain | EVM smart contracts, DeFi, NFTs, tokens | standard eth_* JSON-RPC |
| X-Chain | Exchange Chain | Creating/transferring assets (AVM) | AvalancheGo's own API (not eth_*) |
| P-Chain | Platform Chain | Staking, validators, subnet/L1 management | AvalancheGo's own API |
For 99% of developers, "Avalanche RPC" means the C-Chain. It's the EVM-compatible chain where Trader Joe, Aave, GMX, and everything else you'd recognize lives. It speaks the exact same JSON-RPC your Ethereum tooling already uses — eth_blockNumber, eth_call, eth_getLogs, the lot. If you're deploying a contract or reading on-chain state, the C-Chain is your endpoint and you can mostly ignore X and P.
The X-Chain and P-Chain matter for asset issuance and staking/validator operations respectively, but they use Avalanche's own API namespaces (avm.*, platform.*), not the Ethereum JSON-RPC. If you're a typical dApp dev, you'll rarely touch them directly.
Why the endpoint URL looks weird
An AvalancheGo node exposes each blockchain under a path: /ext/bc/<chain>/rpc. So the mainnet C-Chain EVM endpoint is:
/ext/bc/C/rpc
That's why public Avalanche URLs look like https://api.avax.network/ext/bc/C/rpc instead of a clean host. The C is the C-Chain; a subnet would have its blockchain ID there instead. WebSocket is the same path with /ws. It's not a quirk you did wrong — it's just how Avalanche namespaces its chains.
The C-Chain network IDs:
- Mainnet C-Chain: chain ID
43114 - Fuji testnet C-Chain: chain ID
43113
With SwiftNodes you skip the path gymnastics — the C-Chain is just:
https://rpc.swiftnodes.io/rpc/avalanche?key=YOUR_API_KEY
Connecting to the C-Chain
Because the C-Chain is EVM-equivalent, your existing libraries work unchanged — just point them at the endpoint and set chain ID 43114.
viem:
import { createPublicClient, http } from "viem";
import { avalanche } from "viem/chains";
const client = createPublicClient({
chain: avalanche,
transport: http("https://rpc.swiftnodes.io/rpc/avalanche?key=YOUR_API_KEY"),
});
const block = await client.getBlockNumber();
ethers v6:
import { JsonRpcProvider } from "ethers";
const provider = new JsonRpcProvider(
"https://rpc.swiftnodes.io/rpc/avalanche?key=YOUR_API_KEY"
);
console.log(await provider.getBlockNumber());
web3.py:
from web3 import Web3
w3 = Web3(Web3.HTTPProvider(
"https://rpc.swiftnodes.io/rpc/avalanche?key=YOUR_API_KEY"))
print(w3.eth.block_number)
To add it to MetaMask manually: RPC URL = your endpoint, Chain ID = 43114, Currency = AVAX, and an explorer like snowtrace.io.
Subnets (now "Avalanche L1s")
Here's where the second layer of confusion comes in. Avalanche's whole pitch is app-specific blockchains — subnets, rebranded to "Avalanche L1s" after the Avalanche9000 (ACP-77) upgrade. Projects like DeFi Kingdoms (DFK Chain), Dexalot, and others run their own sovereign chain with custom rules, gas tokens, and validator sets.
The key thing for developers: a subnet/L1 is a separate chain with its own RPC endpoint and its own chain ID. If you're building on DFK Chain, the C-Chain endpoint is useless to you — you need that subnet's RPC (which is again served at its own /ext/bc/<blockchainID>/rpc path). Don't assume "Avalanche RPC" covers a subnet; it doesn't. Each subnet's team publishes its own endpoint, and a managed provider serving the Primary Network C-Chain isn't automatically serving every subnet.
So the mental model is: C-Chain = the shared Avalanche EVM most apps use; subnets = independent chains you opt into per project.
Gotchas worth knowing
- Finality is fast and final. Avalanche's Snowman consensus gives the C-Chain sub-second-to-a-couple-seconds finality with no probabilistic reorgs — once a block is accepted, it's done. You don't need the deep confirmation counts you'd use on a chain with reorg risk. (This is a different model from L2 soft/hard finality — see Soft vs Hard Finality on L2s for the contrast.)
- Gas is AVAX with dynamic fees. The C-Chain uses an EIP-1559-style base-fee market denominated in nAVAX. Standard
eth_feeHistory/eth_maxPriorityFeePerGasapply. - Cross-chain transfers aren't
eth_*. Moving AVAX between the X, P, and C chains uses atomic transactions through Avalanche's own API, not Ethereum JSON-RPC. If you only touch the C-Chain you'll never hit this, but it surprises people expecting one unifiedeth_sendTransactionto move funds across all three. - Historical state needs an archive node. Querying old C-Chain balances or running traces at past blocks requires archive access, same as Ethereum — see Full Node vs Archive Node.
- Public endpoint rate limits.
api.avax.networkis fine for testing but rate-limited and not built for production load — the usual public vs paid RPC tradeoff.
The short version
If someone hands you "Avalanche RPC," they almost certainly mean the C-Chain (43114, EVM, standard eth_*). Point your normal Ethereum tooling at it and you're done. Reach for the X/P chains only for asset issuance or staking, and remember that subnets are their own chains with their own endpoints.
Want a production-grade Avalanche C-Chain endpoint without the /ext/bc/C/rpc paths or public rate limits? Our Avalanche RPC is flat-rate (no per-call metering), and it's one key across dozens of chains. Grab a free key and connect:
https://rpc.swiftnodes.io/rpc/avalanche?key=YOUR_API_KEY