
curl often means writing long commands full of -H and -d flags, then dealing with a wall of unformatted JSON. HTTPie makes API testing easier with readable request syntax, automatic JSON handling, and colorized, formatted output, letting you send requests with data, headers, and authentication directly from the terminal.If you manage web servers or work with APIs, you probably send HTTP requests from the terminal several times a day. You might check whether a health endpoint returns HTTP 200 after a deployment, post test data to a new API, or verify which headers a reverse proxy adds.
curl handles all these tasks, but sending JSON often requires extra flags, careful quoting, and a separate tool such as jq to make the response easier to read.
HTTPie (pronounced aitch-tee-tee-pie) is an open-source command-line HTTP client written in Python, designed to make working with APIs and HTTP servers more convenient. You specify the HTTP method, URL, and request data using a readable syntax, and HTTPie handles the request formatting and displays supported responses with colors and indentation.
It provides two commands, http and https, for sending HTTP and HTTPS requests, respectively. The https command assumes the https:// scheme when one is not specified.
This updated guide replaces our older HTTPie article, which covered HTTPie 1.x. Since then, the project has moved to the httpie/cli repository on GitHub, dropped Python 2.7 support, introduced nested JSON syntax, and added the httpie cli command for managing plugins.
The latest release listed in the official documentation is HTTPie 3.2.4, released on November 1, 2024. Verify the release status again immediately before publication.
How HTTPie Builds a Request from Request Items
Before installing anything, it helps to understand how HTTPie parses a command line. Almost every example later in this guide uses the same handful of separators. Once you understand them, you can build most HTTP requests without looking up the syntax.
The general syntax looks like this:
http [FLAGS] [METHOD] URL [ITEM ...]
The HTTP method is optional. If you omit it, HTTPie uses GET when no request data is supplied and POST when request data is supplied. You can also use a shortcut for localhost: http :8080/health sends a request to http://localhost:8080/health, which is useful when testing a service running on your own machine.
Everything after the URL is a request item. HTTPie determines the type of each item from the separator between its key and value:
Header:Valueadds an HTTP header, for exampleUser-Agent:tecmint-check/1.0.param==valueadds a URL query parameter. For example,page==2appends?page=2, with HTTPie handling URL encoding for the parameter.field=valueadds a string field to the request body. By default, HTTPie serializes data fields as JSON. Use--formto send form-encoded data or--multipartto send multipart form data.field:=jsonadds a raw JSON value, which is useful for numbers, booleans, arrays, and objects. For example,port:=8080sends a number, whileenabled:=truesends a boolean.field@/path/fileuploads a file as a form field. This requires--formor--multipartand results in a multipart upload when a file field is present.field=@/path/filereads a file’s contents into a field as a string.field:=@/path/file.jsonreads a file and embeds its contents as a JSON value.
The difference between = and := catches many beginners. Consider these two examples:
http POST https://api.example.com/devices port=8080 http POST https://api.example.com/devices port:=8080
The first sends "port": "8080" as a JSON string, while the second sends "port": 8080 as a JSON number. If an API schema requires an integer, sending a string may cause validation to fail. The exact response depends on how the API handles invalid input.
Remember these separators, and you’ll be able to construct headers, query parameters, JSON bodies, and file uploads directly from the command line with much less typing.
Install HTTPie: Now that the syntax makes sense, let’s install HTTPie. Most major Linux distributions package it, although the version available depends on the distribution and its release cycle.
On Ubuntu and Debian, you can install HTTPie from the distribution repositories. On Ubuntu, the package is available through the universe component, which may need to be enabled first.
sudo apt update sudo apt install -y httpie
If you want to use the version provided by the HTTPie project, add its official APT repository and signing key:
curl -SsL https://packages.httpie.io/deb/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/httpie.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/httpie.gpg] https://packages.httpie.io/deb ./" | sudo tee /etc/apt/sources.list.d/httpie.list > /dev/null sudo apt update sudo apt install -y httpie
This repository configuration specifies amd64. If you use ARM64 or another architecture, check the repository’s supported architectures before using this entry.
On Fedora, HTTPie is available in Fedora’s standard repositories, so you can install it directly with DNF:
sudo dnf install -y httpie
On Enterprise Linux distributions such as Rocky Linux, AlmaLinux, and RHEL, HTTPie is available through EPEL for some releases. You may also need the CRB repository, which provides dependencies required by certain EPEL packages.
For Rocky Linux 9 and 10, enable CRB and install EPEL:
sudo dnf install -y epel-release sudo dnf config-manager --set-enabled crb sudo dnf install -y httpie
For Rocky Linux 8, enable PowerTools instead of CRB:
sudo dnf install -y epel-release sudo dnf config-manager --set-enabled powertools sudo dnf install -y httpie
Package availability varies by release. The Fedora package index lists HTTPie in EPEL 8 and EPEL 9, but does not currently list it for EPEL 10. Check the HTTPie package index before assuming the package is available for your specific Enterprise Linux release.
Install HTTPie with pipx
If your distribution does not provide HTTPie, you can install it using pipx. It creates an isolated Python environment for HTTPie and exposes its commands on your PATH, avoiding conflicts with system-managed Python packages.
On Ubuntu or Debian, install pipx with:
sudo apt update sudo apt install -y pipx pipx ensurepath
On Fedora or a compatible DNF-based distribution where the package is available, use:
sudo dnf install -y pipx pipx ensurepath
Then install HTTPie:
pipx install httpie
If pipx ensurepath updates your shell configuration, open a new terminal or follow its instructions to update your current PATH. On Rocky Linux or RHEL, the availability of pipx itself depends on the enabled repositories.
On Arch Linux, HTTPie is available through the official repositories:
sudo pacman -Syu httpie
Verify the installation
Regardless of which installation method you choose, check the version and confirm that both HTTP commands are available:
http --version https --version
Example output:
3.2.4 3.2.4
Your output may differ depending on the package source. The examples in this guide target HTTPie 3.x, and the nested JSON syntax used in Example 3 requires HTTPie 3.0 or later. If you install an older distribution package, check its version before running the examples.
Example 1: Check HTTP Status and Response Headers with HTTPie
One of the most common tasks for a sysadmin is checking what a web server returns. In this example, the lab server is 192.168.122.248 (also reachable as server1.tecmint.lan), with a web server listening on port 80.
Running HTTPie with just a URL sends a GET request by default and displays the response status, headers, and body:
http http://192.168.122.248/
When troubleshooting caching, redirects, or server configuration, you may only need the status and response headers. Use the -h flag (--headers) to display the response headers without the body. Unlike curl -I, which sends a HEAD request, HTTPie still sends a normal GET request:
http -h http://192.168.122.248/
Example output:
HTTP/1.1 200 OK Connection: keep-alive Content-Length: 615 Content-Type: text/html Date: Mon, 26 Oct 2026 06:40:12 GMT ETag: "6714a2b1-267" Last-Modified: Sun, 25 Oct 2026 10:12:33 GMT Server: nginx/1.26.3
The actual headers depend on the server and its configuration. Start with the status line: 200 OK indicates a successful request, while codes such as 301 or 302 indicate redirects.
The remaining headers provide details about the response, including its content type, caching metadata, and server information when exposed.
When you need to inspect both the outgoing request and the incoming response, use -v (--verbose). This is useful for confirming that a custom header was sent correctly:
http -v GET http://192.168.122.248/ User-Agent:tecmint-check/1.0
For more precise output, use --print (or -p) to select which parts of the exchange HTTPie displays:
Hprints request headers.Bprints the request body.hprints response headers.bprints the response body.
For example, to display only the request and response headers, run:
http -p Hh http://192.168.122.248/
This is particularly useful when debugging reverse proxies, checking forwarded headers, or verifying custom authentication headers without displaying the response body.
By default, HTTPie does not follow redirects. This lets you inspect the initial response when checking an HTTP-to-HTTPS redirect or diagnosing a redirect loop. To follow redirects, add --follow (or -F). To display the intermediate responses as well as the final response, use --all:
http --follow --all http://192.168.122.248/
These options give you a quick way to inspect server responses and trace redirect behavior without building long curl commands.
Example 2: Send JSON Data and Query Parameters to a REST API
Checking a page is only part of API testing. You often need to submit data, too. This is where HTTPie saves typing compared with curl, it builds the JSON request body from readable field assignments and automatically sets the Content-Type: application/json header.
For this example, we’ll use httpbin.org, a public test service that echoes request details so you can inspect what the server received. The following command sends two string fields, one number, and one boolean:
http POST https://httpbin.org/post name=web01 role=frontend port:=8080 enabled:=true
In the json section of the response, you should see the submitted data represented like this:
{
"enabled": true,
"name": "web01",
"port": 8080,
"role": "frontend"
}
Notice that port arrives as a number and enabled as a boolean. This demonstrates the difference between = and := discussed earlier. If you use port=8080, HTTPie sends the value as the JSON string "8080" rather than the number 8080.
Query parameters use ==. HTTPie handles URL encoding, so you can pass values containing spaces without manually escaping them:
http GET https://httpbin.org/get search=='disk full' limit==10
The request includes the search and limit query parameters. You can inspect the url field in httpbin’s response to see the resulting URL and how the parameters were encoded.
If an API expects form data instead of JSON, add --form (or -f). HTTPie then sends the same key=value items as URL-encoded form data using application/x-www-form-urlencoded:
http --form POST https://httpbin.org/post user=tecmint comment='Hello World'
In the response, check the form section to see the submitted fields. Unlike JSON, form-encoded values are transmitted as strings, so this format is appropriate when an API expects traditional HTML form submissions.
Example 3: Build Nested JSON and Preview Requests with –offline
The flat JSON in the previous example covers many APIs, but real-world payloads often contain nested objects and arrays. Before HTTPie 3.0, building these structures from individual request items was less convenient and often required passing raw JSON with :=.
HTTPie 3.0 introduced nested JSON syntax, which lets you describe the structure directly using square brackets in field names.
Before sending a complex payload to a real API, it is good practice to preview the request. The --offline flag builds and prints the request without sending it over the network, allowing you to inspect the JSON body first.
For example, the following command creates a nested network object containing an IP address and an array of numeric ports, along with a top-level array of tags:
http --offline --print=B POST https://httpbin.org/post
name=web01
'network[ip]=192.168.122.248'
'network[ports][]:=80'
'network[ports][]:=443'
'tags[]=nginx'
'tags[]=production'
Output:
{
"name": "web01",
"network": {
"ip": "192.168.122.248",
"ports": [
80,
443
]
},
"tags": [
"nginx",
"production"
]
}
The important part is how HTTPie interprets the field names:
network[ip]places the IP address inside a nestednetworkobject.network[ports][]appends each supplied value to theportsarray.tags[]appends values to a top-level array.:=preserves the port values as JSON numbers rather than strings.
Because --offline automatically prints the request headers and body, adding --print=B narrows the output to the body. This keeps the example focused on the generated JSON and avoids distracting differences in headers such as Content-Length or User-Agent across HTTPie versions.
Once the payload looks correct, remove --offline and run the command again to send the request:
http POST https://httpbin.org/post
name=web01
'network[ip]=192.168.122.248'
'network[ports][]:=80'
'network[ports][]:=443'
'tags[]=nginx'
'tags[]=production'
HTTPie 3.0 or later is required for this nested JSON syntax. Check your installed version with http --version if you encounter errors. The official version covers nested objects, arrays, and offline request previews.
Example 4: Authenticate with Basic Auth, Bearer Tokens, and Sessions
So far, every request has been anonymous, but most real-world APIs require authentication. HTTPie supports common authentication schemes directly and can also save credentials, headers, and cookies between requests using sessions.
Basic authentication: For HTTP Basic authentication, pass the username to -a (--auth) and omit the password. HTTPie prompts you to enter it before sending the request, keeping it out of the command itself:
http -a tecmint https://httpbin.org/basic-auth/tecmint/Secret123
When prompted, enter Secret123. A successful request returns a response similar to this:
{
"authenticated": true,
"user": "tecmint"
}
Entering the password at the prompt is safer than writing it directly in the command, where it could be saved in shell history or exposed through process arguments. However, if you use a session, HTTPie can save the prompted password in its session file.
Bearer token authentication: Many modern APIs use bearer tokens instead of usernames and passwords. Specify the bearer authentication scheme with -A bearer and pass the token using -a.
For this example, store a test token in an environment variable rather than typing it directly into the command:
export API_TOKEN='your-token-here' http -A bearer -a "$API_TOKEN" https://httpbin.org/bearer
HTTPie sends an Authorization: Bearer ... header with the request, and the httpbin endpoint echoes the authentication result and token information when the request succeeds.
An environment variable avoids placing the literal token in the command text, but it is not a complete secret-management solution. Depending on your system and permissions, environment variables may be accessible to other processes or users. Unset the variable when you finish testing:
unset API_TOKEN
Reuse authentication with sessions: When you send multiple requests to the same API, entering credentials repeatedly becomes inconvenient. HTTPie sessions let you persist authentication, custom headers, and cookies between requests to the same host.
Create a named session by adding --session=lab to the first request:
http --session=lab -a tecmint https://httpbin.org/basic-auth/tecmint/Secret123
Enter the password when prompted. HTTPie saves the session information locally.
You can then reuse the session without specifying the credentials again:
http --session=lab https://httpbin.org/basic-auth/tecmint/Secret123
HTTPie reuses the saved authentication information and any applicable session headers or cookies. The named session is associated with the host, so it can be reused for other requests to httpbin.org.
On Linux, named session files are typically stored under:
~/.config/httpie/sessions//.json
For this example, the file is:
~/.config/httpie/sessions/httpbin.org/lab.json
For more details, see the official HTTPie authentication and sessions documentation.
Example 5: Upload and Download Files with HTTPie
Authentication covered sending credentials, and the next common job is moving files. The old version of this article used the public transfer.sh service for this, but that service has changed hands and gone through several shutdown announcements over the years, so it’s no longer a dependable example. Instead, we’ll upload to httpbin and download from our own lab server.
To upload a file as a multipart form field, the way a browser upload form does, combine --form with the field@path item from the syntax section:
echo "backup completed on $(hostname)" > report.txt http --form POST httpbin.org/post [email protected]
The files section of the response shows the field name and the file contents that the server received. HTTPie also sets the file’s Content-Type based on its extension.
You can also send a file as the raw request body, which is how many APIs accept JSON or binary uploads. Use input redirection, and HTTPie sends the file contents as-is:
http POST httpbin.org/post Content-Type:application/json < payload.json
For downloads, the --download (-d) flag makes HTTPie behave like wget. It saves the body to a file, shows a progress bar, and takes the file name from the URL or from the server’s Content-Disposition header.
To try it in the lab, start a temporary web server on server1 that serves the current directory on port 8000:
python3 -m http.server 8000
If firewalld is running on a Rocky Linux server, you will also need to open port 8000 temporarily with sudo firewall-cmd –add-port=8000/tcp, which is not permanent and goes away at the next reload or reboot.
Back on your admin machine, download a file from that directory:
http --download http://192.168.122.248:8000/report.txt
Use --output (-o) to choose a different file name, and add --continue (-c) together with --output to resume a large download that was interrupted. When you are finished, press Ctrl+C on server1 to stop the temporary web server.
Example 6: Use HTTPie in Scripts to Check Service Health
The examples so far were interactive, but HTTPie is also useful in shell scripts and cron jobs, for example, to check a health endpoint after a deploy. By default, HTTPie exits with status 0 even when the server returns an error such as 404 or 500, because the HTTP exchange itself worked. That isn’t what a script wants.
The --check-status flag fixes this by making HTTPie exit with a code based on the HTTP status: 3 for an unfollowed 3xx redirect, 4 for a 4xx client error, and 5 for a 5xx server error. Let’s deliberately trigger a failure with httpbin to see it:
http --check-status --quiet httpbin.org/status/503 echo $?
Output:
http: warning: HTTP 503 SERVICE UNAVAILABLE 5
The warning goes to standard error, and the exit code is 5, which a script can test. Connection problems give other codes. For example, a timeout set with –timeout exits with 2, and an error such as a refused connection exits with 1.
There is one more flag that matters in scripts. When standard input isn’t a terminal, which is the case in cron jobs and many CI systems, HTTPie tries to read the request body from it.
When you combine redirected input with request data items such as key=value, HTTPie reports an error because raw request bodies and structured request data cannot be used together. The error message may read:
http: error: Request body (from stdin, --raw or a file) and request data (key=value) cannot be mixed
Without request items, HTTPie may wait for standard input if it is not connected to a terminal and no end-of-file signal is received. Add --ignore-stdin when you want to prevent HTTPie from reading standard input:
http --ignore-stdin GET https://httpbin.org/get
Putting these together, here is a small health check script. Create it with nano on Ubuntu and Debian:
nano ~/check-web.sh
On Rocky Linux, AlmaLinux, and RHEL, minimal installs include vi rather than nano, so use vi there:
vi ~/check-web.sh
Then add the following content to the file:
#!/usr/bin/env bash
# ~/check-web.sh
# Check a web endpoint and report its HTTP status using HTTPie.
URL="${1:-http://192.168.122.248/}"
if http --check-status --ignore-stdin --quiet --timeout=5 GET "$URL"; then
echo "OK: $URL is responding"
else
code=$?
echo "FAIL: $URL check failed with HTTPie exit code $code" >&2
exit "$code"
fi
Save the file and exit the editor. The flags in the http line work together like this:
--check-statusturns 3xx, 4xx, and 5xx responses into non-zero exit codes, so the if statement can detect them.--ignore-stdinstops HTTPie from waiting for a request body on standard input, which keeps the script working under cron.--quietsuppresses the normal output, so the script only prints its own OK or FAIL line.--timeout=5gives up after 5 seconds without a response, instead of hanging on an unreachable server.
Make the script executable and run it against the lab server, and then against a URL that returns an error:
chmod +x ~/check-web.sh ~/check-web.sh ~/check-web.sh httpbin.org/status/404
Output:
OK: http://192.168.122.248/ is responding http: warning: HTTP 404 NOT FOUND FAIL: httpbin.org/status/404 check failed with HTTPie exit code 4
Change the default URL value to your own server’s health endpoint. Since the lab server gets its address from DHCP, reserve or set a static address for it first, so the hardcoded IP keeps pointing at the right machine.
--check-status just fixed a health check that always reported success, share it with someone whose monitoring script trusts every response.Pro Tips for Using HTTPie Safely and Efficiently
With HTTPie running interactively and in scripts, a few settings make day-to-day use smoother and safer, especially when you test internal services.
If you find yourself adding the same flags to every command, such as a particular colour style or always following redirects, you can set them as defaults in HTTPie’s configuration file. Open it with nano on Ubuntu and Debian:
mkdir -p ~/.config/httpie nano ~/.config/httpie/config.json
On Rocky Linux, AlmaLinux, and RHEL, use vi:
mkdir -p ~/.config/httpie vi ~/.config/httpie/config.json
Add the following configuration. JSON doesn’t allow comments, so the file path is given here instead of on the first line: ~/.config/httpie/config.json.
{
"default_options": [
"--style=monokai",
"--follow",
"--timeout=10"
]
}
Save the file and exit the editor. The options are applied to every http and https command:
--style=monokaisets the colour scheme for terminal output. Run http--helpand look at the--styleoption to see the styles available in your version.--followfollows redirects automatically, which suits API testing but hides redirects you might want to see when checking server rules.--timeout=10stops requests from hanging forever on an unreachable host.
Adjust the list to your own habits. For a single command, you can still override a default, for example by adding --style=auto.
On the security side, avoid writing passwords and tokens directly on the command line, since they end up in your shell history and are visible to other users through ps while the command runs. Use the password prompt from -a username, an environment variable, or a session file with restricted permissions instead.
Internal servers often use self-signed certificates, and HTTPie will refuse them with an SSL certificate verification error. Rather than turning off checking with --verify=no, point HTTPie at your internal CA with --verify=/path/to/ca.crt, which keeps protection against a man-in-the-middle while still trusting your own certificates.
Make sure you are running HTTPie 3.2.4 or later, because version 3.2.2 had a known issue with SSL certificate validation, and 3.2.4 fixed how the default certificates are loaded.
Finally, remember that HTTPie formats JSON output only when printing to a terminal. When you redirect output to a file or pipe it to another command, HTTPie sends the raw body, which is usually what you want for tools like jq. Add --pretty=all if you want the formatted version saved instead.
Conclusion
HTTPie turns everyday HTTP work into short, readable commands, with automatic JSON bodies, readable output, built-in auth, sessions, and downloads. With --check-status and --ignore-stdin, the same tool also works reliably in scripts and cron jobs for health checks after deploys.
If you want to get faster with the commands that sit around tools like HTTPie, such as curl, ss, grep, and journalctl, our 100+ Essential Linux Commands course walks through them with practical examples.
And if the health check script made you want to write more of your own automation, Bash Scripting for Beginners covers exit codes, conditions, and error handling step by step.
We’d love to hear how you’re using HTTPie in your own setup. Do you still reach for curl for some jobs, and if so, which ones? Have you used HTTPie sessions or plugins with an internal API? Feel free to share your favourite one-liners or any error you hit in the comments below.




