Using XML-RPC with Python3 is really simple. Calling system.version on http://localhost/RCP2 is as simple as:

import xmlrpc.client

proxy = xmlrpc.client.ServerProxy("http://localhost/RPC2")

However, the default client is missing many features, like handling proxies. Using requests for the underlying connection allows for greater control of the http request.

The xmlrpc client allows to change the underlying transport class by a custom class. In order to use requests, we create a simple Transport class:

import requests
import xmlrpc.client

class RequestsTransport(xmlrpc.client.Transport):

    def request(self, host, handler, data, verbose=False):
        # set the headers, including the user-agent
        headers = {"User-Agent": "my-user-agent",
                   "Content-Type": "text/xml",
                   "Accept-Encoding": "gzip"}
        url = "https://%s%s" % (host, handler)
            response = None
            response =, data=data, headers=headers)
            return self.parse_response(response)
        except requests.RequestException as e:
            if response is None:
                raise xmlrpc.client.ProtocolError(url, 500, str(e), "")
                raise xmlrpc.client.ProtocolError(url, response.status_code,
                                                  str(e), response.headers)

    def parse_response(self, resp):
        Parse the xmlrpc response.
        p, u = self.getparser()
        return u.close()

To use this Transport class, we should use:

proxy = xmlrpc.client.ServerProxy(uri, transport=RequestsTransport())

We can now use requests to:

  • use proxies
  • skip ssl verification (on a development server) or adding the right certificate chain
  • set the headers
  • set the timeouts
  • ...

See the documentation or an example for more information.