mitmproxy 12.2.3: a Python 3.12 floor, a curses console, and two dependencies left unpinned on purpose
GitHub describes it as An interactive TLS-capable intercepting HTTP proxy for penetration testers and software developers.. The repository metadata lists Python as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- mitmproxy is an interactive, SSL/TLS-capable intercepting proxy with three front ends over one core, built for penetration testers and software developers. The README is short, so the useful detail lives in pyproject.toml: a Python 3.12 floor with CPython only, a curses terminal expectation baked into the console front end, a version string that is not in the file at all, and a dependency list where almost everything has a hard ceiling and the certificate store and the TLS library deliberately do not.
- Who is it for?
- mitmproxy fits a reader who needs to see and edit HTTP/1, HTTP/2 and WebSocket traffic in a controlled environment, who has Python 3.12 or newer on CPython, and who controls the trust store rather than expecting a fixed one. It does not fit a reader on an older system interpreter or on PyPy, a reader whose tooling needs to read a version string out of pyproject.toml, or a reader who needs the same installed versions of certifi and cryptography across machines.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three front ends over one core, and only the console one needs a terminal
The README names three executables and one sentence each. mitmproxy is an interactive, SSL/TLS-capable intercepting proxy with a console interface for HTTP/1, HTTP/2 and WebSockets. mitmdump is the command-line version of mitmproxy, described with the memorable phrase think tcpdump for HTTP. mitmweb is a web-based interface for mitmproxy. The classification that matters is in pyproject.toml, where the project declares Environment :: Console :: Curses alongside Operating System entries for MacOS, POSIX and Windows. Consequence: the console front end expects a real terminal, so a continuous integration job, a container exec without a tty, or a plain pipe gives you a degraded interface and you should reach for mitmdump or mitmweb instead. The web interface is also a separate build artefact rather than something served out of the Python package, because the frontend lives in a top-level web/ directory alongside the mitmproxy/ package rather than inside it.
requires-python is 3.12, and CPython is the only implementation declared
Three declarations set the support floor. requires-python is >=3.12. The classifiers list Programming Language :: Python :: 3 :: Only, then 3.12, 3.13 and 3.14 individually, and Programming Language :: Python :: Implementation :: CPython. Consequence for a Linux workstation: a great many distributions still ship a default interpreter older than 3.12, so a plain system install is not available and you either add a newer interpreter or take a precompiled binary, which is why the project points at its own website for precompiled binaries alongside the documentation. The PyPy case is the sharper one, because declaring a single implementation means nobody has committed to that runtime, so a team standardised on PyPy is outside the declared support surface rather than merely slower on it. The tree reflects the same discipline: a .python-version file pins one interpreter for development and uv.lock records a resolved set, so contributor environments and user environments are pinned differently on purpose.
certifi and cryptography float while almost everything else is nailed to a ceiling
The dependency list is the most opinionated thing in the repository, and it explains itself in comments. A header comment says it is not considered best practice to use install_requires to pin dependencies to specific versions, and then the list pins nearly all of them anyway, with paired bounds such as argon2-cffi from 23.1.0 to 25.1.0, flask from 3.0 to 3.1.3, and h2 from 4.3.0 to 4.4.1, plus exact ceilings on aioquic at 1.2.0, bcrypt at 5.0.0 and h11 at 0.16.0. Two entries are the exception and both say why. certifi is given no upper bound, with the comment that this gets the latest CA bundle. cryptography is given a relaxed upper bound, with the comment that this is to get security fixes. Consequence: the trust store and the crypto backend are the two components allowed to move, so a resolver refresh or an install with a newer release can change your anchors and your TLS backend without any change in the mitmproxy version you asked for, and those are exactly the two pieces that alter interception behaviour. If you need identical trust across machines, pin them yourself.
A backport marker, a nine-version range, and flask in the core install
Three entries in the same list reward a second look. backports.zstd is pinned from 1.7.0 to 1.7.0 and carries the marker python_version<'3.14', meaning on 3.14 the standard library supplies it and the backport is not installed, so the project is carrying a shim for the versions below its newest classifier while already claiming support for the newest one. argon2-cffi is the widest range in the visible list, spanning from 23.1.0 to 25.1.0, which is a deliberate looseness rather than an oversight given the header comment. And flask sits in the core dependency list next to h11, h2 and Brotli, so the web front end's server library is installed for everyone. Consequence: a deployment that only ever runs mitmdump still pulls a web framework, and an air-gapped install has to mirror a backport package for interpreters below 3.14 as well as the main dependency set.
dynamic = ["version"], so pyproject.toml contains no version to read
The project metadata declares dynamic = ["version"], which means the version string is not written in pyproject.toml and is supplied by the build. Everything else about the manifest is concrete: name mitmproxy, the description, readme pointing at README.md, license as a file reference to LICENSE, Aldo Cortesi as author, Maximilian Hils as maintainer, and the classifier list. Consequence: any automation that reads a version out of pyproject.toml finds nothing. That includes some SBOM and provenance generators, dependency update bots, and any script of your own that wants to record which proxy build produced a capture. The workarounds are the installed distribution metadata or CHANGELOG.md. The release/ directory is the visible machinery behind the dynamic field, and it is also where the difference between a version string and a changelog entry gets resolved, so a pinned install and the human record of what changed are two different places to look.
The newest release is 12.2.3 from May 2026 while the branch was pushed in late September
The release list is uneven in a way that matters for pinning. v12.2.1 shipped on 2025-11-24, v12.2.2 on 2026-04-12, and v12.2.3 on 2026-05-12, so there is roughly a month between the last two and about four and a half months between the first two. The repository is not archived and its default branch was pushed on 2026-09-27, which is about four and a half months after the newest tag, so the default branch carries work that no release has shipped. The classifiers call the project Development Status :: 5 - Production/Stable and Typing :: Typed, so the expectation is a stable product, and the practical reading is that the version you pin is the product. Build on a tag rather than on the branch tip, and check CHANGELOG.md for what a new release changed, because pyproject.toml will not tell you and the docs are published in two channels, stable and dev, which can describe a version you have not installed.
examples/keys.yaml shows that bindings are data you supply, and the docs come in two channels
The extension and configuration surface is visible in four paths. examples/README.md introduces the directory, examples/addons/ holds the project's own addon examples, examples/contrib/ holds community-contributed ones, and examples/keys.yaml is a keymap file sitting directly in the examples tree. Consequence: bindings are treated as data the project expects you to provide rather than a compiled-in default, so a scripted or headless setup has to supply a keymap rather than inherit one, and reading the addons directory is the intended route before writing an addon of your own. Documentation is published twice, with a stable channel and a dev channel under the same docs host, so a tutorial you find may describe behaviour your installed version does not have, and the way to resolve that is to match the tutorial to your version rather than to assume the newest page is right. Questions about usage go to GitHub Discussions rather than the issue tracker, and the site also carries tutorials and the precompiled binaries.
Editorial conclusion
mitmproxy fits a reader who needs to see and edit HTTP/1, HTTP/2 and WebSocket traffic in a controlled environment, who has Python 3.12 or newer on CPython, and who controls the trust store rather than expecting a fixed one. It does not fit a reader on an older system interpreter or on PyPy, a reader whose tooling needs to read a version string out of pyproject.toml, or a reader who needs the same installed versions of certifi and cryptography across machines. Before you pin it, check five things: which front end fits your environment, since the console one is classified as curses and mitmdump and mitmweb are the alternatives; which Python you have, because the floor is 3.12 and the declared implementation is CPython; whether your resolver is allowed to move certifi and cryptography, since those two carry no ceiling or a relaxed one while everything else is nailed; whether you are reading the stable or the dev documentation channel, since both are published; and what changed in the version you are pinning, which CHANGELOG.md records and pyproject.toml does not.
Frequently asked questions
What is MITMProxy for?
It is an interactive, SSL/TLS-capable intercepting proxy with a console interface for HTTP/1, HTTP/2 and WebSockets, and the project description positions it for penetration testers and software developers. It ships three front ends over one core, the interactive console proxy, mitmdump as the command-line version, and mitmweb as a web-based interface, and it also declares topics in security, proxy servers, network monitoring and software testing.
What is the difference between Mitmproxy and Mitmdump?
mitmdump is the command-line version of mitmproxy, described as tcpdump for HTTP, while mitmproxy is the interactive console interface. The classification Environment :: Console :: Curses is what decides which one you want in practice, because the console front end expects a real terminal, so continuous integration, a container without a tty, or a pipe is the situation where mitmdump is the right choice.
how to use mitmproxy web interface
mitmweb is the web-based interface for mitmproxy, and it is the front end to reach for when there is no interactive terminal, which is also the case inside a container. Its frontend lives in a top-level web/ directory separate from the mitmproxy/ package, so the web interface is a build artefact of its own, and the web server library it uses is installed as part of the core package.
how to install mitmproxy
The README sends installation to the overview-installation page in the stable documentation, and says precompiled binaries are available on the mitmproxy website next to the general information and tutorials. For a source install it points at CONTRIBUTING.md. The distribution is on PyPI, and it requires Python 3.12 or newer with CPython as the only declared implementation.
Is MitM proxy safe?
The project is MIT licensed, classifies itself with the Topic :: Security classifier, and is marked Development Status :: 5 - Production/Stable, so the code is an established open source tool rather than something experimental. What makes it sensitive in use is the capability it is built for: a TLS-intercepting proxy has to issue certificates your client will trust, so its certificate material is privileged and anything that trusts it can be read, and you should scope that trust rather than installing it broadly.
What is a good alternative to Mitmproxy?
The project does not name competing tools. What it offers is a choice of front end for the same core, the interactive console proxy, mitmdump as the command-line version described as tcpdump for HTTP, and the web-based mitmweb, plus the extension route through the addons and contrib directories in the examples tree. Precompiled binaries and tutorials are published on the project website.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mitmproxy-mitmproxy)