Skip to content

Output Formats

httptap supports multiple output formats to suit different use cases, from interactive troubleshooting to automated scripting.

Rich Mode (Default)

The default output format uses the Rich library to display a beautiful waterfall table in your terminal.

httptap https://httpbin.io

Features

  • Colorized output with syntax highlighting
  • Visual progress bars for timing phases
  • Structured tables for easy reading
  • Network details including IP, TLS version, and certificate info
  • Response metadata showing status, body size, the Server header, and the redirect target

When to Use

  • Interactive debugging sessions
  • Visual inspection of request performance
  • Presentation of timing data to stakeholders

Compact Mode

One human-readable line per step, designed for terminal logs and redirect-chain tracing.

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

Example 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

Features

  • Single line per step — HTTP status first, then method and URL, then per-phase timings, then human-readable body size.
  • Timings carry ms suffix so they read naturally alongside prose log entries.
  • Response size is formatted with the appropriate unit (B, KB, MB).
  • Redirect summary table is still printed after the per-step lines so the overall shape of the chain stays visible.

When to Use

  • Append to log files
  • Quick performance comparisons
  • CI / CD pipeline output where you still want to see the URL and status
  • Terminal-friendly summaries when the full waterfall is too noisy

Metrics-Only Mode

Raw metrics without formatting, optimized for parsing by other tools.

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

Example 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

Features

  • Machine-parseable format
  • Complete metrics including network details
  • Consistent structure for easy extraction
  • No colors or formatting characters
  • Escaped values use percent-encoding when needed so every metric remains a single key=value token.

When to Use

  • Scripting and automation
  • Data collection for analysis
  • Integration with monitoring tools
  • Parsing with awk/grep/sed

Combined with --compact

--metrics-only takes precedence over --compact. Passing both flags still emits the machine-readable key=value line (so existing scripts keep working) and prints a warning to stderr that --compact was ignored.

Parsing Examples

# Extract TTFB values
httptap --metrics-only https://httpbin.io/delay/1 | grep -oP 'ttfb=\K[0-9.]+'

# Get all timing metrics
httptap --metrics-only https://httpbin.io/get | \
  awk '{for(i=1;i<=NF;i++){if($i ~ /=/) print $i}}'

JSON Export

Full request data exported as structured JSON for comprehensive analysis.

httptap --json output.json https://httpbin.io

Pass - as the path to write the JSON to stdout (the regular report is suppressed); status messages go to stderr:

httptap --json - https://httpbin.io | jq '.steps[0].timing'

JSON Structure

{
  "schema_version": 1,
  "httptap_version": "0.6.3",
  "timestamp": "2026-09-18T08:00:00Z",
  "initial_url": "https://httpbin.io",
  "total_steps": 1,
  "steps": [
    {
      "url": "https://httpbin.io",
      "step_number": 1,
      "request": {
        "method": "GET",
        "headers": {},
        "body_bytes": 0
      },
      "timing": {
        "dns_ms": 8.947,
        "connect_ms": 96.977,
        "tls_ms": 194.566,
        "ttfb_ms": 445.951,
        "total_ms": 447.344,
        "wait_ms": 145.461,
        "xfer_ms": 1.392,
        "is_estimated": false
      },
      "network": {
        "ip": "44.211.11.205",
        "ip_family": "IPv4",
        "http_version": "HTTP/2.0",
        "tls_version": "TLSv1.2",
        "tls_cipher": "ECDHE-RSA-AES128-GCM-SHA256",
        "cert_cn": "httpbin.io",
        "cert_days_left": 41,
        "cert_sans": ["httpbin.io", "*.httpbin.io"],
        "cert_issuer": "WE1",
        "cert_serial": "05BB0F0AA84C8FECE0E72D805BA7A5D2B",
        "cert_not_before": "2026-08-01T00:00:00+00:00",
        "cert_not_after": "2026-10-30T00:00:00+00:00",
        "tls_verified": true,
        "tls_custom_ca": false,
        "proxy_url": null,
        "proxy_source": null
      },
      "response": {
        "status": 200,
        "bytes": 389,
        "content_type": "application/json",
        "server": "gunicorn/19.9.0",
        "date": "2026-09-18T07:59:59+00:00",
        "location": null,
        "headers": {
          "date": "Fri, 18 Sep 2026 07:59:59 GMT",
          "content-type": "application/json",
          "server": "gunicorn/19.9.0"
        }
      },
      "error": null,
      "note": null,
      "redirect_limit_reached": false,
      "proxy": null
    }
  ],
  "summary": {
    "total_time_ms": 447.344,
    "final_status": 200,
    "final_url": "https://httpbin.io",
    "final_bytes": 389,
    "errors": 0
  }
}

