Skip to content
USDC Price:$1.0000Gas:
Arcscan

Public RPC

https://rpc.arc-scan.io is a free JSON-RPC endpoint for Arc mainnet that fronts several independent providers, so a single provider’s outage is not visible to you.

https://rpc.arc-scan.io
No key, no account, no signup.
Using a wallet? Connect RPC in one clickThe button, plus the one step MetaMask and Rabby still need from you.

The endpoint#

One hostname, one chain, no credential. It answers the ordinary read methods, refuses a short list of others by policy, and identifies itself as arcscan-rpc-gateway/1 when you ask it web3_clientVersion — which is how you can tell you reached us and not some other endpoint your wallet had configured.

PropertyValue
URLhttps://rpc.arc-scan.io
ChainArc mainnet only — chain id 5042, hex 0x13b2
TransportHTTPS POST only. A GET answers 405 with allow: POST, OPTIONS.
AuthenticationNone. No key, no account, no signup, no header.
Browser callsAllowed — every answer carries access-control-allow-origin: *.
CostFree, and rate limited per caller.

Mainnet only

This endpoint serves chain 5042 and nothing else — ask it net_version and it says 5042. There is no public Arcscan JSON-RPC endpoint for Arc Testnet. If you are working against testnet, use testnet.arc-scan.ioOpens in a new tab for the explorer and your own node or provider for RPC.

Your first call#

There is nothing to sign up for, so the first call is the whole of getting started. Ask which chain you are talking to:

curl -s -X POST https://rpc.arc-scan.io \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId"}'

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x13b2"
}

And the head of the chain. Arc produces a block roughly every half second, so this number moves while you read it.

curl -s -X POST https://rpc.arc-scan.io \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber"}'

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0xe2a22d"
}

Batches#

A JSON array of calls is answered with an array of results, in id order. Up to 50 entries and 131,072 bytes per request; over either cap the whole request is rejected with 413 before any of it runs.

curl -s -X POST https://rpc.arc-scan.io \
  -H 'content-type: application/json' \
  -d '[{"jsonrpc":"2.0","id":1,"method":"eth_chainId"},
       {"jsonrpc":"2.0","id":2,"method":"eth_blockNumber"}]'

[
  {
    "jsonrpc": "2.0",
    "id": 1,
    "result": "0x13b2"
  },
  {
    "jsonrpc": "2.0",
    "id": 2,
    "result": "0xe2a22e"
  }
]

A batch is not a snapshot

The two heights above differ by one. Each entry is served independently and the chain moves between them, so a batch never gives you a consistent view of a single moment. When you need several facts about one block, pin them to a block number or hash rather than to latest.

What it answers#

The ordinary eth_ read methods work: block, transaction and receipt lookups, eth_getBalance, eth_call, eth_getLogs, eth_gasPrice, eth_estimateGas. Four methods are answered by the endpoint itself with no outbound request — eth_chainId, net_version, web3_clientVersion and eth_accounts, which returns an empty array because we hold no accounts.

Rather than publish a list of every method that works, ask: anything not refused below is forwarded. A method no source offers comes back as -32601 with data.reason of method_not_served, which is a different fact from a policy refusal and says so.

What it refuses#

Refusals are deliberate, and each one states who decided and why. The reason is machine readable: error.data.reason is refused_by_policy and error.data.policy is one of the slugs below — which is what a client should read to decide whether asking again later could ever help. For every slug here, it cannot.

policyWhyMeasured examples
no_custodyThis endpoint holds no keys and will not forward a signing request.eth_sendTransaction, eth_sign, eth_signTypedData_v4
namespaceA whole namespace that is not served here.debug_traceTransaction, ots_getApiLevel
costThe answer is very large and this endpoint is metered.trace_block
no_transportHTTP only. There is no subscription transport here to serve it over.eth_subscribe, eth_unsubscribe
single_legOnly one of the sources behind this endpoint offers it, so publishing it would promise a capability that could disappear without warning.eth_getProof
opacityThe answer would describe a node this endpoint does not operate, so there is no honest value to give.net_peerCount, net_listening
curl -s -X POST https://rpc.arc-scan.io \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_sendTransaction","params":[{}]}'

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32601,
    "message": "arc-scan.io does not serve eth_sendTransaction on this endpoint. This is our own policy decision, not a limitation of the Arc network. This endpoint holds no keys and will not forward a signing request. Sign locally and use eth_sendRawTransaction.",
    "data": {
      "reason": "refused_by_policy",
      "method": "eth_sendTransaction",
      "policy": "no_custody",
      "documentation": "https://arc-scan.io/developers"
    }
  }
}

A refusal is HTTP 200

Every refusal above answers 200 OK with the error inside the JSON-RPC error object, which is what the JSON-RPC specification asks for. So a monitor that watches HTTP status alone will call all of this healthy. Read error.code and error.data.reason, not the status line.

Sending a transaction#

We hold no keys, so every method that would require custody of one is refused — sign locally instead. An already-signed transaction can be broadcast: eth_sendRawTransaction is forwarded, and it is deliberately sent to exactly one provider and never retried, because a proxy that retried a broadcast could submit your transaction twice.

Read the error, do not resubmit blindly

already known and nonce too low come back from the node unchanged rather than being smoothed over, and both usually mean your transaction is already in flight. A malformed payload comes back as -32602 with the node’s own decode message.

Failover#

Behind the one hostname are several independent Arc mainnet providers. A call that fails on one is retried on another, a provider that starts erroring or rate limiting us is cooled off and skipped, and none of that is visible in your response: you get an answer, or an honest error, and never a hint about which source served you. We do not publish who they are.

Two consequences worth knowing

A method offered by only one provider is refused rather than served (the single_leg row above) — a capability that would vanish the moment one source cooled is not a capability we will promise. And if no source could answer at all, you get -32603 with data.reason of unreachable and a message saying that nothing about the result should be assumed, rather than an empty result that would read as “nothing happened on chain”.

Limits and errors#

Requests are rate limited per caller. We are not publishing the threshold here — the only figure we could quote is a configured one, and what you actually meet is the deployed edge — so treat a 429 as the signal, honour its retry-after, and back off rather than tuning against a number. The size caps are exact, and are stated in the refusal itself.

HTTP/1.1 429 Too Many Requests
retry-after: 1
content-type: application/json

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32005,
    "message": "arc-scan.io is rate limiting requests from this client. Retry shortly.",
    "data": {
      "reason": "edge_rate_limited",
      "retry_after_seconds": 1,
      "scope": "client"
    }
  }
}
HTTP · JSON-RPC codeWhat happened
405 · -32600You used GET. JSON-RPC requests must use POST.
413 · -32600The request exceeded 131072 bytes or 50 batch entries; data.reason is request_too_large and both caps are in the message.
429 · -32005Too many requests from one caller. data.reason is edge_rate_limited; honour retry-after.
200 · -32601Either a method we refuse (data.reason is refused_by_policy, with a policy slug) or one no source offers (method_not_served).
200 · -32602Your parameters were rejected. This one is the node’s own message, passed through unchanged.
200 · -32603No answer was obtained at all — data.reason is unreachable. The message says so explicitly, and nothing about the result should be assumed.
Public RPC · Arcscan docs | Arcscan