XH(1)

πŸ’– XH(1) β€” User Commands πŸ’–

okay bestie, welcome to the xh manual page, section 1 of the User Commands vibe. grab a boba, we're sending HTTP requests and we're gonna look cute doing it 🫢


✨ NAME ✨

xh β€” friendly and fast tool for sending HTTP requests

like literally it's an HTTP client that is friendly AND fast, both at once, slay.


🌸 SYNOPSIS 🌸

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

that's the whole shape of it. options first, then maybe a method, then the URL, and if you need to put the vibes after the URL, there's a -- to gatekeep the boundary. ✨


πŸ¦‹ DESCRIPTION πŸ¦‹

xh is an HTTP client with a friendly command line interface. it is striving β€” like genuinely putting in the work β€” to have readable output and easy-to-use options. no cap, that's the whole mission statement.

xh is mostly compatible with HTTPie β€” see http(1). so if you already know HTTPie you're basically already home 🏠

and here's the iconic part: the --curl option can be used to print a curl(1) translation of the command instead of sending a request. so it just… hands you the curl version. it's giving translator. it's giving "let me say that in curl for you." obsessed.


πŸŽ€ POSITIONAL ARGUMENTS πŸŽ€

[METHOD]

the HTTP method you want to use for the request. that's it, that's the job.

it defaults to GET, or to POST if the request contains a body. so like, no body, no method given? GET. body present? surprise, it's POST. iykyk.

URL

the URL to request. yes you do have to give it one, that's kind of the whole point bestie.

the URL scheme defaults to "http://" normally, or "https://" if the program is invoked as "xhs". so the name you call it by changes its whole personality. main character energy fr fr.

a leading colon works as shorthand for localhost. so:

  • ":8000" is equivalent to "localhost:8000"
  • ":/path" is equivalent to "localhost/path"

the colon is the short king of hostnames πŸ’…

[REQUEST_ITEM ...]

optional key-value pairs to be included in the request. this is where it gets fun.

the separator is used to determine the type. so like, the punctuation IS the instruction. let's go through them:

  • key==value β€” Add a query string to the URL.
  • key=value β€” Add a JSON property (--json) or form field (--form) to the request body.
  • key:=value β€” Add a field with a literal JSON value to the request body.

example: "numbers:=[1,2,3] enabled:=true" πŸ”₯

  • key@filename β€” Upload 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" β€” yes bestie, upload your pfp, set the type, set the name, all in one item. iconic.

  • @filename β€” Use a file as the request body.
  • header:value β€” Add a header, e.g. "user-agent:foobar"
  • header: β€” Unset a header, e.g. "connection:"
  • header; β€” Add a header with an empty value.
πŸ‘€ careful, bestie: header:value adds a header, header: unsets one, and header; adds one that's empty. three different punctuation marks, three completely different outcomes. do not mix them up.

an "@" prefix can be used to read a value from a file. for example: "x-api-key:@api-key.txt". so the secret stays in the file and your shell history stays clean, we love a privacy moment πŸ™ˆ

a backslash can be used to escape special characters, e.g. "weird\:key=value". because sometimes you really do mean a literal colon and the colon needs to chill.

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. 🌈


that's part 1 bestie, don't go anywhere β€” there's more πŸ’–

✨ OPTIONS ✨

okay so quick thing before we dive in: every single --OPTION in this list can be undone with a --no-OPTION argument. yes literally, --no-follow, --no-json, whatever β€” it's the uno reverse card of flags. πŸƒ


  • -j, --json β€” (this is the default btw) 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 when there are no files involved. stubborn king behavior πŸ‘‘

Overrides both --json and --form.

  • --raw=RAW β€” Pass raw request data without extra processing. no thoughts, just vibes, just bytes.
  • --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. (she knows when you're piping her somewhere, bestie, and she acts accordingly πŸŽ€)

  • --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. screaming into the void but productively πŸ”₯

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. (resume queen πŸ’…)
  • --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. look but don't touch energy πŸ™ˆ
  • -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. manifesting the request but not manifesting the response ✨
  • --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. living on the edge fr fr πŸ’€

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]

  • --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. gaslighting DNS, iconic tbh 🌈

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. slay πŸ’–
  • 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> β€” your no-color era 🌚
  • 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 all clicks, fr fr. here's the whole vibe in action πŸ‘‡

  • xh httpbin.org/json β€” sends a GET request. that's it. that's the whole thing. iconic.
  • xh httpbin.org/post name=ahmed age:=24 β€” sends a POST request with the body {"name": "ahmed", "age": 24}. notice the := on age?? that's the raw JSON one, so 24 stays a number and doesn't get quoted like a lil string 🧚
  • xh get httpbin.org/json id==5 sort==true β€” sends a GET request to http://httpbin.org/json?id=5&sort=true. the == is your query-string bestie, and yes it'll assemble that whole URL for you πŸ’…
  • xh get httpbin.org/json x-api-key:12345 β€” sends a GET request and slips in a header named X-Api-Key with the value 12345. one colon = header, periodt.
  • echo "[1, 2, 3]" | xh post httpbin.org/post β€” sends a POST request where the body gets read straight from stdin 🫢 pipe it in, she'll take it.
  • xh put httpbin.org/put id:=49 age:=25 | less β€” sends a PUT request and pipes the result right into less. chef's kiss for long responses ✨
  • xh -d httpbin.org/json -o res.json β€” downloads and saves it to res.json. -d is download mode, -o is where it lands πŸ’Ύ
  • xh httpbin.org/get user-agent:foobar β€” makes a request with a custom user agent. you're the main character now, not the default one πŸ‘‘
  • xhs example.com β€” makes an HTTPS request to https://example.com. lowercase s, huge glow-up 🌈

😭 REPORTING BUGS 😭

found something cursed?? not me gatekeeping, go tell the devs directly:

no cap, that's the spot πŸ›


πŸ’œ SEE ALSO πŸ’œ

like,,,,, the extended universe besties:

iykyk 🌸


and that's a wrap on XH(1), bestie!! this page is from version 0.26.2, dated 2026-07-27, and you read the whole thing which is honestly main character energy πŸ‘‘πŸ’– go forth and make requests, drink water, and remember: == is query, : is header, := is raw JSON. bye pookie πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from