Skip to content
/ xh Public

Friendly and fast tool for sending HTTP requests


Notifications You must be signed in to change notification settings


Repository files navigation


Version info Packaging status

xh is a friendly and fast tool for sending HTTP requests. It reimplements as much as possible of HTTPie's excellent design, with a focus on improved performance.



via cURL (Linux & macOS)

curl -sfL | sh

via Powershell (Windows)

iwr -useb | iex

via a package manager

OS Method Command
Any Cargo* cargo install xh --locked
Any Huber huber install xh
Android (Termux) pkg pkg install xh
Android (Magisk/KernelSU) MMRL** mmrl install xhhttp
Alpine Linux apk*** apk add xh
Arch Linux Pacman pacman -S xh
Debian & Ubuntu Apt**** sudo apt install xh
FreeBSD FreshPorts pkg install xh
NetBSD pkgsrc pkgin install xh
Linux & macOS Nixpkgs nix-env -iA nixpkgs.xh
Linux & macOS Flox flox install xh
Linux & macOS Homebrew brew install xh
macOS MacPorts sudo port install xh
Windows Scoop scoop install xh
Windows Chocolatey choco install xh
Windows Winget winget add ducaale.xh

* Make sure that you have Rust 1.74 or later installed

** You will need to install the MMRL CLI

*** The xh package is available in Edge and will be in v3.17+. It is built with native-tls only.

**** You will need to add the apt repository from

via pre-built binaries

The release page contains prebuilt binaries for Linux, macOS and Windows.



  <[METHOD] URL>     The request URL, preceded by an optional HTTP method
  [REQUEST_ITEM]...  Optional key-value pairs to be included in the request.

  -j, --json                             (default) Serialize data items from the command line as a JSON object
  -f, --form                             Serialize data items from the command line as form fields
      --multipart                        Like --form, but force a multipart/form-data request even without files
      --raw <RAW>                        Pass raw request data without extra processing
      --pretty <STYLE>                   Controls output processing [possible values: all, colors, format, none]
      --format-options <FORMAT_OPTIONS>  Set output formatting options
  -s, --style <THEME>                    Output coloring style [possible values: auto, solarized, monokai, fruity]
      --response-charset <ENCODING>      Override the response encoding for terminal display purposes
      --response-mime <MIME_TYPE>        Override the response mime type for coloring and formatting for the terminal
  -p, --print <FORMAT>                   String specifying what the output should contain
  -h, --headers                          Print only the response headers. Shortcut for --print=h
  -b, --body                             Print only the response body. Shortcut for --print=b
  -m, --meta                             Print only the response metadata. Shortcut for --print=m
  -v, --verbose...                       Print the whole request as well as the response
      --all                              Show any intermediary requests/responses while following redirects with --follow
  -P, --history-print <FORMAT>           The same as --print but applies only to intermediary requests/responses
  -q, --quiet                            Do not print to stdout or stderr
  -S, --stream                           Always stream the response body
  -o, --output <FILE>                    Save output to FILE instead of stdout
  -d, --download                         Download the body to a file instead of printing it
  -c, --continue                         Resume an interrupted download. Requires --download and --output
      --session <FILE>                   Create, or reuse and update a session
      --session-read-only <FILE>         Create or read a session without updating it form the request/response exchange
  -A, --auth-type <AUTH_TYPE>            Specify the auth mechanism [possible values: basic, bearer, digest]
  -a, --auth <USER[:PASS] | TOKEN>       Authenticate as USER with PASS (-A basic|digest) or with TOKEN (-A bearer)
      --ignore-netrc                     Do not use credentials from .netrc
      --offline                          Construct HTTP requests without sending them anywhere
      --check-status                     (default) Exit with an error status code if the server replies with an error
  -F, --follow                           Do follow redirects
      --max-redirects <NUM>              Number of redirects to follow. Only respected if --follow is used
      --timeout <SEC>                    Connection timeout of the request
      --proxy <PROTOCOL:URL>             Use a proxy for a protocol. For example: --proxy https:
      --verify <VERIFY>                  If "no", skip SSL verification. If a file path, use it as a CA bundle
      --cert <FILE>                      Use a client side certificate for SSL
      --cert-key <FILE>                  A private key file to use with --cert
      --ssl <VERSION>                    Force a particular TLS version [possible values: auto, tls1, tls1.1, tls1.2, tls1.3]
      --https                            Make HTTPS requests if not specified in the URL
      --http-version <VERSION>           HTTP version to use [possible values: 1.0, 1.1, 2, 2-prior-knowledge]
      --resolve <HOST:ADDRESS>           Override DNS resolution for specific domain to a custom IP
      --interface <NAME>                 Bind to a network interface or local IP address
  -4, --ipv4                             Resolve hostname to ipv4 addresses only
  -6, --ipv6                             Resolve hostname to ipv6 addresses only
  -I, --ignore-stdin                     Do not attempt to read stdin
      --curl                             Print a translation to a curl command
      --curl-long                        Use the long versions of curl's flags
      --help                             Print help
  -V, --version                          Print version

