10 min read
|
Published
|
Updated

JSON-RPC Blockchain Nodes: PHP, Python & JS Guide

How JSON-RPC 2.0 works with blockchain nodes: request and response format, error codes and batching, with working PHP, Python and JavaScript examples.

Chapters
C
Chaingateway Team
Blockchain Experts

Reviewed by Maurice Sobiera

JSON-RPC is a remote procedure call protocol that encodes requests and responses as JSON. An Ethereum node exposes it over HTTP or WebSocket, so a client can read blocks and balances or submit signed transactions by posting a small JSON object. The protocol is versioned and specified, which is why the same code shape works across most EVM nodes.

This article shows the request and response format, the error codes, batching, and one working example each in PHP, Python and JavaScript.

What is JSON-RPC?

JSON-RPC 2.0 is a stateless protocol defined in the JSON-RPC 2.0 specification. The client sends a request object. The server answers with a response object that has the same id.

A request has four members:

MemberMeaning
jsonrpcThe string "2.0"
methodThe name of the method to call, for example eth_blockNumber
paramsAn array or object with the arguments. May be omitted if the method takes none
idA string, number or null. The response carries the same value

A response contains either a result member or an error member, never both. A request without an id is a notification, and the server must not reply to it.

How do you send a JSON-RPC request to a node?

Send an HTTP POST request with the header Content-Type: application/json and the request object as the body. The node’s HTTP endpoint is usually port 8545 for Ethereum clients such as Geth. WebSocket connections work the same way, but keep one connection open.

The method names and parameters are defined by the blockchain, not by JSON-RPC. For Ethereum, the JSON-RPC API reference on ethereum.org lists them. eth_blockNumber takes no parameters and returns the current block number as a hex-encoded quantity.

Request:

{"jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": 1}

Response:

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

Quantities are hex strings with a 0x prefix and no leading zeros. The result 0x4b7 is block 1207.

Example code in PHP, Python and JavaScript

All three examples send the request above to a local node and print the response. They use POST, because JSON-RPC over HTTP does not use GET.

PHP, with the curl extension:

<?php
$request = json_encode([
'jsonrpc' => '2.0',
'method' => 'eth_blockNumber',
'params' => [],
'id' => 1,
]);
$curl = curl_init('http://localhost:8545');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
$response = json_decode(curl_exec($curl), true);
curl_close($curl);
echo hexdec($response['result']); // block number as an integer

Python, with the requests library:

import requests
payload = {"jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": 1}
response = requests.post("http://localhost:8545", json=payload, timeout=10)
body = response.json()
print(int(body["result"], 16)) # block number as an integer

JavaScript, with fetch:

const response = await fetch('http://localhost:8545', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
method: 'eth_blockNumber',
params: [],
id: 1,
}),
});
const body = await response.json();
console.log(parseInt(body.result, 16)); // block number as an integer

How do you read a balance?

Call eth_getBalance with an address and a block parameter. The block parameter can be a hex block number or a tag such as "latest", "safe" or "finalized". The result is the balance in wei, as a hex quantity.

{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": ["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"],
"id": 2
}

For payment systems the tag matters. "latest" can still be reorganized, while "finalized" cannot. Use "finalized" when you credit a deposit and "latest" only for display.

What do the error codes mean?

When a call fails, the response has an error object with a numeric code and a message. The specification reserves these codes:

CodeNameTypical cause
-32700Parse errorThe body is not valid JSON
-32600Invalid RequestThe JSON is not a valid request object
-32601Method not foundWrong method name, or the node does not expose that namespace
-32602Invalid paramsWrong number or type of parameters
-32603Internal errorThe node failed while processing the call

Always check for error before you read result. JSON-RPC carries errors in the response body, so check the body no matter what the HTTP status is.

Can you send several calls in one request?

Yes. A batch is a JSON array of request objects, and the server answers with an array of responses. The responses may come in any order, so match them by id.

[
{"jsonrpc": "2.0", "method": "eth_blockNumber", "params": [], "id": 1},
{"jsonrpc": "2.0", "method": "eth_chainId", "params": [], "id": 2}
]

Batching saves round trips. Node operators may limit the batch size, so check the limit of the endpoint you use.

When should you use an API instead of a node?

Running your own node gives you raw JSON-RPC access, but you maintain the node. For wallet creation, token transfers and deposit notifications, Chaingateway offers a REST API instead; its endpoints are listed in the OpenAPI file. See how to set up a Tron node for what operating a node involves.

How we write these articles

Ready to build this yourself? Get your API key — 7-day trial, no card required — or see the Blockchain API for the full endpoint reference.

C
Chaingateway Team
Blockchain Experts

The Chaingateway team is dedicated to simplifying blockchain integration for developers worldwide.