Skip to content

Basic Usage

Command-Line Interface

The httptap command-line interface provides various options to customize your HTTP requests and output.

Syntax

httptap [OPTIONS] URL

Options

Curl compatibility: Common curl flags are accepted as aliases. Swap curl for httptap and keep using familiar options like -X/--request, -L/--location, -m/--max-time, -k/--insecure, -x, and --http1.1; -f/--fail, -4/--ipv4, -6/--ipv6, and --resolve use the same names as in curl. This is not a full curl clone—stick to the overlapping flags listed here.

Request Options

-X, --request, --method METHOD

Specify the HTTP method to use. Supported methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.

Method values are case-insensitive.

Curl-compatible aliases: -X, --request.

httptap --method POST https://httpbin.io/post

Default behavior: - Without --data: defaults to GET - With --data but no --method: auto-switches to POST (similar to curl) - With explicit --method: respects the specified method

-d, --data DATA

Send request body data. Can be inline string or file reference using @filename syntax.

Inline JSON data:

httptap --data '{"name": "John", "email": "john@example.com"}' https://httpbin.io/post

Load from file:

httptap --data @payload.json https://httpbin.io/post

Inline data is sent as the exact bytes of the argument, like curl; on POSIX systems this includes arguments that are not valid UTF-8.

Auto-detection: - Content-Type is automatically detected (JSON, XML, plain text) - File extension is checked first (.json, .xml, .txt) - Falls back to JSON validation

Examples with different methods:

# POST (auto-detected when --data is present)
httptap --data '{"key": "value"}' https://httpbin.io/post

# PUT
httptap --method PUT --data '{"status": "updated"}' https://httpbin.io/put

# PATCH
httptap --method PATCH --data '{"field": "modified"}' https://httpbin.io/patch

# Explicit GET with body (uncommon, triggers warning)
httptap --method GET --data 'query-data' https://httpbin.io/get

-H, --header

Add custom HTTP headers to the request. Can be used multiple times.

httptap -H "Accept: application/json" https://httpbin.io
httptap \
  -H "User-Agent: MyApp/1.0" \
  -H "Authorization: Bearer token123" \
  https://httpbin.io/bearer