Field Reference

The top-level metadata identifies the report format and when it was produced. Consumers should use schema_version to select compatible parsing logic.

Field Type Description
schema_version integer Version of the JSON report format. The current version is 1.
httptap_version string Version of httptap that generated the report.
timestamp string Export creation time in RFC 3339 UTC format, for example 2026-09-18T08:00:00Z.
initial_url string URL passed to httptap before redirects.
total_steps integer Number of entries in steps.
steps array Per-request measurements, including each followed redirect.
summary object Aggregate values for the export.

Timing values ending in _ms are milliseconds. Request and response body sizes are bytes. Response sizes (bytes, final_bytes) count the body as received on the wire, before Content-Encoding decoding, like curl's size_download. Certificate and response dates are ISO 8601/RFC 3339 timestamps when available. See the example above for the nested steps and summary structure.

Credentials are masked: the password (or a bare token) in the userinfo of step urls, response.location, the Location and Content-Location headers, and network.proxy_url is replaced with ****, and sensitive headers such as Authorization and Set-Cookie are masked as well.

network.tls_custom_ca is true when --cacert was used and false otherwise. A step's redirect_limit_reached is true when --follow stopped at the 10-redirect limit on that step; such a step also counts toward summary.errors.

A step with an error keeps the response it had already received: if the status line and headers arrived before the failure (for example, the body stalled past -m/--max-time), response.status, response.headers and response.bytes (the body bytes received so far) are filled in. A step that failed before the status line has response.status: null. The exit code is still the network error code (75).

Features

  • Complete data export of all phases
  • Structured format for easy parsing
  • Redirect chain support with multiple steps
  • Metadata preservation (headers, timestamps)
  • Error information when requests fail

When to Use

  • Post-processing analysis
  • Integration with data pipelines
  • Long-term performance tracking
  • Detailed debugging sessions
  • Sharing results with team members

Processing Examples

Using jq to extract specific fields:

# Get total time
jq '.summary.total_time_ms' output.json

# Extract all TTFB values
jq '.steps[].timing.ttfb_ms' output.json

# Get certificate expiration
jq '.steps[0].network.cert_days_left' output.json

# Filter failed requests
jq 'select(.summary.errors > 0)' output.json

HAR Export

--har PATH writes the analysed request chain as an HTTP Archive (HAR) 1.2 document, the format that browser DevTools and HAR viewers read. Pass - to write it to stdout (the regular report is suppressed); status messages go to stderr:

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

--har and --json can be combined, but only one of them can write to stdout. If the file cannot be written, httptap exits with code 73, as it does for --json.

To open the file in Chrome DevTools, open the Network panel and use Import HAR file (the upload arrow in the toolbar), or drag the file onto the panel. Firefox DevTools offers Import HAR in the Network panel's settings menu.

HAR Structure

A trimmed example for a single HTTPS request:

