# httptap: see the HTTP and HTTPS requests any Linux program makes

> httptap wraps a command, intercepts its HTTP and HTTPS traffic in a private network namespace, and prints each request and response. It is a Linux-only Go binary for debugging what a CLI tool or script actually sends.

**monasticacademy/httptap** — View HTTP/HTTPS requests made by any Linux program

- Repository: https://github.com/monasticacademy/httptap
- Website: https://www.monasticacademy.org
- Stars: 4,182 · Forks: 66
- Language: Go
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/monasticacademy-httptap

## What httptap is for, and who it is for

Most network debugging tools assume you control the client. You add a proxy flag, set an environment variable, or patch the code to log its requests. That breaks down when the program is a compiled binary, a vendor CLI, or a shell script that builds its own HTTP client and ignores HTTPS_PROXY. httptap takes the opposite approach: it runs the program inside a network namespace it creates, and observes the traffic from outside the program's control.

The audience is narrow and specific. You are on Linux. You have a command that talks to an API and you want to know which endpoints it calls, in what order, and with what status codes. The README's examples are exactly this shape: running curl, a short Python requests script, gcloud compute instances list, and kubectl get all, and reading the request and response lines httptap prints alongside the program's own output. The tool prints summaries, not full bodies: the README shows lines like a GET line and a response line with a status code and a byte count.

It is not a general packet analyzer and not a replacement for reading source code. If you have the source and can add logging, that is usually faster. httptap earns its place when the source is unavailable or the client is opaque.

## How the interception works: namespaces, a TUN device, and gVisor

The repository layout tells most of the story. There are files named device.go, dns.go, tcp.go, udp.go, proxy.go, mux.go, and context.go at the top level, and go.mod pulls in gvisor.dev/gvisor, github.com/songgao/water (a TUN/TAP library), github.com/vishvananda/netlink and netns, github.com/miekg/dns, and github.com/google/gopacket. Topics on the repository include gvisor, linux-network-namespace, tun-device, and man-in-the-middle.

The README states the design intent plainly: httptap does not need root, does not set up a daemon, does not create iptables rules, and does not change your routing table. It uses Linux network namespaces, which is why the project says porting to other operating systems would be very difficult. The command you pass after -- runs in that namespace, and its traffic is captured there rather than on your host interfaces.

For HTTPS, the tool has to terminate TLS to read the request line, which is why man-in-the-middle appears as a topic and why the go.mod includes a certificate library (github.com/joemiller/certin) and a PKCS#12 library. The Makefile has a setup-tls target that generates a test CA and a localhost certificate, which is how the project's own tests exercise the HTTPS path. The practical consequence for you: httptap presents its own certificate to the wrapped program, so a client that pins certificates or refuses unknown CAs will fail or refuse to connect.

## Installing httptap and running a first capture

The README gives two install paths. The first downloads a prebuilt static binary from the latest release, choosing the archive by CPU architecture. Run it in a shell; you should end up with an httptap executable in the current directory.

```bash
curl -L https://github.com/monasticacademy/httptap/releases/latest/download/httptap_linux_$(uname -m).tar.gz | tar xzf -
```

If you have Go 1.23.1 or later, the second path installs from source into your Go binary directory:

```bash
go install github.com/monasticacademy/httptap@latest
```

On Ubuntu 23.10 and later, the README says you must first relax the kernel restriction on unprivileged user namespaces, or httptap will not be able to create the namespace it needs. The README notes the same may apply to other distributions that disabled unprivileged user namespaces by default.

```bash
sudo sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
```

With that in place, the first real use is to wrap a command. The README's quickstart runs curl against a site and shows a 302 response printed by httptap, with curl's own output suppressed by -o /dev/null. The arrow lines are httptap's; anything else is the wrapped program's output.

```bash
httptap -- curl -s https://buddhismforai.sutra.co -o /dev/null
```

Adding -L to the curl invocation shows the follow-up request that curl makes after the redirect, which is the point of the tool: you see the second request that the program never told you about. Two flags appear in the README for non-standard ports. --http 8080 and --https 8443 are used in the Makefile's localhost tests, and --https 443 6443 appears in the kubectl example, where 6443 is the Kubernetes API port. The --print-dns flag, also shown in the Makefile, adds DNS lookups to the output.

## Where httptap breaks down

The clearest limitation is the platform. The README says httptap only runs on Linux at present and that the Linux-specific system calls, in particular network namespaces, would make it very difficult to port. If your debugging happens on a developer laptop running macOS, this tool is not an option, and no amount of configuration changes that.

The second limitation is the namespace restriction itself. On Ubuntu 23.10 and later, and possibly on other distributions that disabled unprivileged user namespaces, you must change two kernel sysctl values before httptap works at all. That is a system-wide setting. The README acknowledges this and says the author is investigating shipping an AppArmor profile to avoid it, but as of the documentation that work is not done. On a locked-down machine where you cannot run sudo sysctl, httptap is unusable.

