Skip to content
Login

Traffic and metrics

Every connection HLE runs is measured, and every one of them is measured the same way: a chart of traffic over time, and three numbers above it. Whether you are looking at a tunnel, a webhook receiver, an agent, or a firepuncher forward, the widget is the same and the axes mean the same thing.

Where to find it

You wantOpen
Everything on the accountDashboard → Overview
One tunnel or webhook receiverits page, from the connections list
One agent, summed over its endpointsAgents → the agent
An agent’s TCP forwardsFirepuncher, on the agent

Each view offers 24 hours, 7 days and 30 days.

What the three numbers mean

The metric strip changes with what you are looking at, because the honest answer is different for each. Nothing is averaged across things that cannot be meaningfully averaged.

ViewMetrics
AccountRequests · Traffic · WS streams
TunnelRequests · Traffic · Latency
Webhook receiverDeliveries · Traffic · Latency
FirepuncherForwards · Traffic · Median length

Two deliberate omissions:

  • The account view has no latency. Latency is a property of a connection. Averaging it across every tunnel on an account produces a number that describes nothing.
  • Firepuncher counts forwards, not requests. A forward is a TCP session, so its useful second dimension is how long it lasted, not how quickly it replied.

A forward that is still open counts, and its traffic is included as the agent relays it — an SSH session held open for hours would otherwise show as nothing at all until you closed it. When something is open you get a fourth number, Open now, which is what explains a traffic figure that keeps climbing while the forward count and the median sit still. The median covers finished forwards only: an open session’s age is not its length.

For a forward, in means bytes travelling toward the target service and out means bytes coming back — the same direction convention as a tunnel’s request and response bodies, so bars point the same way on every chart.

Webhook outcomes

A webhook receiver’s chart splits deliveries by what happened to them: delivered, failed, rate limited, rejected. This is the fastest way to tell “the provider stopped sending” from “we turned it away”.

Outcomes are recorded hourly. On the 30-day view they are absent rather than approximated, because the coarser table that backs long ranges does not record them — an empty outcome breakdown at 30 days is not a sign that nothing failed.

Resolution and retention

RangeBucketSource
24 hours1 hourhourly rows
7 days6 hourshourly rows
30 days24 hoursdaily rollups

Per-tunnel hourly rows are purged after two weeks, so ranges longer than 7 days are served from the rollups. The account’s own hourly table is never purged, which is why the account chart stays hour-resolution at every range.

Reading it from a script

The dashboard has no privileged path — it calls the same endpoint you can.

Terminal window
curl -s -H "Authorization: Bearer $HLE_API_KEY" \
"https://hle.world/api/metrics/series?kind=account&range=7d"
GET /api/metrics/series
kind=account | tunnel | agent | firepuncher (required)
subdomain=<subdomain> (required for kind=tunnel)
agent_id=<id> (required for agent, firepuncher)
range=24h | 7d | 30d (default 24h)

The response is one shape for every kind:

{
"kind": "tunnel",
"range": "24h",
"bucket_hours": 1,
"hourly": true,
"points": [
{ "t": "2026-08-13T09:00:00Z", "requests": 412, "ws_streams": 3,
"bytes_in": 91233, "bytes_out": 8812301, "latency_ms": 47,
"delivered": 0, "failed": 0, "rate_limited": 0, "rejected": 0 }
],
"metrics": [
{ "key": "requests", "label": "Requests", "unit": "count", "value": 9812 },
{ "key": "traffic", "label": "Traffic", "unit": "bytes", "value": 40122333 },
{ "key": "latency", "label": "Latency", "unit": "ms", "value": 47 }
]
}

metrics is what the strip shows, already labelled — render it rather than hard-coding names, so a view that gains a metric does not need your script changed. A value of null means “no data in this range”, not zero.

The connection log

The chart says how much; the log says who. Every request that met a tunnel’s access rules — and every one that did not — is recorded with the client address, which rule matched, and the outcome. Filter it by event type, tunnel and date range from Activity, or read it from /api/logs.

Retention follows your plan: 7 days on Free, up to 30 on PAYG.

When you need the bodies

Metrics deliberately contain no payloads. When a specific tunnel is misbehaving in a way counters cannot explain, HLE has a per-tunnel capture mode that records full requests and responses for a bounded window.

It is administrator-initiated and off by default — capture is a privacy-sensitive operation, not something a chart turns on. If you are debugging a tunnel on hle.world and need it, ask; if you run your own relay, see debug_capture.py.

  • Agent — one process, many endpoints
  • Firepuncher — TCP forwards, and their forward log
  • Webhooks — receivers, rate limits and delivery outcomes