Sending a JSON request with curl means remembering three flags and quoting a JSON body inside a shell string. HTTPie was built around the observation that this is the single most common thing anyone does with an HTTP client, and that it should therefore be the default rather than an assembly job.

The short verdict. Worth installing if you poke at APIs by hand — the syntax is quicker to write and the coloured, pretty-printed output means you can read a response without piping it anywhere. But every API’s documentation gives you a curl command, every server has curl and none has HTTPie, and curl is what belongs in a script. This is a tool for the terminal you are sitting in front of, not for anything that has to run somewhere else.

What it changes

curlhttp
Sending JSON-X POST -H 'Content-Type: ...' -d '{...}'The default
OutputRaw bytes, no colourFormatted, highlighted, headers shown
MethodInferred, or -XThe first argument
Redirects-L, and people forget--follow; also not on by default
Sessions and cookiesCookie jar files--session=name, stored for you
Written inCPython — noticeably slower to start
Present everywhereYesNo
Protocol coverageEnormous — far beyond HTTPHTTP only

Installing it — the command is not the package

sudo apt install httpie        # Debian, Ubuntu
sudo dnf install httpie
sudo pacman -S httpie
pipx install httpie            # anywhere, without touching system Python

http --version                 # the command is `http`, not `httpie`

The package is httpie; the command you type is http (and https, which is the same thing with the scheme assumed). That catches everyone once. Note also that installing it with pip as root is the exact thing not to do — use your package manager, or pipx.

The syntax, translated

You wantcurlHTTPie
A GETcurl https://api.example.com/usershttp api.example.com/users
A JSON POSTcurl -X POST -H 'Content-Type: application/json' -d '{"name":"bob"}' URLhttp POST URL name=bob
A non-string fieldHand-written JSONage:=30, admin:=true
A query parameter?page=2 in the URLpage==2
A header-H 'X-Token: abc'X-Token:abc
Basic auth-u user:pass-a user:pass
Form encoding-d 'a=b'--form a=b
Upload a file-F 'f=@x.png'--form f@x.png
Headers only-I--headers
Show the request too-v-v
Follow redirects-L--follow
Save to a file-O--download

Four separators do all the work, and they are worth learning as a set: = for a string field, := for raw JSON, == for a query parameter, : for a header. Once those are in your fingers a fairly involved request becomes one readable line:

http POST api.example.com/users \
  Authorization:"Bearer $TOKEN" \
  name=Alice email=alice@example.com \
  age:=34 tags:='["admin","beta"]' \
  active:=true

Two more that earn their place. --offline prints the request it would send without sending it, which is the fastest way to check you have built what you think you have. And --session=work keeps cookies and headers across invocations, so you authenticate once and stop pasting a token into every command.

http --offline POST api.example.com/users name=bob age:=30
http --session=work -a alice:secret api.example.com/login
http --session=work api.example.com/me        # still authenticated

Where curl is still the right answer

  • Anything in a script, container or CI job. curl is present on every system in the world and HTTPie is on almost none of them. A pipeline that depends on installing a Python package first is a pipeline with a new failure mode.
  • Health checks and readiness probes. curl -fsS is the idiom, and its exit codes are what everything expects. HTTPie’s startup time also matters when something runs every five seconds.
  • Following documentation. Every API’s quickstart is a curl command. Translating each one is friction you did not need.
  • Anything that is not plain HTTP. FTP, SFTP, SMTP, MQTT-over-websockets, client certificates, unix sockets, --resolve to test a host before DNS changes, low-level TLS debugging. HTTPie does none of it.
  • Piping into other tools. HTTPie detects it is not writing to a terminal and disables formatting, so this works — but if you are only going to send the output to jq anyway, the pretty printing was the entire benefit.
  • Very large downloads. curl or wget, with resume.

If the startup time bothers you

HTTPie is a Python program, and on a cold start you can feel it — fine when you are reading the response, irritating in a loop. xh is a Rust reimplementation that accepts substantially the same syntax and starts instantly.

xh POST api.example.com/users name=bob age:=30     # same syntax, much faster

It does not implement every HTTPie feature, and sessions and plugins are the usual gaps. If you like the syntax and use it constantly, it is worth trying; if you use it twice a week, the difference is not worth a second tool.

Quick reference

http example.com/api                 # GET
http POST example.com/api name=bob   # JSON POST
http PUT example.com/api/1 age:=30   # raw JSON value
http example.com/api page==2         # query parameter
http example.com/api X-Token:abc     # header
http -a user:pass example.com/api    # basic auth
http --form example.com/upload f@photo.png
http --offline POST example.com name=bob    # build it, do not send it
http --session=work example.com/me
http --download example.com/big.iso

Related