Summary
The Polygon RPC API is the JSON-RPC interface your app uses to read Polygon PoS state and submit transactions. You connect over HTTP or WebSocket to a node that exposes standard Ethereum-compatible methods such as eth_call, eth_getLogs, and eth_sendRawTransaction. This page covers the exact chain settings, working request examples, and the failure modes developers hit most often. It also explains when a shared public endpoint is enough and when a dedicated Polygon node is the better fit for your workload.
The Polygon RPC API is the JSON-RPC surface your application uses to read Polygon PoS state and broadcast transactions. If you are wiring up a wallet, a backend indexer, or a dApp frontend, you need three things: the correct chain settings, a working request pattern, and a clear idea of which failures are your code versus the endpoint. This page gives you all three, then helps you decide whether a shared public endpoint or a dedicated Polygon node fits your workload.
Chain settings at a glance
Before you send a single request, confirm the network parameters. Polygon PoS mainnet and Polygon Amoy testnet use different chain IDs and different native currency symbols, and mixing them up is one of the most common setup mistakes.
| Setting | Polygon mainnet | Polygon Amoy testnet |
|---|---|---|
| Chain ID | 137 | 80002 |
| Chain name | Polygon Mainnet | Amoy |
| Native currency | POL (18 decimals) | POL (18 decimals) |
| Block explorer | polygonscan.com | amoy.polygonscan.com |
| Transport | HTTP, WebSocket | HTTP, WebSocket |
| Example endpoint | https://polygon.api.onfinality.io/public | https://polygon-amoy.api.onfinality.io/public |
Those public endpoints are useful for quick tests and low-volume reads. For production traffic, rate limits and shared capacity apply, so most teams move to a managed or dedicated endpoint. You can review the full Polygon RPC network page for supported transports and current access options.
If you are adding Polygon to a wallet or a frontend network switcher, the configuration usually looks like this:
const polygonMainnet = {
chainId: '0x89', // 137
chainName: 'Polygon Mainnet',
nativeCurrency: { name: 'POL', symbol: 'POL', decimals: 18 },
rpcUrls: ['https://polygon.api.onfinality.io/public'],
blockExplorerUrls: ['https://polygonscan.com'],
};
How to decide: public endpoint or dedicated node
The decision is usually about workload shape, not about which endpoint is "better" in the abstract. Use the table below to place your own traffic pattern.
| Your workload | Shared public endpoint | Managed RPC API | Dedicated Polygon node |
|---|---|---|---|
| Wallet reads, occasional eth_call | Fine for testing | Good fit | Overkill |
| dApp frontend with steady user traffic | Rate limits become visible | Good fit | Consider at high volume |
| Backend indexer scanning eth_getLogs | Not suitable | Possible with tuned ranges | Strong fit |
| High-frequency trading or bots | Not suitable | Possible | Strong fit |
| Archive queries over old blocks | Not available | Depends on plan | Strong fit |
| Debug/trace calls | Not available | Depends on plan | Strong fit |
A practical rule: if your app can tolerate occasional 429 responses and you only read recent state, a shared endpoint is enough. If you depend on log queries, historical state, trace calls, or predictable throughput, plan for a managed or dedicated setup. OnFinality offers both managed RPC API access and dedicated nodes for teams that need isolated capacity.
Sending your first Polygon JSON-RPC request
Every Polygon RPC call follows the same JSON-RPC 2.0 envelope. Start with a simple health check to confirm the endpoint is reachable and returning the expected chain.
curl -s https://polygon.api.onfinality.io/public \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'
A correct response returns the chain ID as a hex string:
{"jsonrpc":"2.0","id":1,"result":"0x89"}
If you get 0x89, you are on Polygon mainnet. If you get 0x13882, you are on Amoy testnet (80002). If you get a different value entirely, your endpoint is pointing at another network.
Reading a balance follows the same shape:
curl -s https://polygon.api.onfinality.io/public \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"eth_getBalance","params":["0x0000000000000000000000000000000000001010","latest"]}'
In JavaScript, the same call through ethers looks like this:
import { JsonRpcProvider } from 'ethers';
const provider = new JsonRpcProvider('https://polygon.api.onfinality.io/public');
const block = await provider.getBlockNumber();
const balance = await provider.getBalance('0x0000000000000000000000000000000000001010');
console.log({ block, balance: balance.toString() });
Polygon RPC methods you will actually use
Polygon PoS is EVM-compatible, so the method set matches Ethereum. The methods below cover most production traffic.
| Method | Purpose | Notes |
|---|---|---|
| eth_chainId | Identify the network | Use as a startup health check |
| eth_blockNumber | Latest block height | Cheap and safe to poll |
| eth_getBalance | Account balance | Returns hex wei |
| eth_call | Read contract state | No gas, no state change |
| eth_getLogs | Query event logs | Range limits apply on shared endpoints |
| eth_getTransactionReceipt | Confirm a transaction | Poll after broadcast |
| eth_sendRawTransaction | Broadcast a signed tx | Requires a funded signer |
| eth_getCode | Check contract deployment | Useful for address validation |
Two Polygon-specific details are worth remembering. First, the native gas token is POL, and the well-known fee address 0x0000000000000000000000000000000000001010 is used in gas accounting. Second, because Polygon PoS has had reorgs and state-sync delays historically, backends that index logs should track confirmations rather than assuming a block is final the moment it appears.
WebSocket subscriptions for live data
If you need push updates instead of polling, connect over WebSocket. The OnFinality Polygon endpoint supports both HTTP and WebSocket transport.
import WebSocket from 'ws';
const ws = new WebSocket('wss://polygon.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) => {
const msg = JSON.parse(data.toString());
if (msg.method === 'eth_subscription') {
console.log('New head:', msg.params.result.number);
}
});
WebSocket connections are stateful. If your process restarts or the socket drops, you must resubscribe. Build reconnect logic with backoff, and re-fetch the latest block on reconnect so you do not miss events during the gap.
Debug path: common Polygon RPC failures
When a request fails, the error message usually points at the cause. Use this table to move from symptom to fix.
| Symptom | Likely cause | Next step |
|---|---|---|
| 429 Too Many Requests | Shared endpoint rate limit | Reduce polling, batch calls, or move to a managed plan |
| eth_getLogs returns range error | Query window too wide | Split into smaller block ranges |
| eth_call reverts with no reason | Contract reverted or wrong ABI | Simulate with eth_call and check inputs |
| Transaction stuck pending | Gas price too low for current conditions | Re-estimate gas and consider replacement |
| nonce too low | Local nonce out of sync | Resync nonce from eth_getTransactionCount |
| Missing trie node | Archive data not available | Use an archive-capable endpoint |
| WebSocket closes silently | Idle timeout or network drop | Add heartbeat and reconnect logic |
A quick diagnostic loop for a failing endpoint:
# 1. Is the endpoint alive and on the right chain?
curl -s https://polygon.api.onfinality.io/public -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'
# 2. Is it synced to the head?
curl -s https://polygon.api.onfinality.io/public -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"eth_blockNumber","params":[]}'
If eth_chainId is correct but eth_blockNumber lags behind a public block explorer, the node may be catching up. If both succeed but your app still fails, the problem is likely in your request payload, ABI, or nonce handling rather than the endpoint.
Production readiness checklist
Before you point real traffic at any Polygon endpoint, confirm these items:
- Chain ID and native currency match the network you intend to use (137 for mainnet, 80002 for Amoy).
- You have a fallback endpoint or provider in case the primary becomes unavailable.
- Log queries are chunked into ranges the endpoint accepts.
- WebSocket clients implement reconnect and resubscribe.
- You monitor error rates, latency, and block height lag rather than only checking uptime.
- Archive and trace needs are confirmed with your provider before launch, not after.
A simple monitoring probe keeps you ahead of outages:
async function probe(url) {
const start = Date.now();
const res = await fetch(url, {
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, latencyMs: Date.now() - start, block: parseInt(json.result, 16) };
}
Run this on a schedule and alert when latency rises or the block height stops advancing.
Where OnFinality fits
OnFinality provides RPC API access and dedicated node infrastructure for Polygon and many other networks. For quick tests, the public endpoints above are enough. For production apps that need predictable throughput, archive access, or isolated capacity, a managed or dedicated setup removes the shared-endpoint constraints. You can compare plans on the RPC pricing page and browse other chains on the supported RPC networks list. If you are still weighing providers, the RPC provider selection guide walks through the evaluation criteria that matter most.
Key Takeaways
- Polygon mainnet uses chain ID 137 and POL as the native currency; Amoy testnet uses 80002.
- The Polygon RPC API is EVM-compatible, so standard Ethereum JSON-RPC methods apply.
- Public endpoints are fine for testing and light reads, but log queries, archive data, and high throughput usually need a managed or dedicated endpoint.
- Most failures trace back to rate limits, log range limits, nonce sync, or missing archive data, and each has a specific fix.
- Monitor latency and block height lag, not just uptime, and always keep a fallback endpoint.
Frequently Asked Questions
What is the Polygon RPC API?
It is the JSON-RPC interface that lets your application read Polygon PoS state and submit transactions through a node. It follows the JSON-RPC 2.0 standard and supports the same method set as Ethereum because Polygon PoS is EVM-compatible.
What is the Polygon chain ID?
Polygon mainnet uses chain ID 137 (0x89). Polygon Amoy testnet uses chain ID 80002 (0x13882). Always confirm the chain ID with eth_chainId before sending transactions.
Does Polygon RPC support WebSocket?
Yes. The OnFinality Polygon endpoint supports both HTTP and WebSocket transport, which lets you subscribe to newHeads, logs, and other events instead of polling.
Why does eth_getLogs fail on Polygon?
Most log query failures come from requesting too wide a block range. Shared endpoints limit the range to protect capacity. Split your query into smaller windows or use a provider that supports wider ranges.
Can I use a public Polygon RPC endpoint in production?
You can, but shared public endpoints apply rate limits and may not offer archive or trace data. For production traffic, a managed or dedicated endpoint gives you more predictable behavior.
How do I get testnet POL for Amoy?
Use a Polygon Amoy faucet to request testnet POL for development. The Amoy network uses the same POL token symbol as mainnet but on a separate chain, so testnet funds have no mainnet value.