{
  "log": {
    "version": "1.2",
    "creator": { "name": "httptap", "version": "0.7.0" },
    "pages": [
      {
        "startedDateTime": "2026-10-06T08:00:00.000+00:00",
        "id": "page_1",
        "title": "https://httpbin.io/get",
        "pageTimings": { "onContentLoad": -1, "onLoad": -1 }
      }
    ],
    "entries": [
      {
        "pageref": "page_1",
        "startedDateTime": "2026-10-06T08:00:00.000+00:00",
        "time": 448.2,
        "request": {
          "method": "GET",
          "url": "https://httpbin.io/get",
          "httpVersion": "HTTP/2.0",
          "cookies": [],
          "headers": [],
          "queryString": [],
          "headersSize": -1,
          "bodySize": 0
        },
        "response": {
          "status": 200,
          "statusText": "OK",
          "httpVersion": "HTTP/2.0",
          "cookies": [],
          "headers": [{ "name": "content-type", "value": "application/json; charset=utf-8" }],
          "content": { "size": 389, "mimeType": "application/json; charset=utf-8" },
          "redirectURL": "",
          "headersSize": -1,
          "bodySize": 389,
          "_transferSize": 389
        },
        "cache": {},
        "timings": {
          "blocked": -1,
          "dns": 8.9,
          "connect": 291.6,
          "send": 0,
          "wait": 146.4,
          "receive": 1.3,
          "ssl": 194.6
        },
        "serverIPAddress": "44.211.11.205",
        "_tls": {
          "version": "TLSv1.2",
          "cipher": "ECDHE-RSA-AES128-GCM-SHA256",
          "certCN": "httpbin.io",
          "certIssuer": "Amazon RSA 2048 M03",
          "certDaysLeft": 200,
          "verified": true
        }
      }
    ]
  }
}

The document contains:

  • One page for the run. Its title is the URL passed to httptap; the page load timings do not apply and are -1.
  • One entry per request, in redirect-chain order, each pointing to the page through pageref. httptap measures durations rather than wall-clock start times, so the entries are laid out back to back and the last one ends when the file is written.
  • Request: method, URL, negotiated HTTP version, the headers httptap was given (-H and the Content-Type derived from --data), the parsed query string and bodySize. The request body itself is never written.
  • Response: status, HTTP version, headers, redirectURL (the Location header), content.mimeType (the Content-Type, or x-unknown when absent) and the body size. httptap does not decode the body, so content.size and bodySize are the size as received on the wire, before Content-Encoding decoding. The body text is never included.
  • serverIPAddress: the address httptap connected to.

statusText is the standard reason phrase for the status code (empty for unknown codes), and headersSize is -1: httptap does not record the reason phrase or header sizes sent on the wire. The cookies arrays are empty; Cookie and Set-Cookie appear, masked, in the headers.

Timings

HAR field httptap value Notes
blocked -1 Not measured.
dns dns_ms
connect connect_ms + tls_ms Includes the TLS handshake, as the HAR specification requires.
ssl tls_ms HTTPS only, -1 for plain HTTP. Already part of connect.
send 0 Not measured separately; sending the request is part of wait.
wait wait_ms Server processing, up to the first response byte.
receive xfer_ms Body transfer.

time is the sum of blocked, dns, connect, send, wait and receive, leaving out -1 values. ssl is not added again because connect already contains it. Values are milliseconds rounded to three decimals. When the connection and TLS phases were estimated rather than measured (is_estimated in the JSON export), timings carries "_estimated": true.

Failed Requests

A step that failed is still exported. Its response.status is 0, or the status that had already arrived (for example, when the body stalled past -m/--max-time), and the error message is in response._error, where Chrome DevTools reads it when importing a HAR. Because a failed step has no measured phases, its dns, connect and ssl are -1, send, wait and receive are 0, and time is 0.

Custom Fields

The HAR specification reserves fields starting with _ for extensions. httptap adds:

Field Location Contents
_tls entry version, cipher, certCN, certIssuer, certDaysLeft, verified; HTTPS only.
_proxy entry url (credentials masked) and source of the proxy the request went through.
_redirectLimitReached entry true when --follow stopped at the 10-redirect limit on this step.
_estimated timings true when the connection and TLS timings were estimated.
_transferSize response Body bytes received on the wire, -1 when no response arrived.
_error, _errorKind response Error message and its kind (network or internal) for a failed step.

Redaction

