# curl: HTTP Debugging in CLI

LLMS index: [llms.txt](/en/llms.txt)

---

cURL is the standard tool for debugging HTTP in the terminal. It ships out of the box on Linux and macOS and is present in most Docker images. Need to quickly check an API, inspect response headers, or trace a redirect issue — one command line is enough.

## Basic Debug Flags

The most common scenario: get a response and see what the server returned. The `-i` flag prints headers before the body, `-v` enables verbose mode with connection details.

```bash
curl -i https://api.example.com/health
curl -v https://api.example.com/health
```

The difference: `-i` shows headers plus body, `-v` adds DNS resolution, TLS handshake, and debug info before the request.

A HEAD request checks resource availability and metadata without downloading the body:

```bash
curl -I https://api.example.com/v2/large-file.zip
```

> [!NOTE]
> HEAD does not guarantee the server supports ranges or caching — this depends on server configuration.

## Methods and Request Body

By default, curl sends GET. For other methods, use the `-X` flag.

```bash
curl -X POST https://api.example.com/users
curl -X DELETE https://api.example.com/users/42
```

Request body is passed via `-d`. For JSON APIs, a typical pattern:

```bash
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -d '{"name": "alice", "role": "admin"}'
```

> [!TIP]
> Multiline JSON is easier to read in a heredoc when the body is large:
> ```bash
> curl -X POST https://api.example.com/users \
>   -H "Content-Type: application/json" \
>   -d @- <<'EOF'
>   {
>     "name": "alice",
>     "role": "admin"
>   }
>   EOF
> ```

To send form data or data from a file:

```bash
curl -X POST https://api.example.com/upload \
  -d "username=admin" \
  -d "password=secret"
```

## Custom Headers

The `-H` flag adds or overrides a header. You can use `-H` multiple times.

```bash
curl -X GET https://api.example.com/orders \
  -H "Accept: application/json" \
  -H "X-Request-ID: $(uuidgen)" \
  -H "Cache-Control: no-cache"
```

Overriding the Host header is useful when debugging virtual hosts or proxies:

```bash
curl -X GET http://10.0.0.5/ \
  -H "Host: example.com"
```

To remove a default header, use `-H "Accept:"` — empty value after the colon.

## Auth and Certificates

Basic HTTP auth via `-u` in `user:password` format:

```bash
curl -u admin:secret https://api.example.com/admin
```

For Bearer tokens, use a header:

```bash
curl -H "Authorization: Bearer eyJhbGci..." https://api.example.com/me
```

> [!WARNING]
> `-u` sends credentials in plain text if TLS is not used. Always use HTTPS for production servers.

When working with self-signed certificates, the `-k` flag disables verification:

```bash
curl -k https://dev.example.com/api
```

For known hosts and pinned certificates:

```bash
# specify CA bundle
curl --cacert /etc/ssl/certs/ca-certificates.crt https://secure.example.com
# check remote host certificate
curl -v https://secure.example.com 2>&1 | grep "Server certificate"
```

## Timeouts and Saving Response

By default, curl waits indefinitely. For scripts and monitoring, set limits:

| Flag | Purpose |
|------|---------|
| `--max-time N` | total timeout in seconds |
| `--connect-timeout N` | connection timeout |

```bash
curl --max-time 5 --connect-timeout 2 https://slow-api.example.com
```

Saving the response:

```bash
# to file with original name
curl -O https://example.com/reports/november.csv
# to specified file
curl -o report.csv https://example.com/reports/november.csv
```

Redirect stdout to pipe the response body:

```bash
curl -s https://api.example.com/health | jq .status
```

## Redirects

Curl does not follow redirects by default. The `-L` flag enables automatic redirection:

```bash
curl -L https://bit.ly/api-status
```

To debug a redirect chain:

```bash
curl -Lv https://short.link/resource 2>&1 | grep -E "< HTTP|< Location"
```

> [!NOTE]
> `-L` limits redirect depth (default 50). Infinite redirect loops are a common cause of curl hanging.

A flag combination for a full picture when debugging an API:

```bash
curl -X POST https://api.example.com/orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"item_id": 101, "qty": 2}' \
  -iv --max-time 10 -o response.json
```

This command shows request and response headers, saves the body to a file, and enforces a 10-second timeout.
