jsonrpcclient Guide

This library allows you to call remote procedures using the JSON-RPC message format.


Install the package with the Requests library (alternatively, see other options):

$ pip install "jsonrpcclient[requests]"

For Python versions older than 3.5, install a 2.x version, and jump over to the 2.x docs.

$ pip install "jsonrpcclient[requests]>=2,<3"


The simplest way to send a standard http request is to use the convenience function request.

from jsonrpcclient import request
response = request("http://cats.com", "speak", name="Yoko")

The arguments to request are: the http server’s endpoint url, the RPC method to call, followed by any arguments to the method.

The response.data.result contains the payload back from the server.

>>> print(response.data.result)

For more advanced usage, read on.

Create a client object to work with:

from jsonrpcclient.clients.http_client import HTTPClient
client = HTTPClient("http://cats.com")

Send a request:

response = client.send('{"jsonrpc": "2.0", "method": "ping", "id": 1}')

Instead of typing the whole JSON-RPC request string, a Request class makes it easy for you:

>>> from jsonrpcclient.requests import Request
>>> Request("ping")
{'jsonrpc': '2.0', 'method': 'ping', 'id': 1}

The first argument to Request is the remote method to call, and subsequent ones are arguments to the method.

>>> Request("cat", name="Yoko")
{'jsonrpc': '2.0', 'method': 'cat', 'params': {'name': 'Yoko'}, 'id': 1}

Pass a request_id to specify the “id” part of the JSON-RPC request.

>>> Request("ping", request_id="foo")
--> {"jsonrpc": "2.0", "method": "ping", "id": "foo"}

If a request id is not specified, one is generated for the request.

Sending a Request object:

response = client.send(Request("ping"))

If a response is not required, use the Notification class instead of Request.

A request() method is provided which wraps send(Request()).

response = client.request("ping")

If a response is not required, use notify instead of request.


Batch requests

JSON-RPC allows you to send multiple requests in a single message:

req = '''[
    {"jsonrpc": "2.0", "method": "cat", "id": 1},
    {"jsonrpc": "2.0", "method": "dog", "id": 2}

Send multiple Request objects:

responses = client.send([Request("cat"), Request("dog")])

The server may not support batch requests.


A Response object is returned from the send, request and notify methods.

The object has three attributes:

  • text: This is the response text received from the server.
  • raw: The framework’s own response object, e.g. for the HTTP client this is the requests library’s Response object.
  • data: The parsed response. (see below)

For single requests, data contains the following attributes:

  • id: The request ID.
  • result: The result part of the JSON-RPC response message. This is the payload you’ve requested from the server.

For batch requests, data is a list of responses. When iterating over the responses, check the ok attribute.

for responses in response.data:
    if response.ok:

If ok is False, the other attributes are message, code and data.

If the request wasn’t successful, an exception will be raised.


Any of the following options can be configured in:

  • arguments to send/request/notify.
  • arguments to the client;
  • the config file (see below);


Adds log handlers, to log incoming/outgoing messages to stderr. (this option can’t be passed to send/request/notify, only to the client or config file.)


Specifies a generator which will be used to create the “id” part of the JSON-RPC request. Some built-in options are in the id_generators module: decimal, hexadecimal, random and uuid. Default is id_generators.decimal().


>>> from jsonrpcclient import id_generators
>>> random_ids = id_generators.random()
>>> client.request("ping", id_generator=random_ids)
--> {"jsonrpc": "2.0", "method": "ping", "id": "9zo2a2xb"}


Show abbreviated requests and responses in logs. Default is False.


Validate responses against the JSON-RPC schema. Default is True.

Config file

Here’s an example of the config file .jsonrpcclientrc - this should be placed in the current or home directory:

basic_logging = no
id_generator = jsonrpcclient.id_generators.decimal
trim_log_values = no
validate_against_schema = yes

Configuring the Requests library

HTTPClient makes use of Kenneth Reitz’s Requests library. The Session is available so you can configure it before sending any requests.

For example, Basic Auth:

client.session.auth = ("user", "pass")

SSL authentication:

client.session.verify = "/path/to/certificate"

Custom HTTP headers:

client.session.headers.update({"Content-Type": "application/json-rpc"})

You can also configure some Requests options when calling send:

client.send(req, verify=True, cert="/path/to/certificate",
            headers={"Content-Type": "application/json-rpc"})

As in the Requests library, any dictionaries passed to send in named arguments will be merged with the session-level values that are set. The method-level parameters override session parameters.


Request and response messages are logged to the loggers jsonrpcclient.client.request and jsonrpcclient.client.response on the INFO log level.

>>> client.request("ping")
--> {"jsonrpc": "2.0", "method": "ping", "id": 4}
<-- {"jsonrpc": "2.0", "result": "pong", "id": 4} (200 OK)

No handlers are created by default. Here’s an example of adding handlers to the loggers and setting the log level to INFO:

from logging.config import dictConfig
log_config = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "request": {"format": "<-- %(message)s"},
        "response": {"format": "<-- %(message)s (%(http_code)s %(http_reason)s)"},
    "handlers": {
        "request": {"formatter": "request", "class": "logging.StreamHandler"},
        "response": {"formatter": "response", "class": "logging.StreamHandler"},
    "loggers": {
        "jsonrpcclient": {"level": "INFO"},
        "jsonrpcclient.client.request": {"handlers": ["request"]},
        "jsonrpcclient.client.response": {"handlers": ["response"]},

(For non-http clients, don’t include http_code and http_reason in the formats.)

For the lazy, you can pass basic_logging=True when creating the client object, which will add a StreamHandler to each logger and set the log level to INFO. (Alternatively call client.basic_logging()).