# HTTPie User Guide

HTTPie (pronounced *aitch-tee-tee-pie*) is a command-line HTTP client built to make interacting with web services and APIs as human-friendly as possible. You type requests in a simple, natural syntax that closely mirrors the actual HTTP message sent over the wire, and HTTPie gives you back formatted, colorized output. It is designed for testing, debugging, and generally talking to HTTP servers and JSON APIs from your terminal.

This guide covers everything you can do with the `http` and `https` commands: installation, the request-item syntax that lets you build any request, sessions, authentication, downloads, output control, and the `httpie` management interface. Every command, flag, and behavior described here is taken directly from HTTPie's source code (version `3.2.4`).

> [!NOTE]
> HTTPie installs **two** request commands: `http` (default scheme `http://`) and `https` (default scheme `https://`). They are identical apart from the default scheme. A third command, `httpie`, is a management interface for plugins and configuration — it does **not** send requests. See [The httpie management command](#the-httpie-management-command).

---

## Table of contents

- [Quick start](#quick-start)
- [Installation](#installation)
- [The request syntax](#the-request-syntax)
- [Request items: building any request](#request-items-building-any-request)
- [Sending JSON](#sending-json)
- [Nested JSON](#nested-json)
- [Sending forms and uploading files](#sending-forms-and-uploading-files)
- [HTTP headers](#http-headers)
- [Query string parameters](#query-string-parameters)
- [Raw request body](#raw-request-body)
- [Authentication](#authentication)
- [Cookies and sessions](#cookies-and-sessions)
- [Controlling the output](#controlling-the-output)
- [Downloading files](#downloading-files)
- [Redirects, proxies, and networking](#redirects-proxies-and-networking)
- [HTTPS, SSL, and certificates](#https-ssl-and-certificates)
- [Offline mode and scripting](#offline-mode-and-scripting)
- [Configuration](#configuration)
- [The httpie management command](#the-httpie-management-command)
- [How HTTPie works under the hood](#how-httpie-works-under-the-hood)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
- [Complete option reference](#complete-option-reference)

---

## Quick start

After [installing](#installation) HTTPie, make your first request:

```bash
https httpie.io/hello
```

That sends a `GET` request to `https://httpie.io/hello` and prints the colorized response headers and body.

The general shape of every command is:

```bash
http [flags] [METHOD] URL [ITEM [ITEM]]
```

Only the URL is required. Here is a request that sends a JSON body with a custom header, using a `PUT` method:

```bash
http PUT pie.dev/put X-API-Token:123 name=John
```

```http
PUT /put HTTP/1.1
Accept: application/json, */*;q=0.5
Content-Type: application/json
Host: pie.dev
X-API-Token: 123

{
    "name": "John"
}
```

Three things just happened automatically:

- The method was sent as `PUT` because you named it.
- `name=John` became a JSON field, so HTTPie set `Content-Type: application/json`.
- `X-API-Token:123` became a request header.

That is the core idea: the **separator** between a key and a value (`:`, `=`, `==`, `:=`, `@`, …) decides what kind of request part it becomes. The rest of this guide is mostly about those separators and the flags that shape the request and the output.

> [!TIP]
> Add `-v` (`--verbose`) to any command to see the full request **and** response — the single most useful flag for learning and debugging:
> ```bash
> http -v pie.dev/get
> ```

---

## Installation

HTTPie is a Python application and is packaged for every major platform. Pick the method that matches your operating system. All commands below are taken from HTTPie's official packaging database.

### Universal (any OS with Python)

Requires **Python 3.7 or newer** (check with `python --version`).

=== "Install"

    ```bash
    python -m pip install --upgrade pip wheel
    python -m pip install httpie
    ```

=== "Upgrade"

    ```bash
    python -m pip install --upgrade pip wheel
    python -m pip install --upgrade httpie
    ```

### macOS

=== "Homebrew"

    ```bash
    brew update
    brew install httpie
    ```

=== "MacPorts"

    ```bash
    port selfupdate
    port install httpie
    ```

### Windows

=== "Chocolatey"

    ```bash
    choco install httpie
    ```

### Linux

=== "Debian / Ubuntu"

    ```bash
    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 httpie
    ```

    Also works for Debian-derived distributions (Linux Mint, Pop!_OS, elementary OS, Kubuntu, etc.).

=== "Fedora"

    ```bash
    dnf install httpie
    ```

=== "CentOS / RHEL"

    ```bash
    yum install epel-release
    yum install httpie
    ```

=== "Arch Linux"

    ```bash
    pacman -Syu httpie
    ```

=== "Snap"

    ```bash
    snap install httpie
    ```

=== "Single binary"

    Standalone executables — no Python installation needed:

    ```bash
    https --download packages.httpie.io/binaries/linux/http-latest -o http
    ln -ls ./http ./https
    chmod +x ./http ./https
    ```

### FreeBSD

```bash
pkg install www/py-httpie
```

### Installing the development version

To try the latest unreleased code from the `master` branch:

```bash
python -m pip install --upgrade https://github.com/httpie/cli/archive/master.tar.gz
```

Verify any installation with:

```bash
http --version
```

```text
3.2.4
```

> [!NOTE]
> Development builds report a version with a `.dev0` suffix (e.g. `3.3.0.dev0`).

---

## The request syntax

Every HTTPie invocation follows the same grammar:

```bash
http [flags] [METHOD] URL [ITEM [ITEM ...]]
```

| Part | Required? | Description |
|------|-----------|-------------|
| `flags` | No | Options like `-v`, `--form`, `--download`. They come before or after the URL. |
| `METHOD` | No | `GET`, `POST`, `PUT`, `DELETE`, … Defaults are automatic (see below). |
| `URL` | **Yes** | The only required argument. Scheme defaults to `http://` (or `https://` with the `https` command). |
| `ITEM` | No | Zero or more [request items](#request-items-building-any-request) — headers, data, params, files. |

### The HTTP method

The method name comes right before the URL:

```bash
http DELETE pie.dev/delete
```

In addition to the standard methods (`GET`, `POST`, `HEAD`, `PUT`, `PATCH`, `DELETE`), any custom method name is allowed:

```bash
http AHOY pie.dev/post
```

There are no restrictions on which methods may carry a body — you can send an empty `POST` or a `GET` with a body.

#### Optional `GET` and `POST`

When you omit the method, HTTPie chooses one for you:

- **`GET`** when the request has no body.
- **`POST`** when the request has data items, piped input, or `--raw`.

```bash
http pie.dev/get                 # → GET (no data)
http pie.dev/post hello=world    # → POST (has data)
```

### The request URL

The URL is the only thing HTTPie strictly needs. Several shortcuts make it faster to type:

| You type | HTTPie sends |
|----------|--------------|
| `http example.org` | `http://example.org` |
| `https example.org` | `https://example.org` |
| `http ://example.org` | `http://example.org` (paste-friendly: keep the `://`, add a space) |
| `http :3000/bar` | `http://localhost:3000/bar` |
| `http :/foo` | `http://localhost/foo` |
| `http :` | `http://localhost/` |

> [!TIP]
> The `:port` and `:/path` shorthands are perfect for local development — `http :8000/api/health` hits `http://localhost:8000/api/health`.

You can change the default scheme with `--default-scheme`:

```bash
http --default-scheme=https example.org    # → https://example.org
```

---

## Request items: building any request

Request items are the heart of HTTPie. Each item is a `key`/`value` pair, and the **separator** you use determines what part of the request it becomes. This is what lets you build virtually any HTTP request without quoting headaches or escaping `&`.

```bash
http PUT pie.dev/put \
    X-Date:today \          # Header
    token==secret \         # Query parameter
    name=John \             # Data field (JSON by default)
    age:=29                 # Raw JSON field (a number, not a string)
```

### The full separator table

| Separator | Item type | Example | Result |
|-----------|-----------|---------|--------|
| `:` | HTTP header | `X-API-Token:123` | Header `X-API-Token: 123` |
| `==` | URL query parameter | `search==httpie` | `?search=httpie` (auto URL-encoded) |
| `=` | Data field | `name=John` | JSON string field (or form field with `--form`) |
| `:=` | Raw JSON field | `age:=29`, `ok:=true`, `tags:='["a","b"]'` | Non-string JSON value |
| `@` | File upload field | `cv@~/files/cv.pdf` | Multipart file (with `--form`/`--multipart`) |
| `=@` | Data field from file | `essay=@notes.txt` | Field value read from a file |
| `:=@` | Raw JSON from file | `config:=@./config.json` | JSON value parsed from a file |
| `==@` | Query param from file | `token==@token.txt` | Param value read from a file |
| `:@` | Header from file | `X-Data:@payload.txt` | Header value read from a file |
| `;` | Empty header | `Header;` | Sends `Header:` with an empty value |

> [!IMPORTANT]
> The `:=` and `:=@` (raw JSON) separators only make sense for JSON requests. With `--form`/`--multipart`, simple scalar values (string, number, float) are still accepted, but complex JSON types (arrays, objects) raise an error: `Cannot use complex JSON value types with --form/--multipart.`

### File-based values

Adding `@` to a separator reads the value from a file instead of the command line. Trailing newlines are stripped:

```bash
http POST pie.dev/post \
    X-Data:@files/text.txt \         # Header value from a file
    token==@files/text.txt \         # Query param value from a file
    name=@files/text.txt \           # Data field value from a file
    bookmarks:=@files/data.json      # JSON object embedded from a file
```

### Escaping separators

If a separator character must appear literally in a key, escape it with a backslash:

```bash
http pie.dev/post field-name-with\:colon=value
```

For example, `foo\==bar` becomes the data field `foo=` with value `bar` (not a URL parameter).

If a field name or header starts with a dash, place it after the `--` token so HTTPie doesn't mistake it for a flag:

```bash
http pie.dev/post -- -name-starting-with-dash=foo -Unusual-Header:bar
```

---

## Sending JSON

JSON is the default content type. Any `=` and `:=` data items are serialized into a JSON object, and HTTPie sets these headers automatically (both can be overridden):

| Header | Value |
|--------|-------|
| `Content-Type` | `application/json` |
| `Accept` | `application/json, */*;q=0.5` |

```bash
http PUT pie.dev/put name=John email=[email removed]
```

```http
PUT /put HTTP/1.1
Accept: application/json, */*;q=0.5
Content-Type: application/json
Host: pie.dev

{
    "email": "[email removed]",
    "name": "John"
}
```

### String vs. non-string fields

Use `=` for strings and `:=` for any other JSON type (numbers, booleans, arrays, objects):

```bash
http PUT pie.dev/put \
    name=John \                       # String
    age:=29 \                         # Number
    married:=false \                  # Boolean
    hobbies:='["http", "pies"]' \     # Array
    favorite:='{"tool": "HTTPie"}' \  # Object
    bookmarks:=@files/data.json \     # Embed a JSON file
    description=@files/text.txt       # Embed a text file as a string
```

> [!TIP]
> Use `--json` (`-j`) to force JSON mode and the `Accept: application/json` header even when you aren't sending data. HTTPie will also try to detect and prettify JSON responses even when the server returns the wrong `Content-Type`.

### Explicit JSON

```bash
http --json pie.dev/get
```

This sets `Accept` to `application/json, */*;q=0.5` regardless of whether you send any data.

---

## Nested JSON

You can build deeply nested JSON objects and arrays directly from the command line using a path syntax inside the field name. You still use `=` and `:=`, but the key becomes a path:

```bash
http pie.dev/post \
  platform[name]=HTTPie \
  platform[about][mission]='Make APIs simple and intuitive' \
  platform[about][stars]:=54000 \
  platform[apps][]=Terminal \
  platform[apps][]=Desktop \
  platform[apps][]=Web
```

```json
{
    "platform": {
        "name": "HTTPie",
        "about": {
            "mission": "Make APIs simple and intuitive",
            "stars": 54000
        },
        "apps": ["Terminal", "Desktop", "Web"]
    }
}
```

The rules:

- `key[child]=value` creates a nested object.
- `key[]=value` appends to an array.
- `key[2]=value` sets an explicit array index (missing indexes become `null`).
- `[]:=1` (no leading key) builds a **top-level array**.

### Type safety and errors

Each path has a fixed type once first used. Mixing object-access and array-access on the same path raises a clear, pointed error:

```text
HTTPie Type Error: Can't perform 'key' based access on 'array' which has a type of 'array' but this operation requires a type of 'object'.
array[key]
     ^^^^^
```

Syntax mistakes are similarly guided:

```text
HTTPie Syntax Error: Expecting ']'
foo[baz][quux
             ^
```

> [!NOTE]
> Brackets, backslashes, and numeric indices can be escaped with `\` when you need them literally — e.g. `'foo\[bar\]:=1'` produces the key `"foo[bar]"`, and `'object[\1]=x'` produces the string key `"1"` instead of array index `1`.

---

## Sending forms and uploading files

Add `--form` (`-f`) to serialize data items as a URL-encoded form instead of JSON. The `Content-Type` becomes `application/x-www-form-urlencoded; charset=utf-8`.

```bash
http --form POST pie.dev/post name='John Smith'
```

```http
POST /post HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8

name=John+Smith
```

### File uploads

Use the `@` separator to upload a file. The presence of any file field automatically upgrades a `--form` request to `multipart/form-data`:

```bash
http -f POST pie.dev/post name='John Smith' cv@~/files/data.xml
```

The content type of each uploaded file is inferred from its name; override it inline with `;type=`:

```bash
http -f POST pie.dev/post cv@'~/files/data.bin;type=application/pdf'
```

### Forcing multipart and custom boundaries

To send a `multipart/form-data` request even without files, use `--multipart`. To set a fixed boundary string, use `--boundary`:

```bash
http --multipart --boundary=xoxo --offline example.org hello=world
```

> [!NOTE]
> File uploads are always **streamed**, so HTTPie can upload very large files without exhausting memory.

---

## HTTP headers

Set any header with the `Header:Value` notation:

```bash
http pie.dev/headers User-Agent:Bacon/1.0 X-Foo:Bar Referer:https://httpie.org/
```

### Default headers

HTTPie sets these by default, all overridable:

```http
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: HTTPie/<version>
Host: <taken-from-URL>
```

### Unsetting and emptying headers

| Goal | Syntax | Example |
|------|--------|---------|
| Remove a header entirely | `Header:` | `http pie.dev/headers Accept: User-Agent:` |
| Send a header with an empty value | `Header;` | `http pie.dev/headers 'Header;'` |
| Read a header value from a file | `Header:@file` | `http pie.dev/headers X-Data:@files/text.txt` |

> [!WARNING]
> Some internal headers such as `Content-Length` cannot be unset when HTTPie adds them automatically.

### Repeated headers

Pass the same header name twice to send it as two separate header lines, or use a comma-separated value to send it as one:

```bash
http --offline example.org Cookie:one Cookie:two       # Two Cookie lines
http --offline example.org Numbers:one,two             # One line: Numbers: one,two
```

---

## Query string parameters

The `param==value` syntax appends URL parameters without you having to escape `&` for the shell. Special characters in the name and value are automatically URL-encoded:

```bash
http https://api.github.com/search/repositories q==httpie per_page==1
```

```http
GET /search/repositories?q=httpie&per_page=1 HTTP/1.1
```

You can also read a parameter value from a file with `param==@file`:

```bash
http pie.dev/get text==@files/text.txt
```

---

## Raw request body

When the structured request-item syntax isn't what you want, you can pass an arbitrary raw body. There are three ways to do it, and **they cannot be combined with `key=value` data items**.

### 1. Pipe via stdin

```bash
http PUT pie.dev/put X-API-Token:123 < files/data.json
echo -n '{"name": "John"}' | http PATCH pie.dev/patch
http pie.dev/post <<<'{"name": "John"}'
grep '401 Unauthorized' /var/log/httpd/error_log | http POST pie.dev/post
```

### 2. The `--raw` option

Handy when piping is awkward (e.g. when generating documentation examples):

```bash
http --raw '{"name": "John"}' pie.dev/post
http --raw 'Hello, world!' pie.dev/post
```

### 3. A filename with `@`

Reads the file as the body **and** sets `Content-Type` from the file extension:

```bash
http PUT pie.dev/put @files/data.xml
```

> [!TIP]
> In scripts, always pass `--ignore-stdin`. Otherwise, when `stdin` isn't a terminal (cron jobs, CI), HTTPie waits for piped body data and appears to hang. See [Offline mode and scripting](#offline-mode-and-scripting).

### Chunked and compressed bodies

```bash
http --chunked PUT pie.dev/put hello=world        # Transfer-Encoding: chunked
http --compress pie.dev/post @files/data.xml      # Content-Encoding: deflate
http -xx PUT pie.dev/put hello=world              # Force compression even if not smaller
```

By default, `--compress` (`-x`) is skipped if compression wouldn't reduce the size; passing it twice forces it.

---

## Authentication

Two flags control authentication:

| Flag | Purpose |
|------|---------|
| `--auth`, `-a` | The credentials — a `username:password` pair or a `token`. |
| `--auth-type`, `-A` | The mechanism: `basic` (default), `digest`, `bearer`, or any installed plugin. |

### Basic, digest, and bearer

```bash
http -a username:password pie.dev/basic-auth/username/password     # Basic (default)
http -A digest -a username:password pie.dev/digest-auth/...        # Digest
https -A bearer -a token pie.dev/bearer                            # Bearer token
```

### Password prompt and empty passwords

If you omit the password, HTTPie securely prompts for it:

```bash
http -a username pie.dev/basic-auth/username/password
```

```text
http: password for [email removed]:
```

To send an *empty* password without a prompt, keep the trailing colon: `-a username:`.

> [!CAUTION]
> When combined with `--session`, prompted passwords are stored in the session file in **plain text**.

### `.netrc` support

Credentials in your `~/.netrc` are honored automatically. Disable this with `--ignore-netrc`:

```bash
http --ignore-netrc pie.dev/basic-auth/httpie/test
```

### Auth plugins

More mechanisms install as plugins (AWS, OAuth, JWT, NTLM, HMAC, …). Search PyPI for `httpie-`, then install with the [plugin manager](#the-httpie-management-command):

```bash
httpie cli plugins install httpie-jwt-auth
```

---

## Cookies and sessions

### Cookies

HTTPie has no special cookie syntax — cookies are just headers:

```bash
http pie.dev/cookies Cookie:sessionid=foo
http pie.dev/cookies 'Cookie:sessionid=foo;another-cookie=bar'
```

> [!NOTE]
> Quote the value when it contains `;` so your shell doesn't interpret it.

### Sessions

By default every request is independent. A **session** persists custom headers, authentication, and cookies between requests to the same host. Activate one with `--session=NAME_OR_PATH`.

```bash
http --session=user1 -a user1:password pie.dev/get X-Foo:Bar   # Create
http --session=user1 pie.dev/get                               # Reuse — auth + X-Foo restored
```

Headers starting with `Content-` or `If-` are **not** persisted (they are request-specific).

#### Named vs. anonymous sessions

- **Named:** `--session=user1` stores the file in the config directory under `sessions/<host>/<name>.json`.
- **Anonymous:** `--session=./session.json` (a path containing at least one `/`) stores it wherever you point and can be **shared across hosts**.

```bash
http --session=/tmp/session.json example.org
http --session=/tmp/session.json admin.example.org   # Same session, different host
```

> [!IMPORTANT]
> For an anonymous session you must include at least one `/` (e.g. `./session.json`). Without a slash, HTTPie treats the value as a named session.

#### Read-only sessions

Use `--session-read-only=NAME_OR_PATH` to use a session without updating it from the response:

```bash
http --session-read-only=./ro-session.json pie.dev/headers Custom-Header:value
```

#### Cookie domain binding

Session cookies have a `domain` field that binds them to a host (and its subdomains). Set `"domain": null` in the session JSON to make a cookie unbound (sent to any host). All session data — credentials, passwords, cookies — is stored as plain-text JSON you can edit by hand.

> [!WARNING]
> Session files are plain text. Anyone with read access to the file can read the stored credentials and cookies.

---

## Controlling the output

By default HTTPie prints the response headers and body. The following options change what is shown.

| Option | Prints |
|--------|--------|
| `--headers`, `-h` | Only the response headers |
| `--body`, `-b` | Only the response body |
| `--meta`, `-m` | Only the response metadata (elapsed time) |
| `--verbose`, `-v` | The whole exchange: request **and** response (also enables `--all`) |
| `-vv` | Like `-v`, plus response metadata |
| `--print`, `-p` | A custom selection (see below) |
| `--quiet`, `-q` | Nothing to stdout/stderr (`-qq` silences warnings too) |

### Fine-grained `--print`

`--print` (`-p`) takes a string of characters, each selecting one part of the exchange:

| Character | Part |
|-----------|------|
| `H` | request headers |
| `B` | request body |
| `h` | response headers |
| `b` | response body |
| `m` | response metadata |

```bash
http --print=Hh PUT pie.dev/put hello=world    # Request headers + response headers
http --print=hm pie.dev/get                    # Response headers + metadata
```

### Colors and formatting

Syntax highlighting and formatting are applied automatically for terminal output. Control them with:

| Option | Effect |
|--------|--------|
| `--pretty=all` | Colors **and** formatting (default for terminals) |
| `--pretty=colors` | Colors only |
| `--pretty=format` | Formatting only |
| `--pretty=none` | No processing (default for redirected output) |
| `--style=NAME`, `-s` | Choose a color scheme |

Notable styles include `auto` (default, follows your terminal), `pie-dark`, `pie-light`, `pie`, `monokai`, and `fruity`. Run `http --help` to see every available style on your system.

Formatting sorts headers by name, indents and key-sorts JSON, and indents XML. Tune it with `--format-options`:

| Option | Default | Shortcut |
|--------|---------|----------|
| `headers.sort` | `true` | `--sorted` / `--unsorted` |
| `json.format` | `true` | — |
| `json.indent` | `4` | — |
| `json.sort_keys` | `true` | `--sorted` / `--unsorted` |
| `xml.format` | `true` | — |
| `xml.indent` | `2` | — |

```bash
http --format-options headers.sort:false,json.sort_keys:false,json.indent:2 pie.dev/get
http --unsorted pie.dev/get    # Shortcut: disable all sorting
```

### Overriding response encoding and type

```bash
http --response-charset=big5 pie.dev/get          # Force a charset
http --response-mime=text/yaml pie.dev/get        # Force highlighter/formatter
```

### Streamed responses

Responses are downloaded in chunks. Use `--stream` (`-S`) to flush each line immediately (like `tail -f`), which is ideal for long-lived endpoints:

```bash
http --stream pie.dev/stream/3
```

> [!NOTE]
> Streaming is enabled automatically when the response has `Content-Type: text/event-stream` (Server-Sent Events).

### Binary data

Binary response bodies are suppressed in the terminal so they can't garble it:

```text
+-----------------------------------------+
| NOTE: binary data not shown in terminal |
+-----------------------------------------+
```

---

## Downloading files

The `--download` (`-d`) flag turns HTTPie into a `wget`-style downloader: response headers print to `stderr` and the body streams to a file with a progress bar.

```bash
http --download https://github.com/httpie/cli/archive/master.tar.gz
```

```text
Downloading 251.30 kB to "httpie-master.tar.gz"
Done. 251.30 kB in 2.73862s (91.76 kB/s)
```

### How the filename is chosen

In decreasing priority:

1. `--output`/`-o` if you provide it (file is overwritten, or appended to with `--continue`).
2. The server's `Content-Disposition` header.
3. A name generated from the URL and `Content-Type`.

To avoid overwriting, HTTPie adds a numeric suffix when needed.

### Resuming a download

`--continue` (`-c`) resumes a partial download (requires `--output` and a server that supports `Range`/`206`):

```bash
http -dco file.zip example.org/file
```

`-dco` is shorthand for `--download --continue --output`.

> [!IMPORTANT]
> `--download` always implies `--follow` and `--check-status`. HTTPie exits `1` if the body wasn't fully downloaded.

---

## Redirects, proxies, and networking

### Following redirects

Redirects are **not** followed by default. Enable them with `--follow` (`-F`):

```bash
http --follow pie.dev/redirect/3
http --follow --all pie.dev/redirect/3              # Show every intermediary response
http --follow --max-redirects=2 pie.dev/redirect/3  # Cap the number followed (default 30)
```

> [!NOTE]
> For `307 Temporary Redirect` and `308 Permanent Redirect`, the original method and body are reused. Otherwise a body-less `GET` is sent.

### Proxies

```bash
http --proxy=http:http://10.10.1.10:3128 --proxy=https:https://10.10.1.10:1080 example.org
http --proxy=http:http://user:pass@10.10.1.10:3128 example.org        # With auth
http --proxy=http:socks5://user:pass@host:port example.org            # SOCKS
```

HTTPie also honors the `ALL_PROXY`, `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` environment variables.

### Other networking flags

| Flag | Effect |
|------|--------|
| `--timeout=SECONDS` | Fail if no response within the timeout (default `0` = no limit). |
| `--max-headers=N` | Stop after reading N response headers (default `0` = no limit). |
| `--check-status` | Exit non-zero on `3xx`/`4xx`/`5xx` responses. |
| `--path-as-is` | Don't squash `/../` and `/./` in the URL path. |

---

## HTTPS, SSL, and certificates

```bash
http --verify=no https://pie.dev/get                          # Skip cert verification
http --verify=/ssl/custom_ca_bundle https://example.org       # Custom CA bundle
http --cert=client.pem https://example.org                    # Client certificate
http --cert=client.crt --cert-key=client.key https://example.org
```

If a client key is encrypted, HTTPie prompts for the passphrase automatically; supply it non-interactively with `--cert-key-pass`.

Choose a TLS version with `--ssl` (one of `ssl2.3`, `ssl3`, `tls1`, `tls1.1`, `tls1.2`, `tls1.3`) and the cipher list with `--ciphers` (OpenSSL cipher-list format).

> [!CAUTION]
> `--verify=no` disables certificate validation entirely, exposing the connection to man-in-the-middle attacks. Use it only against trusted hosts you control. You can also set a custom CA bundle via the `REQUESTS_CA_BUNDLE` environment variable.

---

## Offline mode and scripting

### Offline mode

`--offline` builds the request and prints it without sending anything over the network. It automatically prints both request headers and body (`--print=HB`):

```bash
http --offline POST pie.dev/post hello=world
```

Use it to generate documentation examples or raw request files:

```bash
http --offline POST pie.dev/post hello=world > request.http
nc pie.dev 80 < request.http
```

### Scripting best practices

```bash
#!/bin/bash
if http --check-status --ignore-stdin --timeout=2.5 HEAD pie.dev/get &> /dev/null; then
    echo 'OK!'
else
    case $? in
        2) echo 'Request timed out!' ;;
        3) echo 'Unexpected HTTP 3xx Redirection!' ;;
        4) echo 'HTTP 4xx Client Error!' ;;
        5) echo 'HTTP 5xx Server Error!' ;;
        6) echo 'Exceeded --max-redirects redirects!' ;;
        *) echo 'Other Error!' ;;
    esac
fi
```

- Use `--check-status` so the exit code reflects the HTTP status (see [Exit status codes](#exit-status-codes)).
- Use `--ignore-stdin` so HTTPie doesn't hang waiting for piped input in non-interactive environments.
- Use `--timeout` so a non-responsive server doesn't freeze your script.

---

## Configuration

HTTPie reads an optional `config.json` file. It doesn't exist by default — create it yourself.

### Config directory

| Platform | Location |
|----------|----------|
| Most systems | `$XDG_CONFIG_HOME/httpie/config.json` (defaults to `~/.config/httpie/config.json`) |
| Legacy | `~/.httpie/config.json` (used if `~/.httpie` exists) |
| Windows | `%APPDATA%\httpie\config.json` |

Override the directory with the `HTTPIE_CONFIG_DIR` environment variable:

```bash
export HTTPIE_CONFIG_DIR=/tmp/httpie
http pie.dev/get
```

Run `http --debug` and look for `config_dir` to see your exact path.

### Configurable options

| Key | Type | Purpose |
|-----|------|---------|
| `default_options` | array | Options applied to every invocation (e.g. a default style). |
| `plugins_dir` | path | Where `httpie cli plugins install` stores plugins. |
| `disable_update_warnings` | boolean | Turn off new-release notifications. |

```json
{
    "default_options": ["--style=fruity", "--check-status"]
}
```

> [!TIP]
> Any default option can be undone for a single invocation with the matching `--no-OPTION` flag — e.g. `--no-style` or `--no-session`.

---

## The httpie management command

The `httpie` command (distinct from `http`/`https`) manages plugins and configuration. It never sends requests.

### Plugin manager

| Command | What it does |
|---------|--------------|
| `httpie cli plugins install <target>...` | Install plugins from PyPI or a local path. |
| `httpie cli plugins list` | List installed plugins and their entry points. |
| `httpie cli plugins upgrade <target>...` | Upgrade installed plugins. |
| `httpie cli plugins uninstall <target>...` | Remove plugins installed via this manager. |

```bash
httpie cli plugins install httpie-plugin
httpie cli plugins list
```

```text
httpie_plugin (1.0.2)
  httpie_plugin (httpie.plugins.auth.v1)
```

> [!NOTE]
> The plugin manager is a thin overlay on top of `pip` that installs into an isolated `plugins_dir`, so it works even on installations (like Homebrew) where direct `pip install` into HTTPie's environment fails. `httpie plugins ...` is an accepted alias for `httpie cli plugins ...`.

### Other management commands

| Command | What it does |
|---------|--------------|
| `httpie cli check-updates` | Check whether a newer release is available. |
| `httpie cli export-args [-f json]` | Export the `http`/`https` parser spec (for autocomplete tools). |
| `httpie cli sessions upgrade <host> <session>` | Upgrade one session file to the latest format. |
| `httpie cli sessions upgrade-all` | Upgrade every named session. |

```bash
httpie cli sessions upgrade-all
```

```text
Upgraded 'api_auth' @ 'pie.dev' to v3.1.0
Upgraded 'login_cookies' @ 'httpie.io' to v3.1.0
```

The session-upgrade commands accept `--bind-cookies`, which binds previously unbound cookies to the session's host.

---

## How HTTPie works under the hood

A quick mental model of what happens when you run a command (useful for predicting behavior):

1. **Parse** — your arguments are split into flags and request items. The request-item separators decide which become headers, data, params, or files.
2. **Method inference** — if you didn't name a method, HTTPie picks `GET` or `POST` based on whether there's a body.
3. **Build** — HTTPie assembles a request using the [Requests](https://requests.readthedocs.io/) library, applying session data, auth, and default headers.
4. **Send** — unless `--offline` is set. Redirects are handled according to `--follow`/`--max-redirects`.
5. **Output** — the response streams through a formatter (colors, JSON/XML indentation) chosen from the `Content-Type`, then prints.

> [!NOTE]
> HTTPie is built on two well-known libraries: [Requests](https://requests.readthedocs.io/) for the HTTP transport and [Pygments](https://pygments.org/) for syntax highlighting. For architecture, internals, and the plugin API, see the **HTTPie Admin Guide**.

---

## Troubleshooting

### Error: `Request body (from stdin, --raw or a file) and request data (key=value) cannot be mixed.`

**Cause:** You combined piped/`--raw`/`@file` body data with `key=value` data items. Only one source of request data is allowed.
**Solution:** Use either structured items **or** a raw body, not both. To let the `key=value` items win and ignore stdin, add `--ignore-stdin`.
**Prevention:** When scripting, decide up front whether a request is structured or raw.

### Problem: HTTPie hangs and produces no output

**Cause:** In a non-interactive context (cron, CI, a subshell), `stdin` isn't a terminal, so HTTPie waits for a request body that never arrives.
**Solution / Prevention:** Always pass `--ignore-stdin` in scripts unless you are deliberately piping a body.

### Error: `Cannot use complex JSON value types with --form/--multipart.`

**Cause:** You used a `:=` raw-JSON array or object together with `--form`/`--multipart`.
**Solution:** Send the request as JSON (drop `--form`), or pass only scalar values (strings, numbers) as form fields.

### Error: `--continue only works with --download` / `--continue requires --output to be specified`

**Cause:** `--continue` (`-c`) was used without `--download`, or without `--output`.
**Solution:** Resume downloads with all three: `http -dco file.zip example.org/file`.

### Error: `cannot combine --compress and --chunked` / `cannot combine --compress and --multipart`

**Cause:** `--compress` can't be used with `--chunked` or `--multipart` in the same request.
**Solution:** Drop one of the conflicting flags.

### Error: `Only terminal output can be colorized on Windows.`

**Cause:** You combined `--pretty` (colors) with `--output` to a file on Windows.
**Solution:** Write the file without colors, or print to the terminal and redirect separately.

### Problem: JSON `Content-Type` not set when a single header is present

**Cause:** A known issue ([#1640](https://github.com/httpie/cli/issues/1640), [#1834](https://github.com/httpie/cli/issues/1834)) where supplying certain single headers can suppress the automatic `application/json` content type.
**Solution:** Set the header explicitly: add `Content-Type:application/json` to the request.

### Error: `'<value>' is not a valid value`

**Cause:** A request item didn't contain a recognized separator, so HTTPie couldn't classify it.
**Solution:** Make sure each item uses one of the [separators](#the-full-separator-table) (`:`, `=`, `==`, `:=`, `@`, …). Escape a literal separator in a key with `\`.

### Problem: A field or header starting with `-` is treated as a flag

**Cause:** HTTPie parses leading-dash tokens as options.
**Solution:** Put such items after the `--` token: `http pie.dev/post -- -Weird-Header:value`.

### Error: `Unable to prompt for passwords because --ignore-stdin is set.`

**Cause:** You used `--auth` without a password while `--ignore-stdin` is active, so HTTPie can't prompt.
**Solution:** Provide the full `username:password`, or remove `--ignore-stdin` for interactive use.

### Problem: A binary response shows "binary data not shown in terminal"

**Cause:** This is intentional — HTTPie suppresses binary bodies to protect your terminal.
**Solution:** Redirect output to a file (`> out.bin`) or use `--download`.

### Error: `invalid config file` / `cannot read config file`

**Cause:** `config.json` contains invalid JSON or can't be read.
**Solution:** Validate the file's JSON. Find its location with `http --debug` (look for `config_dir`).

### Problem: A new-version warning keeps appearing

**Cause:** HTTPie checks for updates periodically and warns about once a week.
**Solution:** Set `"disable_update_warnings": true` in `config.json`.

---

## FAQ

**Q: What's the difference between `http` and `https`?**
They are the same program; `http` defaults the URL scheme to `http://` and `https` defaults it to `https://`. Use whichever saves typing.

**Q: How do I see the request that HTTPie actually sends?**
Use `-v` (`--verbose`) to print the full request and response, or `--offline` to build and print a request without sending it.

**Q: How do I send a number or boolean in JSON instead of a string?**
Use the `:=` separator: `age:=29`, `active:=true`, `tags:='["a","b"]'`.

**Q: Why did my request become a `POST` when I didn't ask for one?**
HTTPie defaults to `POST` whenever there's body data, and `GET` otherwise. Name the method explicitly to override.

**Q: How do I upload a file?**
Use `@`: `http -f POST pie.dev/post cv@~/files/cv.pdf`. The `--form` flag plus a file field produces a `multipart/form-data` request.

**Q: How do I keep a login across multiple requests?**
Use a session: `http --session=mysession -a user:pass example.org/login`, then reuse `--session=mysession` on later commands.

**Q: Where are my session and config files stored?**
On most systems under `~/.config/httpie/` (sessions in `sessions/<host>/`), and `%APPDATA%\httpie\` on Windows. Override with `HTTPIE_CONFIG_DIR`.

**Q: How do I make form data the default instead of JSON?**
Add `--form` to `default_options` in your `config.json`.

**Q: How do I pass a raw JSON body instead of building it field by field?**
Pipe it (`echo '{...}' | http POST url`), use `--raw '{...}'`, or read it from a file with `@file.json`.

**Q: How do I make HTTPie return a non-zero exit code on HTTP errors?**
Add `--check-status`. The exit code will be `3` (3xx, unless `--follow`), `4` (4xx), or `5` (5xx).

**Q: How do I disable colors when piping to another program?**
Output is already uncolored when redirected. Force it anywhere with `--pretty=none`. Force colors *on* in a pipe with `--pretty=all` and view through `less -R`.

**Q: How do I install an authentication method that isn't built in?**
Install a plugin: `httpie cli plugins install httpie-jwt-auth`, then use it with `-A jwt`.

**Q: How do I skip SSL verification for a self-signed certificate?**
Use `--verify=no`, or better, point `--verify` at the CA bundle: `--verify=/path/to/ca.pem`.

**Q: Can I send the same header twice?**
Yes — repeat it: `http example.org Cookie:one Cookie:two`. HTTPie sends two separate header lines.

**Q: How do I resume an interrupted download?**
`http -dco file.zip example.org/file` — the server must support `Range` requests.

**Q: How do I send a request body with a `GET`?**
Just add data items and name the method: `http GET pie.dev/get hello=world`.

---

## Complete option reference

### Content type

| Option | Description |
|--------|-------------|
| `--json`, `-j` | (default) Serialize data items as a JSON object; set JSON `Content-Type`/`Accept`. |
| `--form`, `-f` | Serialize data items as form fields (`application/x-www-form-urlencoded`). |
| `--multipart` | Always send `multipart/form-data`, even without files. |
| `--boundary` | Custom multipart boundary string (with `--form`). |
| `--raw` | Pass a raw request body string without processing. |

### Content processing

| Option | Description |
|--------|-------------|
| `--compress`, `-x` | Deflate-compress the body (`Content-Encoding: deflate`). Repeat to force. |

### Output processing

| Option | Description |
|--------|-------------|
| `--pretty` | `all` / `colors` / `format` / `none`. |
| `--style`, `-s` | Color scheme (default `auto`). |
| `--unsorted` | Disable all output sorting. |
| `--sorted` | Re-enable all output sorting. |
| `--response-charset` | Override response encoding for display (e.g. `utf8`, `big5`). |
| `--response-mime` | Override response MIME type for coloring/formatting. |
| `--format-options` | Fine-grained formatting (e.g. `json.indent:2`). |

### Output options

| Option | Description |
|--------|-------------|
| `--print`, `-p` | Select parts to print (`H`, `B`, `h`, `b`, `m`). |
| `--headers`, `-h` | Print only response headers. |
| `--meta`, `-m` | Print only response metadata. |
| `--body`, `-b` | Print only response body. |
| `--verbose`, `-v` | Print the whole exchange; repeat (`-vv`) to add metadata. |
| `--all` | Show all intermediary requests/responses. |
| `--history-print`, `-P` | Output options for intermediary exchanges. |
| `--stream`, `-S` | Stream the body line by line (`tail -f` behavior). |
| `--output`, `-o` | Save output to a file. |
| `--download`, `-d` | Download the body to a file (wget-style). |
| `--continue`, `-c` | Resume an interrupted download (needs `--output`). |
| `--quiet`, `-q` | Suppress stdout/stderr; repeat (`-qq`) to silence warnings. |

### Sessions

| Option | Description |
|--------|-------------|
| `--session` | Create or reuse-and-update a session. |
| `--session-read-only` | Read a session without updating it. |

### Authentication

| Option | Description |
|--------|-------------|
| `--auth`, `-a` | `username[:password]` or `token`. |
| `--auth-type`, `-A` | `basic` (default), `digest`, `bearer`, or a plugin. |
| `--ignore-netrc` | Ignore credentials from `.netrc`. |

### Network

| Option | Default | Description |
|--------|---------|-------------|
| `--offline` | — | Build and print the request without sending it. |
| `--proxy` | — | `PROTOCOL:PROXY_URL` (repeatable). |
| `--follow`, `-F` | off | Follow `30x` redirects. |
| `--max-redirects` | `30` | Maximum redirects to follow. |
| `--max-headers` | `0` | Max response headers to read (`0` = no limit). |
| `--timeout` | `0` | Connection timeout in seconds (`0` = no limit). |
| `--check-status` | off | Exit non-zero on error status codes. |
| `--path-as-is` | off | Don't squash `/../` and `/./` in the path. |
| `--chunked` | off | Use `Transfer-Encoding: chunked`. |

### SSL

| Option | Default | Description |
|--------|---------|-------------|
| `--verify` | `yes` | `no` to skip verification, or a CA-bundle path. |
| `--ssl` | — | TLS version: `ssl2.3`, `ssl3`, `tls1`, `tls1.1`, `tls1.2`, `tls1.3`. |
| `--ciphers` | — | OpenSSL cipher-list string. |
| `--cert` | — | Client-side certificate file. |
| `--cert-key` | — | Private key for `--cert`. |
| `--cert-key-pass` | — | Passphrase for the private key (prompted if omitted). |

### Troubleshooting & meta

| Option | Default | Description |
|--------|---------|-------------|
| `--ignore-stdin`, `-I` | off | Don't read stdin (use in scripts). |
| `--help` | — | Show the help message. |
| `--manual` | — | Show the full manual / man page. |
| `--version` | — | Show the version and exit. |
| `--traceback` | off | Print a Python traceback on error. |
| `--default-scheme` | `http` | Default URL scheme when none is given. |
| `--debug` | off | Print diagnostic info for bug reports. |

> [!NOTE]
> Every `--OPTION` has a corresponding `--no-OPTION` form that resets it to its default — useful for overriding `default_options` from the config file on a single invocation.

### Exit status codes

| Code | Meaning |
|------|---------|
| `0` | Success |
| `1` | Generic error |
| `2` | Request timed out |
| `3` | `3xx` redirect (with `--check-status`, no `--follow`) |
| `4` | `4xx` client error (with `--check-status`) |
| `5` | `5xx` server error (with `--check-status`) |
| `6` | Too many redirects |
| `7` | Plugin error |
| `130` | Interrupted with `Ctrl-C` |

### Environment variables

| Variable | Effect |
|----------|--------|
| `HTTPIE_CONFIG_DIR` | Override the configuration directory. |
| `XDG_CONFIG_HOME` | Base directory for the default config location. |
| `REQUESTS_CA_BUNDLE` | Custom CA bundle for SSL verification. |
| `ALL_PROXY`, `HTTP_PROXY`, `HTTPS_PROXY` | Proxy servers per protocol. |
| `NO_PROXY` | Hosts that bypass the configured proxies. |
| `HTTPIE_STDIN_READ_WARN_THRESHOLD` | Seconds before warning about idle stdin (default `10.0`; `0` disables). |

---

_Generated June 2026 from httpie/cli at 5b604c3. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
