Getting Started With HTTPie To Interact With APIs

HTTPie is an HTTP client and an alternative to the famous cURL. Its goal is to make it easy to interact with HTTP servers, using a simple and natural syntax. This post will show how to quickly start using those benefits to test APIs.

There is actually another good tool I could recommended, Postman, which provides a user interface. But if you like the idea of being productive using a CLI tool, cURL and httpie are your options.

So you need to install HTTPie first

Assuming you already have Python 3 installed on your machine, you can install HTTPie as an add-on module for Python. Even better, as a good practice of seperating things, in a virtual environment. That's how I work, but it is just one of the options.

$ pip install httpie

As an alternative, you could use the package manager for your system, such as "apt-get", "yum", "homebrew", or other. For example, on macOS:

$ brew update
$ brew install httpie

Once done, you can call the HTTPie program by its name, adding the path if needed. You may want to it call it with the -h option the first time to get see its usage instructions:

$ http -h

usage: http [--json] [--form] [--pretty {all,colors,format,none}]
            [--style STYLE] [--print WHAT] [--headers] [--body] [--verbose]
            [--all] [--history-print WHAT] [--stream] [--output FILE]
            [--download] [--continue]
            [--session SESSION_NAME_OR_PATH | --session-read-only SESSION_NAME_OR_PATH]
            [--auth USER[:PASS]] [--auth-type {basic,digest}]
            [--proxy PROTOCOL:PROXY_URL] [--follow]
            [--max-redirects MAX_REDIRECTS] [--timeout SECONDS]
            [--check-status] [--verify VERIFY]
            [--ssl {ssl2.3,ssl3,tls1,tls1.1,tls1.2}] [--cert CERT]
            [--cert-key CERT_KEY] [--ignore-stdin] [--help] [--version]
            [--traceback] [--default-scheme DEFAULT_SCHEME] [--debug]
            [METHOD] URL [REQUEST_ITEM [REQUEST_ITEM ...]]

Getting started with a demo or test service

We can use the http://httpbin.org service maintained by Kenneth Reitz, to start testing, if we do not have our own testing API server.

This service provides the /get endpoint to help test a GET request, which is what you do when you want to get an HTML page or read some information that is exposed by an API endpoint for that purpose.

$ http http://httpbin.org/get

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 257
Content-Type: application/json
Date: Sat, 14 Oct 2017 07:24:21 GMT
Server: meinheld/0.6.1
Via: 1.1 vegur
X-Powered-By: Flask
X-Processed-Time: 0.00122308731079

{
    "args": {},
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Connection": "close",
        "Host": "httpbin.org",
        "User-Agent": "HTTPie/0.9.9"
    },
    "origin": "85.170.243.247",
    "url": "http://httpbin.org/get"
}

As another GET request example, we can test the /image/png endpoint which returns a PNG image.

$ http http://httpbin.org/image/png

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 8090
Content-Type: image/png
Date: Sat, 14 Oct 2017 06:53:08 GMT
Server: meinheld/0.6.1
Via: 1.1 vegur
X-Powered-By: Flask
X-Processed-Time: 0.000449180603027



+-----------------------------------------+
| NOTE: binary data not shown in terminal |
+-----------------------------------------+

Let's now submit a form with data using the /post endpoint.

$ http -f POST http://httpbin.org/post firstname=Kamon lastname=Ayeva

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 477
Content-Type: application/json
Date: Sat, 14 Oct 2017 07:02:47 GMT
Server: meinheld/0.6.1
Via: 1.1 vegur
X-Powered-By: Flask
X-Processed-Time: 0.000810146331787

{
    "args": {},
    "data": "",
    "files": {},
    "form": {
        "firstname": "Kamon",
        "lastname": "Ayeva"
    },
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Connection": "close",
        "Content-Length": "30",
        "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
        "Host": "httpbin.org",
        "User-Agent": "HTTPie/0.9.9"
    },
    "json": null,
    "origin": "85.170.243.247",
    "url": "http://httpbin.org/post"
}

I have also played with other demo or toy API servers, such as http://jsonplaceholder.typicode.com with it's /posts endpoint.

We can get the list of posts on the server:

$ http http://jsonplaceholder.typicode.com/posts

HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
CF-Cache-Status: HIT
CF-RAY: 3ad8dd1586b614e5-CDG
Cache-Control: public, max-age=14400
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Sat, 14 Oct 2017 07:35:44 GMT
Etag: W/"6b80-Ybsq/K6GwwqrYkAsFxqDXGC7DoM"
Expires: Sat, 14 Oct 2017 11:35:44 GMT
Pragma: no-cache
Server: cloudflare-nginx
Set-Cookie: __cfduid=ddf4dd8ed5ea69bb8403aeba069f169331507966544; expires=Sun, 14-Oct-18 07:35:44 GMT; path=/; domain=.typicode.com; HttpOnly
Transfer-Encoding: chunked
Vary: Accept-Encoding
Via: 1.1 vegur
X-Content-Type-Options: nosniff
X-Powered-By: Express

[
    {
        "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
        "id": 1,
        "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
        "userId": 1
    },
    {
        "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla",
        "id": 2,
        "title": "qui est esse",
        "userId": 1
    },
    ...
    ...
    ...
    {
        "body": "cupiditate quo est a modi nesciunt soluta\nipsa voluptas error itaque dicta in\nautem qui minus magnam et distinctio eum\naccusamus ratione error aut",
        "id": 100,
        "title": "at nam consequatur ea labore ea harum",
        "userId": 10
    }
]

We can add a post to the list of posts:

$ http -f POST http://jsonplaceholder.typicode.com/posts userId=1 title="Been trying this API" body="I been doing tests on this API using httpie and it works like a charm."

HTTP/1.1 201 Created
Access-Control-Allow-Credentials: true
CF-RAY: 3ad8ea5497b66956-CDG
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 149
Content-Type: application/json; charset=utf-8
Date: Sat, 14 Oct 2017 07:44:47 GMT
Etag: W/"95-MKeni/3m7kBc6y7Ue6geX3blGN0"
Expires: -1
Pragma: no-cache
Server: cloudflare-nginx
Set-Cookie: __cfduid=db6b89d4ce1115eb775764c905d003e1b1507967086; expires=Sun, 14-Oct-18 07:44:46 GMT; path=/; domain=.typicode.com; HttpOnly
Vary: Origin, X-HTTP-Method-Override, Accept-Encoding
Via: 1.1 vegur
X-Content-Type-Options: nosniff
X-Powered-By: Express

{
    "body": "I been doing tests on this API using httpie and it works like a charm.",
    "id": 101,
    "title": "Been trying this API",
    "userId": 1
}

What next?

Next, we can exercise on the real stuff out there, and look at cases like using API endpoints which require authentication. I am currently playing with the APIs of different services including DNSimple, GitHub and Digital Ocean. So expect one of them featured in a future post.

comments powered by Disqus

Need help for your project?

Our team can contribute to your project, working on a specific task, or doing all the coding based on your specifications, using Python, a web framework such as Django or a CMS.