The HAR export applies the same masking as the JSON export: the password (or a bare token) in URL userinfo is replaced with **** in request URLs, the page title, redirectURL, the Location and Content-Location headers and the proxy URL, and sensitive headers such as Authorization, Cookie and Set-Cookie are masked.

Warning

Paths and query strings are kept, and HAR files are often attached to bug reports. Review a HAR file for sensitive data before sharing it.

Prometheus Textfile Export

Write a node_exporter textfile collector report with --prometheus PATH:

httptap --prometheus /var/lib/node_exporter/httptap.prom https://api.example.com/health

The file is written atomically. Every sample carries a host label (hostname only) and the redirect-chain step, so several probes can share one textfile directory. Exported gauges:

Metric Extra labels Meaning
httptap_request_success 1 if the step completed, 0 on a network/TLS error
httptap_request_duration_seconds phase dns, connect, tls, ttfb, wait, xfer, total
httptap_response_status_code HTTP status of the step
httptap_response_body_size_bytes Response body size on the wire
httptap_last_run_timestamp_seconds Unix time the file was written (host only)

Failed steps export only httptap_request_success 0, so an outage never looks like a fast response. Paths and query strings are never used as labels.

OpenTelemetry Export

--otlp ENDPOINT sends OTLP/HTTP traces. Install the optional extra first:

pip install 'httptap[otel]'
httptap --otlp http://localhost:4318/v1/traces https://api.example.com/health

A run is exported as one trace: an httptap.analysis root span with one http.request span per redirect step, laid out one after another, and child spans for the DNS, connection, TLS, server wait and transfer phases. Delivery is bounded by -m/--max-time; a collector error is reported as a warning and does not change the exit code. The export omits the full request URL, so query parameters are not sent to the collector.

Redirect Chains

When using --follow, all output formats include data for each step in the redirect chain.

Rich Mode

Shows a summary table with totals for the entire chain.

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

Compact Mode

Outputs one line per redirect step, followed by the redirect chain summary table.

httptap --follow --compact https://httpbin.io/redirect/2

Output:

Step 1: 302 GET https://httpbin.io/redirect/2 | dns=8.9ms connect=97.0ms tls=194.6ms ttfb=446.0ms total=447.3ms | 0 B
Step 2: 302 GET https://httpbin.io/relative-redirect/1 | dns=2.7ms connect=97.5ms tls=194.0ms ttfb=400.2ms total=400.6ms | 0 B
Step 3: 200 GET https://httpbin.io/get | dns=2.6ms connect=97.4ms tls=197.3ms ttfb=403.2ms total=404.0ms | 389 B

JSON Export

Includes all steps in the steps array with complete timing and metadata.

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

Combining Options

Output format options can be combined with other flags:

# Follow redirects with compact output
httptap --follow --compact https://httpbin.io/redirect/2

# Export redirect chain to JSON with metrics display
httptap --follow --json chain.json --metrics-only https://bit.ly/example

Note

When both --json and display modes (--compact, --metrics-only) are used together, the display mode shows on stdout while JSON is written to the file.


SLO Threshold Overlay

--slo KEY=MS[,KEY=MS...] augments every output mode with a pass/fail verdict evaluated against the final successful request.

  • Rich mode — a framed panel is printed after the waterfall. The border is green for pass, red for fail, and each violation is listed with actual, threshold, and overrun in milliseconds.
  • Compact mode — behaves as Rich mode above; the SLO panel is still printed after the one-line step summaries.
  • Metrics-only — the line for the final successful step gains slo=pass or slo=fail slo_violations=<keys> tokens. Intermediate redirect steps remain unchanged.
  • JSON — summary.slo contains pass, thresholds_ms, and violations[] (each with key, threshold_ms, actual_ms, delta_ms). Absent when --slo is not supplied.

A violation makes httptap exit with code 4 while still rendering the full output, so the evidence is preserved for post-mortem.

See the dedicated SLO Threshold Checking page for the specification grammar, evaluation rules, exit-code precedence, and CI / cron recipes.


What's Next?