How WireLens captures traffic

What happens between your app and the server on Mac and on iPhone, and what WireLens can and cannot see.

Mac iPhone and iPad

WireLens sits between your app and the network. The way it gets there differs by platform, because macOS and iOS allow different things, but what it records is the same.

On the Mac: a proxy inside the app#

  • WireLens runs an HTTP proxy inside the app, listening on 127.0.0.1:9090 by default.
  • With the This Mac capture scope, macOS's HTTP and HTTPS proxy settings point at that listener, so every app that honours the system proxy sends its traffic through WireLens. Browsers, most native apps and anything built on URLSession do.
  • Plain HTTP is read, forwarded and recorded as it passes.
  • HTTPS starts as a request to open a tunnel (CONNECT host:443). For a host that is not on your SSL Proxying Include list, WireLens passes the tunnel through untouched and records it as a CONNECT row. For a host that is, WireLens completes TLS itself with a certificate for that host, signed by your WireLens root, reads the exchange, and opens its own TLS connection to the server.
  • WireLens's own connections to servers go straight out to the network, never back through the system proxy.
  • Tools that ignore the system proxy, such as many command line tools, runtimes and containers, are pointed at the listener with a couple of environment variables. See Client setup.
  • Each flow is attributed to the app that made it, by matching the local connection to the process that owns it. No network or kernel extension is involved; a signed helper that you approve once changes the proxy settings.

On iPhone and iPad: a local VPN#

iOS does not let one app redirect other apps through a proxy, so WireLens uses a packet tunnel, the same mechanism VPN apps use, which runs entirely on the device:

  • When capture starts, iOS sends the device's IPv4 and IPv6 traffic, and its DNS, into WireLens's tunnel on the phone.
  • Web traffic on ports 80 and 443 goes to WireLens's proxy on the phone. On other ports WireLens recognises HTTP and TLS and handles them the same way; anything else passes through.
  • WireLens connects to the real servers from the phone. There is no WireLens server in the path, and nothing is sent to us.
  • With Block QUIC on, WireLens drops HTTP/3's UDP traffic so apps fall back to TCP, where it can decrypt them.
  • iOS limits how much memory a network extension may use, so WireLens keeps very large bodies truncated and bounds how many connections it decrypts at once, which keeps the phone's network responsive.

What WireLens can and cannot see#

TrafficWhat you get
Plain HTTPEverything
HTTPS, host on the Include list, root trustedEverything
HTTPS, host not on the Include listHost, port, timing and bytes, as a CONNECT row
Apps that pin their certificatesThe tunnel only. Decrypting them makes the app refuse the connection.
HTTP/3 over QUICNothing while it stays on QUIC. Block QUIC and it falls back to TCP.
Mac apps that ignore the system proxyNothing until they are pointed at WireLens

A status column that does not guess#

When an exchange fails, WireLens records what actually happened: the connection was refused, the response was cut short, a breakpoint aborted it, the Block List stopped it. It never fills in a status the app did not receive, so a failure never passes for a success, and a success never hides a failure. gRPC and GraphQL get the same treatment for the failures they report inside a 200.

Something here is unclear, or wrong for your setup? Contact support or write to support@wirelens.app.