Header names must be HTTP tokens (letters, digits and !#$%&'*+-.^_`|~), and values may contain only printable ASCII characters, spaces and tabs. A header that breaks these rules, such as a name with a space, a value with CR, LF or another control character, or a non-ASCII value (httpx sends header values as ASCII), is rejected with exit code 64 before any request is made. The error names the header but never prints its value.

-L, --location, --follow

Follow HTTP redirects and show timing for each step in the chain (max 10 redirects).

Curl-compatible aliases: -L, --location.

httptap --follow https://httpbin.io/redirect/3

By default, httptap does not follow redirects and will stop at the first redirect response (3xx status code).

If the response is still a redirect after 10 followed redirects, httptap stops, prints a warning, marks that step with redirect_limit_reached: true in the JSON export, and exits with code 47.

When following redirects, httptap applies the same rules as curl and browsers:

  • Authorization, Cookie and Proxy-Authorization headers are sent only to the original origin (scheme, host and port). Once a redirect points to a different origin, they are dropped for the rest of the chain; an http → https upgrade on the same host with default ports (80 → 443) keeps them.
  • 303 See Other, and 301/302 after a POST, switch the next request to GET without a body. 307 and 308 keep the method and body.

If the Location of a redirect cannot be requested (an invalid or out-of-range port, a missing host, a scheme other than http/https, a malformed IPv6 literal), the 3xx step is kept and the chain ends with a failed step for that target with the error Invalid redirect target: …, and httptap exits with code 75. Without --follow, the 3xx response is reported as received, whatever its Location.

Credentials in a Location URL (https://user:password@host/) are masked in the output and JSON export (https://user:****@host/), but the real URL is followed.

-m, --max-time, --timeout SECONDS

Abort the request chain if total elapsed time exceeds the specified number of seconds.

The limit is a hard deadline for the whole chain, redirects included: DNS, connecting, waiting for the response and reading the body all share it, and a server that stalls or keeps trickling bytes is cut off when it passes. The step then fails with Request timeout: total deadline exceeded and httptap exits with code 75.

Curl-compatible aliases: -m, --max-time.

httptap --timeout 10 https://httpbin.io/delay/2

Default timeout is 20 seconds.

--no-http2 / --http1.1

Disable HTTP/2 negotiation and force HTTP/1.1 connections.

httptap --no-http2 https://httpbin.io

By default, HTTP/2 is enabled if the server supports it.

Curl-compatible alias: --http1.1.

-4, --ipv4 and -6, --ipv6

Restrict DNS resolution and the connection to IPv4 or IPv6. The options are mutually exclusive.

httptap -4 https://example.com
httptap --ipv6 https://example.com

They cannot be used with HTTP, HTTPS, or SOCKS5H proxies, because those proxies resolve the target hostname themselves.

--resolve HOST:PORT:ADDR

Connect a hostname and port to a specific IPv4 or IPv6 address while retaining the original Host header and TLS SNI. This is useful when testing one backend before a DNS switch or bypassing a round-robin DNS record. The option can be repeated for different host and port pairs.

httptap --resolve api.example.com:443:203.0.113.10 https://api.example.com/health
httptap --resolve api.example.com:443:[2001:db8::10] https://api.example.com/health

Internationalized hostnames match in either form: an entry for bücher.example also applies to https://xn--bcher-kva.example/, and the other way round. httptap resolves such names in their IDNA 2008 form (xn--…), the same name it sends in the Host header and TLS SNI.

--resolve applies to direct connections and local-DNS SOCKS5 proxies. HTTP, HTTPS, and SOCKS5H proxies resolve the target remotely, so combining them with --resolve is rejected, the same as for -4/-6.

-k, --insecure, --ignore-ssl

Disable TLS certificate verification. Useful for debugging self-signed hosts or expired certificates.

httptap --ignore-ssl https://self-signed.badssl.com

Warning

Use this option only on trusted networks. It disables certificate validation and relaxes handshake constraints.

Curl-compatible aliases: -k, --insecure.

-x, --proxy URL

Route requests through the specified proxy. Supports HTTP, HTTPS, SOCKS5, and SOCKS5H protocols.

Curl-compatible alias: -x.

# HTTP proxy
httptap --proxy http://proxy.local:8080 https://httpbin.io/get

# SOCKS5 proxy (DNS resolved by proxy)
httptap --proxy socks5h://proxy.local:1080 https://httpbin.io/get

# SOCKS5 proxy (DNS resolved locally)
httptap --proxy socks5://proxy.local:1080 https://httpbin.io/get

# Ignore proxy environment variables and connect directly
httptap --proxy "" https://httpbin.io/get

The --proxy flag takes precedence over environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY). Use --proxy "" to ignore all proxy environment variables and connect directly. See Advanced Features for details on proxy protocols, DNS resolution, and environment variable configuration.

Credentials in the proxy URL (http://user:password@proxy:3128), including ones taken from environment variables, are used for the connection but masked in the output and JSON export (http://user:****@proxy:3128).

A proxy given without a scheme (proxy.local:3128) is treated as http://, as in curl. A malformed proxy URL (an unsupported scheme, a missing host, an invalid or out-of-range port, an unterminated IPv6 literal) is rejected with exit code 64 before any request is made; the error shows the URL with its password masked.

--cacert, --ca-bundle PATH

Use a custom CA certificate bundle (PEM format) for TLS verification. Useful for internal endpoints signed by a private CA.

httptap --cacert ~/certs/company-ca.pem https://internal-api.example.com/health

Mutually exclusive with --ignore-ssl.

Output Options

--compact

Display results in a compact single-line format, suitable for logging.

httptap --compact https://httpbin.io/get

Output:

Step 1: 200 GET https://httpbin.io/get | dns=8.9ms connect=97.0ms tls=194.6ms ttfb=446.0ms total=447.3ms | 389 B

--compact prints one human-readable line per step (suitable for logs and redirect-chain tracing) while still rendering the analysis header and Redirect Chain Summary table. Response size is shown with the appropriate unit (B, KB, MB). For machine-parseable output, see --metrics-only.

--metrics-only

Output raw metrics without formatting, ideal for scripting and automation.

httptap --metrics-only https://httpbin.io

Output:

Step 1: dns=30.1 connect=97.3 tls=199.0 ttfb=472.2 total=476.0 status=200 bytes=389 ip=44.211.11.205 family=IPv4 tls_version=TLSv1.2 proxy=direct

--json PATH

Export full request data to a JSON file. Use - to write the JSON to stdout instead; the regular report is then suppressed so the output can be piped.

httptap --json report.json https://httpbin.io
httptap --json - https://httpbin.io | jq '.summary'

If the file cannot be written, httptap exits with code 73.

The JSON file contains:

  • Timing breakdown for all phases
  • Network information (IP address, TLS details, certificate info)
  • Response metadata (status, headers, body size)
  • Complete redirect chain (when using --follow)
  • SLO evaluation (when --slo is supplied)

--har PATH

Export the request chain as an HTTP Archive (HAR 1.2) file that browser DevTools and HAR viewers can open. Use - to write it to stdout; the regular report is then suppressed. --har can be combined with --json, but only one of them can use -.

httptap --follow --har run.har https://httpbin.io/redirect/2
httptap --har - https://httpbin.io/get | jq '.log.entries[].timings'

If the file cannot be written, httptap exits with code 73. See HAR Export for the timings mapping and the fields httptap adds.

--prometheus PATH

Write per-phase timings in Prometheus textfile collector format. Durations are exported as httptap_request_duration_seconds gauges with host, step and phase labels, next to httptap_request_success and httptap_last_run_timestamp_seconds; paths and query strings are never labels.

httptap --prometheus /var/lib/node_exporter/httptap.prom https://httpbin.io/get

--otlp ENDPOINT

Export the run as one OpenTelemetry trace: a root span, one span per request step and child spans for DNS, connection, TLS, server wait, and transfer phases. Install the optional dependency first:

pip install 'httptap[otel]'
httptap --otlp http://localhost:4318/v1/traces https://httpbin.io/get

--slo KEY=MS[,KEY=MS...], --slo-file PATH

Check the final successful step against per-phase latency budgets. On violation httptap still renders the full report but exits with code 4 so the result can gate CI jobs, cron probes, or Kubernetes readiness checks.

httptap --slo total=500,ttfb=200 https://httpbin.io/get

# One threshold per line; inline values override file values.
httptap --slo-file slo.txt --slo total=1000 https://httpbin.io/get

Supported keys: dns, connect, tls, ttfb, wait, xfer, total. See the dedicated SLO Threshold Checking page for the full specification, exit-code precedence, and CI/cron recipes.

-f, --fail

Exit with code 22 when any completed request returns HTTP 4xx or 5xx, while still rendering the full timing report and writing --json output. Network and TLS failures keep their existing higher-priority exit codes.

httptap --fail https://httpbin.io/status/500

--version

Display the httptap version and exit.

httptap --version

HTTP Methods

httptap supports all standard HTTP methods:

  • GET - Retrieve resource (default when no --data is provided)
  • POST - Create/submit resource (auto-selected when --data is provided)
  • PUT - Replace resource
  • PATCH - Partially update resource
  • DELETE - Remove resource
  • HEAD - Get headers only
  • OPTIONS - Query allowed methods

Method Selection Logic

  1. Explicit method: --method always takes precedence
  2. Auto-POST: When --data is present without --method, defaults to POST
  3. Default GET: Without --data or --method, uses GET

Examples by Use Case

API Testing:

# Create resource
httptap --data '{"title": "New Post"}' https://httpbin.io/post

# Update resource
httptap --method PUT --data '{"title": "Updated"}' https://httpbin.io/put

# Partial update
httptap --method PATCH --data '{"status": "published"}' https://httpbin.io/patch

# Delete resource
httptap --method DELETE https://httpbin.io/delete

Health Checks:

# Quick check (headers only)
httptap --method HEAD https://httpbin.io/status/200

# Full response
httptap https://httpbin.io/status/200

Request Flow

Every httptap request follows these phases:

  1. DNS Resolution - Domain name lookup
  2. TCP Connect - Establish TCP connection (through an HTTP CONNECT proxy: connect to the proxy and open the tunnel)
  3. TLS Handshake - Negotiate secure connection (HTTPS only)
  4. Server Wait - Time between request sent and first response byte
  5. Body Transfer - Download response body

Understanding Output

Rich Mode (Default)

The default rich output displays a waterfall table with:

  • Phase name and duration
  • Visual progress bar
  • Network details (IP, TLS version, certificate info)
  • Response metadata (status, size, Server header, redirect target)

Timing Breakdown

  • DNS (ms) - Time to resolve domain to IP address
  • Connect (ms) - Time to establish TCP connection; through an HTTP CONNECT proxy it also covers the CONNECT round-trip, so the tunnel setup is not counted as server wait. When the host has several addresses and the first ones fail, the time spent on them is also counted here and in Total (like curl's time_connect)
  • TLS (ms) - Time for TLS handshake (HTTPS only)
  • TTFB (ms) - Time to first byte (includes server processing)
  • Transfer (ms) - Time to download response body
  • Total (ms) - End-to-end request duration

Network Information

  • IP Address - Resolved IP address and family (IPv4/IPv6)
  • TLS Version - Protocol version (TLS 1.2, TLS 1.3)
  • Cipher Suite - Negotiated cipher suite
  • Certificate CN - Common Name from server certificate
  • Certificate Expiry - Days until certificate expires

Examples

Basic Health Check

httptap https://httpbin.io/status/200

API Request with Authentication

httptap \
  -H "Authorization: Bearer ${API_TOKEN}" \
  -H "Accept: application/json" \
  https://httpbin.io/bearer

Follow Redirect Chain

httptap --follow https://httpbin.io/redirect/3

Export for Analysis

httptap --json analysis.json --follow https://httpbin.io/redirect/2

Log to File

httptap --metrics-only https://httpbin.io/delay/1 >> api-latency.log

What's Next?