Each option can be reset with a --no-OPTION argument.

Run xh help for more detailed information.

Request Items

xh uses HTTPie's request-item syntax to set headers, request body, query string, etc.

  • =/:= for setting the request body's JSON or form fields (= for strings and := for other JSON types).
  • == for adding query strings.
  • @ for including files in multipart requests e.g picture@hello.jpg or picture@hello.jpg;type=image/jpeg;filename=goodbye.jpg.
  • : for adding or removing headers e.g connection:keep-alive or connection:.
  • ; for including headers with empty values e.g header-without-value;.

An @ prefix can be used to read a value from a file. For example: x-api-key:@api-key.txt.

The request body can also be read from standard input, or from a file using @filename.

To construct a complex JSON object, a JSON path can be used as a key e.g app[container][0][id]=090-5. For more information on this syntax, refer to

Shorthand form for URLs

Similar to HTTPie, specifying the scheme portion of the request URL is optional, and a leading colon works as shorthand for localhost. :8000 is equivalent to localhost:8000, and :/path is equivalent to localhost/path.

URLs can have a leading :// which allows quickly converting a URL into a valid xh or HTTPie command. For example becomes http ://

xh http://localhost:3000/users # resolves to http://localhost:3000/users
xh localhost:3000/users        # resolves to http://localhost:3000/users
xh :3000/users                 # resolves to http://localhost:3000/users
xh :/users                     # resolves to http://localhost:80/users
xh                 # resolves to
xh ://              # resolves to

Making HTTPS requests by default

xh will default to HTTPS scheme if the binary name is one of xhs, https, or xhttps. If you have installed xh via a package manager, both xh and xhs should be available by default. Otherwise, you need to create one like this:

cd /path/to/xh && ln -s ./xh ./xhs
xh  # resolves to
xhs # resolves to

Strict compatibility mode

If xh is invoked as http or https (by renaming the binary), or if the XH_HTTPIE_COMPAT_MODE environment variable is set, it will run in HTTPie compatibility mode. The only current difference is that --check-status is not enabled by default.


# Send a GET request

# Send a POST request with body {"name": "ahmed", "age": 24}
xh name=ahmed age:=24

# Send a GET request with querystring id=5&sort=true
xh get id==5 sort==true

# Send a GET request and include a header named x-api-key with value 12345
xh get x-api-key:12345

# Send a POST request with body read from stdin.
echo "[1, 2, 3]" | xh post

# Send a PUT request and pipe the result to less
xh put id:=49 age:=25 | less

# Download and save to res.json
xh -d -o res.json

# Make a request with a custom user agent
xh user-agent:foobar

How xh compares to HTTPie


  • Improved startup speed.
  • Available as a single statically linked binary that's easy to install and carry around.
  • HTTP/2 support.
  • Builtin translation to curl commands with the --curl flag.
  • Short, cheatsheet-style output from --help. (For longer output, pass help.)


  • Not all of HTTPie's features are implemented. (#4)
  • No plugin system.
  • General immaturity. HTTPie is old and well-tested.
  • Worse documentation.

Similar or related Projects

  • curlie - frontend to cURL that adds the ease of use of httpie
  • httpie-go - httpie-like HTTP client written in Go
  • curl2httpie - convert command arguments between cURL and HTTPie