XH(1)

✨ NAME ✨

Okay bestie, meet xh(1) πŸ‘‹ β€” the manual page for xh, aka the Friendly and fast tool for sending HTTP requests. πŸ’–

πŸ¦‹ SYNOPSIS πŸ¦‹

xh [OPTIONS] [METHOD] URL [--] [REQUEST_ITEM ...]

πŸ’… DESCRIPTION πŸ’…

xh is an HTTP client with a friendly command line interface. It literally strives to have readable output and easy-to-use options. πŸŽ€

It's mostly compatible with HTTPie β€” see http(1). iykyk. ✨

The --curl option can be used to print a curl(1) translation of the command instead of sending a request. Obsessed with that trick. πŸ”₯


πŸŽ€ POSITIONAL ARGUMENTS πŸŽ€

🌸 [METHOD]

The HTTP method to use for the request. πŸ’…

This defaults to GET, or to POST if the request contains a body. Periodt.

πŸ¦‹ URL

The URL to request. ✨

The URL scheme defaults to http:// normally, or https:// if the program is invoked as xhs.

A leading colon works as shorthand for localhost. :8000 is equivalent to localhost:8000, and :/path is equivalent to localhost/path. Cute, right? πŸ’–

🧚 [REQUEST_ITEM ...]

Optional key-value pairs to be included in the request. 🫢

The separator is used to determine the type:

  • key==value β€” adds a query string to the URL. 🌈
  • key=value β€” adds a JSON property (--json) or form field (--form) to the request body. πŸ’…
  • key:=value β€” adds a field with a literal JSON value to the request body. Example: "numbers:=[1,2,3] enabled:=true" πŸ”₯
  • key@filename β€” uploads a file (requires --form or --multipart). To set the filename and mimetype, ;type= and ;filename= can be used respectively. Example: "pfp@ra.jpg;type=image/jpeg;filename=profile.jpg" πŸ“Ž
  • @filename β€” uses a file as the request body. πŸ“
  • header:value β€” adds a header, e.g. "user-agent:foobar". πŸ‘‘
  • header: β€” unsets a header, e.g. "connection:". πŸ™ˆ
  • header; β€” adds a header with an empty value. ⭐

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

A backslash can be used to escape special characters, e.g. "weird\:key=value". πŸ¦‹

To construct a complex JSON object, the REQUEST_ITEM's key can be set to a JSON path instead of a field name. For more information on this syntax, refer to https://httpie.io/docs/cli/nested-json. 🌸

✨ OPTIONS ✨

okay so bestie, this is the big options buffet, and it’s lowkey iconic. Every single --OPTION can be reset with a --no-OPTION argument. Slay.

  • -j, --json β€” (default) Serialize data items from the command line as a JSON object. Overrides both --form and --multipart.
  • -f, --form β€” Serialize data items from the command line as form fields. Overrides both --json and --multipart.
  • --multipart β€” Like --form, but force a multipart/form-data request even without files. Overrides both --json and --form.
  • --raw=RAW β€” Pass raw request data without extra processing.
  • --pretty=STYLE β€” Controls output processing. Possible values are:
    • all β€” (default) Enable both coloring and formatting
    • colors β€” Apply syntax highlighting to output
    • format β€” Pretty-print json and sort headers
    • none β€” Disable both coloring and formatting

Defaults to "format" if the NO_COLOR env is set and to "none" if stdout is not tty.

  • --format-options=FORMAT_OPTIONS β€” Set output formatting options. Supported option are:
    • json.indent:<NUM>
    • json.format:<true|false>
    • xml.indent:<NUM>
    • xml.format:<true|false>
    • headers.sort:<true|false>

Example: --format-options=json.indent:2,headers.sort:false.

  • -s, --style=THEME β€” Output coloring style. Possible values: auto, solarized, monokai, fruity.
  • --response-charset=ENCODING β€” Override the response encoding for terminal display purposes. Example: --response-charset=latin1.
  • --response-mime=MIME_TYPE β€” Override the response mime type for coloring and formatting for the terminal. Example: --response-mime=application/json.
  • -p, --print=FORMAT β€” String specifying what the output should contain:
    • H β€” request headers
    • B β€” request body
    • h β€” response headers
    • b β€” response body
    • m β€” response metadata