The third is TLS interception. Because httptap must terminate TLS to read request lines, it sits between the program and the server with its own certificate. Programs that pin certificates, verify against a fixed CA bundle, or use mutual TLS will not work cleanly through it. The README does not document a bypass for certificate pinning, and the go.mod's inclusion of a PKCS#12 library suggests client-certificate handling exists, but the README does not describe a workflow for it.

Finally, the output is summaries. The README shows request lines, response lines, status codes, and byte counts. It does not show a documented mode for dumping full request or response bodies, so if you need payload contents, httptap is the wrong tool and a packet capture with a decrypting proxy is the right one.

## How httptap differs from mitmproxy and strace

The obvious alternative is mitmproxy. Both intercept TLS and both let you inspect HTTP traffic from a client you did not write. The difference is in how the client is redirected. mitmproxy is a proxy: the client has to be pointed at it, usually through HTTP_PROXY and HTTPS_PROXY environment variables or an explicit --proxy flag. That works well for browsers and for well-behaved HTTP libraries, and it gives you a full interactive UI, request replay, and scripted addons. It fails for the exact case httptap was built for, a program that ignores proxy variables or speaks a protocol the proxy does not handle.

httptap inverts that. There is no proxy address to configure because the wrapped process runs in a namespace where its traffic is captured regardless of what the program does. The README's claim that it will not affect other processes on the same system is the payoff of that design. The cost is that you cannot attach it to an already-running process, and you get summary lines rather than an interactive session.

The other comparison is strace, which shows syscalls including sendto and recvfrom. strace works on any Linux program without a namespace, but it gives you byte buffers, not parsed HTTP. You end up reconstructing request lines and headers by hand, and TLS payloads are ciphertext. httptap's value is that it does the parsing and the TLS termination for you, at the price of the namespace and sysctl requirements strace does not have.

## Maintenance, licence, and what a v0.1.x release implies

The repository is not archived, and the last push was on 2026-06-15. The most recent tagged release listed is v0.1.1 from 2025-02-26, preceded by v0.1.0 the same day and v0.0.8 on 2025-02-03. That gap between the latest tag and the latest push is worth noting: work has continued on the main branch since the last release, so installing @latest with go install may give you code that is ahead of the newest tagged binary. If you need reproducibility, pin to a release artifact rather than tracking the branch.

The version number itself is a signal. A 0.1.x line means the author has not committed to interface stability, so flags and output formatting can change between releases. The README already documents one environment-dependent behaviour (the Ubuntu sysctl requirement) that the author says will be updated as more is learned, which suggests the platform notes are still moving.

The licence is MIT, which is permissive and places few obligations on how you redistribute or modify the code. That is a statement about the licence text, not legal advice; if you are embedding httptap in a product, have your own counsel review it. The dependencies matter more in practice than the httptap licence itself: gVisor, quic-go, and the netlink and water libraries each carry their own terms, and go.mod lists them explicitly.

## Conclusion

Adopt httptap when you need to see the wire traffic of a CLI tool you cannot modify, especially one that ignores proxy environment variables. Skip it on macOS, Windows, or anywhere unprivileged user namespaces are disabled and you cannot change sysctl. Before relying on it, confirm on your own distribution that the two sysctl keys the README lists are settable, and check whether the traffic you care about is HTTP/2 or QUIC, since the README only demonstrates HTTP/1.1-style request and response lines.

## FAQ

### Does httptap need root to capture traffic?

The README states that you do not need to be the root user to run httptap, and that it does not create iptables rules or change your routing table. There is a --user flag shown in the Makefile's test-root target, which runs the wrapped command as a specified user inside the namespace.

### Why does httptap fail on Ubuntu 23.10 and later?

The README says Ubuntu 23.10 and later restrict unprivileged user namespaces, and httptap needs them to create the namespace it runs your command in. It documents two sysctl commands to disable that restriction, and notes the same may be needed on other distributions that disabled unprivileged user namespaces by default.

### Can httptap show traffic on a non-standard port like 6443?

Yes. The README's kubectl example uses --https 443 6443 to cover both the standard HTTPS port and the Kubernetes API port, and the Makefile tests use --http 8080 and --https 8443 for localhost. The flags take the ports you want treated as HTTP or HTTPS.

## Sources

- [License: MIT](https://github.com/monasticacademy/httptap/blob/main/LICENSE)
- [monasticacademy/httptap on GitHub](https://github.com/monasticacademy/httptap)
- [Project website](https://www.monasticacademy.org)
- [README](https://github.com/monasticacademy/httptap/blob/main/README.md)
- [Releases](https://github.com/monasticacademy/httptap/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/monasticacademy-httptap