Example: --print=Hb.

  • -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. Additionally, this enables --all for printing intermediary requests/responses while following redirects. Using verbose twice i.e. -vv will print the response metadata as well. Equivalent to --print=HhBb --all.
  • --debug β€” Print full error stack traces and debug log messages. Logging can be configured in more detail using the $RUST_LOG environment variable. Set RUST_LOG=trace to show even more messages. See https://docs.rs/env_logger/0.11.3/env_logger/#enabling-logging.
  • --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. Using quiet twice i.e. -qq will suppress warnings as well.
  • -S, --stream β€” Always stream the response body.
  • -x, --compress β€” Content compressed (encoded) with Deflate algorithm. The Content-Encoding header is set to deflate. Compression is skipped if it appears that compression ratio is negative. Compression can be forced by repeating this option.
⚠️ Note: Compression cannot be used if the Content-Encoding request header is present.
  • -o, --output=FILE β€” Save output to FILE instead of stdout.
  • -d, --download β€” Download the body to a file instead of printing it. The Accept-Encoding header is set to identity and any redirects will be followed.
  • -c, --continue β€” Resume an interrupted download. Requires --download and --output.
  • --session=FILE β€” Create, or reuse and update a session. Within a session, custom headers, auth credentials, as well as any cookies sent by the server persist between requests.
  • --session-read-only=FILE β€” Create or read a session without updating it from 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). PASS will be prompted if missing. Use a trailing colon (i.e. "USER:") to authenticate with just a username. TOKEN is expected if --auth-type=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. The exit code will be 4 on 4xx (Client Error), 5 on 5xx (Server Error), or 3 on 3xx (Redirect) if --follow isn't set. If stdout is redirected then a warning is written to stderr.
  • -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. The default value is "0", i.e., there is no timeout limit.
  • --proxy=PROTOCOL:URL β€” Use a proxy for a protocol. For example: --proxy https:http://proxy.host:8080. PROTOCOL can be "all", "http" or "https". If your proxy requires credentials, put them in the URL, like so: --proxy http:socks5://user:password@proxy.host:8000. You can specify proxies for multiple protocols by repeating this option. The environment variables "ALL_PROXY", "HTTP_PROXY" and "HTTPS_PROXY" can also be used, but are completely ignored if --proxy is passed.
  • --verify=VERIFY β€” If "no", skip SSL verification. If a file path, use it as a CA bundle. Specifying a CA bundle will disable the system's built-in root certificates. "false" instead of "no" also works. The default is "yes" ("true").
  • --cert=FILE β€” Use a client side certificate for SSL.
  • --cert-key=FILE β€” A private key file to use with --cert. Only necessary if the private key is not contained in the cert file.
  • --ssl=VERSION β€” Force a particular TLS version. "auto" gives the default behavior of negotiating a version with the server. Possible values: auto, tls1, tls1.1, tls1.2, tls1.3.
  • --native-tls β€” Use the system TLS library instead of rustls (if enabled at compile time).
  • --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, 3-prior-knowledge.
  • --resolve=HOST:ADDRESS β€” Override DNS resolution for specific domain to a custom IP. You can override multiple domains by repeating this option. Example: --resolve=example.com:127.0.0.1.
  • --interface=NAME β€” Bind to a network interface or local IP address. Example: --interface=eth0 --interface=192.168.0.2.
  • -4, --ipv4 β€” Resolve hostname to ipv4 addresses only.
  • -6, --ipv6 β€” Resolve hostname to ipv6 addresses only.
  • --unix-socket=FILE β€” Connect using a Unix domain socket. Example: xh :/index.html --unix-socket=/var/run/temp.sock.
  • -I, --ignore-stdin β€” Do not attempt to read stdin. This disables the default behaviour of reading the request body from stdin when a redirected input is detected. It is recommended to pass this flag when using xh for scripting purposes. For more information, refer to https://httpie.io/docs/cli/best-practices.
  • --curl β€” Print a translation to a curl command. For translating the other way, try https://curl2httpie.online/.
  • --curl-long β€” Use the long versions of curl's flags.
  • --generate=KIND β€” Generate shell completions or man pages. Possible values are:
    • complete-bash β€” Generate completions for bash
    • complete-elvish β€” Generate completions for elvish
    • complete-fish β€” Generage completions for fish
    • complete-nushell β€” Generate completions for nushell
    • complete-powershell β€” Generate completions for powershell
    • complete-zsh β€” Generate completions for zsh
    • man β€” Generate manual page in roff format
    • man-markdown β€” Generate manual page in markdown format

Example: xh --generate=complete-bash > xh.bash.

  • --help β€” Print help.
  • -V, --version β€” Print version.

🚦 EXIT STATUS 🚦

  • 0 β€” Successful program execution.
  • 1 β€” Usage, syntax or network error.
  • 2 β€” Request timeout.
  • 3 β€” Unexpected HTTP 3xx Redirection.
  • 4 β€” HTTP 4xx Client Error.
  • 5 β€” HTTP 5xx Server Error.
  • 6 β€” Too many redirects.

🌱 ENVIRONMENT 🌱

  • XH_CONFIG_DIR β€” Specifies where to look for config.json and named session data. The default is ~/.config/xh for Linux/macOS and %APPDATA%\xh for Windows.
  • XH_HTTPIE_COMPAT_MODE β€” Enables the HTTPie Compatibility Mode. The only current difference is that --check-status is not enabled by default. An alternative to setting this environment variable is to rename the binary to either http or https.
  • REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE β€” Sets a custom CA bundle path.
  • ALL_PROXY=[protocol://]<host>[:port] β€” Sets the proxy server for all requests (unless overridden for a specific protocol).
  • HTTP_PROXY=[protocol://]<host>[:port] β€” Sets the proxy server to use for HTTP.
  • HTTPS_PROXY=[protocol://]<host>[:port] β€” Sets the proxy server to use for HTTPS.
  • NO_PROXY β€” List of comma-separated hosts for which to ignore the other proxy environment variables. "*" matches all host names.
  • NETRC β€” Location of the .netrc file.
  • NO_COLOR β€” Disables output coloring. See https://no-color.org.
  • RUST_LOG β€” Configure low-level debug messages. See https://docs.rs/env_logger/0.11.3/env_logger/#enabling-logging.

πŸ“ FILES πŸ“

  • ~/.config/xh/config.json β€” xh configuration file. The only configurable option is "default_options" which is a list of default shell arguments that gets passed to xh. Example:
{ "default_options": ["--native-tls", "--style=solarized"] }
  • ~/.netrc, ~/_netrc β€” Auto-login information file.
  • ~/.config/xh/sessions β€” Session data directory grouped by domain and port number.

✨ EXAMPLES ✨

okay bestie, this is the part where it gets good πŸ’… here's a whole lil' tour of stuff you can do, copied exactly so you can just vibe-check each one and steal whatever you need 🫢


xh httpbin.org/json

the classic. the icon. the main character. this just sends a GET request, periodt πŸ’–

xh httpbin.org/json

xh httpbin.org/post name=ahmed age:=24

sends a POST request, and the body it ships off is literally {"name": "ahmed", "age": 24} ✨ (notice the := for the raw JSON value, that's the trick, iykyk)

xh httpbin.org/post name=ahmed age:=24

xh get httpbin.org/json id==5 sort==true

sends a GET request to http://httpbin.org/json?id=5&sort=true 🌸 (the double-equals == is the query-string girlie, she goes straight into the URL)

xh get httpbin.org/json id==5 sort==true

xh get httpbin.org/json x-api-key:12345

sends a GET request and includes a header named X-Api-Key with the value 12345 πŸŽ€ (single colon : = header, no cap)

xh get httpbin.org/json x-api-key:12345

echo "[1, 2, 3]" | xh post httpbin.org/post

sends a POST request where the body is read from stdin πŸ¦‹ very "not me piping things into other things" of you, and we love that

echo "[1, 2, 3]" | xh post httpbin.org/post

xh put httpbin.org/put id:=49 age:=25 | less

sends a PUT request and then pipes the result straight into less 😭 so you can scroll it like the distinguished gentleperson you are

xh put httpbin.org/put id:=49 age:=25 | less

xh -d httpbin.org/json -o res.json

downloads and saves to res.json πŸ”₯ that -d/-o combo is giving "saving my work before the wifi dies" energy

xh -d httpbin.org/json -o res.json

xh httpbin.org/get user-agent:foobar

makes a request with a custom user agent πŸ‘‘

xh httpbin.org/get user-agent:foobar

xhs example.com

makes an HTTPS request to https://example.com ⭐ (yup β€” xhs, the HTTPS-only twin, tiny name change, big security energy)

xhs example.com

πŸ› REPORTING BUGS πŸ›

found a lil' gremlin in the code? πŸ’€ take it straight to xh's Github issues at <https://github.com/ducaale/xh/issues> β€” the maintainers fr fr want to hear about it, and honestly? be as specific as you can, bestie, it helps a ton 🫢


πŸ‘€ SEE ALSO πŸ‘€

go touch some other grass, these are the neighbours:

and if you want the full lore dump, HTTPie's online documentation lives at <https://httpie.io/docs/cli> 🌈


aaand that's the whole page, bestie πŸŽ€ you made it to the end, iconic behavior honestly πŸ‘‘

this lil' rewrite is based on xh version 0.26.3, dated 2026-10-21 β€” go forth and make some requests, slay πŸ’…βœ¨πŸ’–

πŸ“¦ where this page comes from