Self-hosted service
alexbers/mtprotoproxy avatar
alexbers/mtprotoproxy

An MTProto proxy is one Python file, and the container tells you what it needs

Async MTProto proxy for Telegram

2,174 stars519 forksPythonMIT

At a glance

What is it?
This Telegram proxy is small enough that the repository is the program, the config and a container file, and the interesting decisions are all visible in those three artefacts: a bundled pure-Python AES implementation, a capability granted to the system interpreter so a non-root user can bind a low port, host networking, and a mount that lets you edit the code without rebuilding.
Who is it for?
Use mtprotoproxy if you need a Telegram proxy you can read end to end, because the entire implementation is a single module you can inspect before you run it, which is not true of most networking servers. Do not adopt it as a high-availability deployment, since the compose file is a single service on the host network with no load balancer in front and the multi-instance balancing the readme mentions relies on clients choosing between endpoints.
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 130 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 October 7, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The whole proxy is one file, which changes how you should evaluate it

Look at the top-level listing and there is no framework, no package layout and no dependency manifest: a container file, a licence, the readme, a config file, a compose file, the proxy module itself, and a directory holding a pure-Python AES implementation. The entire server is that one module. That has an obvious implication for anyone considering running it, which is that you can read the whole thing before you start it, and that is not a claim you can make about a compiled binary or for a large codebase. The second implication is about maintenance. A single-file server has no internal module boundaries to hold it together, so every change is a change to the whole program, and the readme's own advice for tuning points at wiki pages rather than at a configuration reference, which suggests the knobs are inside the file. The third is that everything the proxy depends on comes from the operating system rather than from a package manager. The container build installs a Python interpreter, an event loop implementation, a cryptography library, a SOCKS library, a capability tool and certificate authorities, and nothing else. There is no lockfile and no version pinning anywhere in what is shown, so the build is reproducible in shape but not in exact package versions, which is worth knowing before you treat an image built today as the image you tested.

A bundled AES implementation, and a cryptography library beside it

The presence of a vendored AES directory next to a container that installs a cryptography package is the kind of thing that deserves an explanation, and the readme does not give one. The reasonable reading is that MTProto's obfuscated transport needs an AES mode or a construction that the general-purpose library does not expose in the form the protocol requires, so a small pure-Python implementation is carried in-tree to cover that case. A pure-Python implementation is orders of magnitude slower than a compiled one, so the design implication is that whatever it is used for must not be on the hot path for every byte of traffic, or the performance claim in the readme would not hold. The readme states the proxy should comfortably serve about four thousand simultaneous users on a virtual server with one CPU core and a gigabyte of memory, which is a striking figure for a Python program and is the sort of number you should treat as a design target rather than a measurement, since the readme does not describe the test method. The SOCKS library in the build list tells you there is a SOCKS path in the program, and the optional event loop module is the one the readme tells you enables an extra speed boost, so the fast path uses a C-implemented event loop with the standard library's being the fallback.

The container grants a capability to the interpreter, and that is a real decision

The container build is short and one line deserves careful reading. After installing the packages, it runs a command that sets the capability to bind privileged ports on the system Python binary itself, and only then does it create an unprivileged user with a fixed identifier and switch to it. The ordering matters and the target matters more. Granting a capability to the interpreter means that any code running under that interpreter, including anything a user of the proxy could somehow get to execute, can bind a low port. Granting it to a copy of your own binary would be narrower. The reason for doing it this way is the opposite of security: the proxy wants to listen on a port below 1024 so clients get a link with no port suffix, and running as a non-root user means it cannot do that without a capability, and running as root in a container that shares the host network would be worse. The author chose the capability over root, which is the better of the two, and the cost is a grant on a shared binary inside an image that is rebuilt from the base image. The compose file completes the picture. It builds locally, restarts unless stopped, uses host networking, mounts the config and the program from the host so you can edit them without rebuilding, mounts the host timezone read-only so timestamps are right, and caps log growth at ten files of ten megabytes. There is also a commented memory limit, which is a hint about what the author expected people to set.

Four steps to a shareable link

The startup instructions are numbered and fit on a few lines, which is the readme's claim of simplicity made concrete. You clone a branch called stable rather than the default branch, change into the directory, optionally edit the config to set the port, the user list and the advertising tag, and then either bring the compose stack up or run the module directly with the system Python if you would rather not use Docker. There is a fourth optional step that is the point of the whole exercise: reading the container logs, which is where the shareable link appears. The clone command is given as a single line with the directory change appended:

bash
git clone -b stable https://github.com/alexbers/mtprotoproxy.git; cd mtprotoproxy

Then the two ways to start it:

bash
docker-compose up -d
bash
python3 mtprotoproxy.py

Three things to notice. The stable branch is deliberate, so what you clone is not necessarily what the default branch points at, which is a sensible convention for a project whose main branch may carry work in progress. The direct Python path means the container is optional, and the wiki has a page dedicated to running without it. And the config is edited in place and mounted, so the file on your host is the file the container reads, which is why the volume list in the compose file includes the program as well as the config. That last detail is unusual and useful: it means you can patch the proxy by editing a file, and the next container start picks it up, without an image rebuild.

Channel advertising is a documented default, not a hidden one

There is a section on advertising a channel, and its instructions are short: get a tag from a named bot and put it into the config. That is a promotion mechanism, and it is documented in the readme rather than buried, which is the right way to do it and does not make it free of consequence. A proxy that inserts a channel promotion is doing something on behalf of every user who connects through it, and the person running the proxy is the one who chose the tag. If you run this for yourself, the tag is a way to be sponsored for your own traffic. If you run it for other people, you are choosing what they are shown, and you should decide that deliberately rather than by copying a config file. There is also a question the readme does not answer, which is what happens to the promotion if the channel is removed or becomes something else, and whether a user can opt out. The readme does not describe any opt-out, so treat the mechanism as unconditional unless you find otherwise in the wiki. Two smaller configuration items are named alongside the tag. One is the port, which is a straightforward setting. The other is the user list, and the readme's instruction to set it comes with no explanation in this document, so what it restricts and how the values are formed is a question for the wiki rather than something to guess at. Set it deliberately and understand it, because a proxy's access control is the part that matters.

Scaling and instrumentation, and the gap between them

The advanced usage section is four bullets and they describe two different concerns. Two are about running more of it: you can pass a config file path to the module so different instances can be configured differently, and you can run several instances, in which case clients are automatically balanced between them. Automatic balancing here means client-side selection among the endpoints you publish, not a load balancer in your infrastructure, so if you want one address rather than several you have to put something in front that does the balancing, and the compose file has no such service. The other two bullets are about seeing what it is doing: the event loop module for extra speed, and runtime statistics exported to a metrics system. Prometheus export in a single-file Python server is a feature worth having, because a proxy is exactly the kind of thing that fails quietly, and the only way to notice is a counter. The wiki adds a page on optimisation and fine tuning, which suggests the knobs are numerous enough to warrant a page. Between them, the four bullets give you a scaling story and an observability story, and neither of them is the story of running this reliably for months: there is no high-availability configuration, no database, and no session persistence in what the readme describes. The release history is worth reading alongside that. There is a gap of more than three years between the second-newest and newest release, and the last commit is two months after that newest release, so the code is still being worked on while releases are irregular.

Editorial conclusion

Use mtprotoproxy if you need a Telegram proxy you can read end to end, because the entire implementation is a single module you can inspect before you run it, which is not true of most networking servers. Do not adopt it as a high-availability deployment, since the compose file is a single service on the host network with no load balancer in front and the multi-instance balancing the readme mentions relies on clients choosing between endpoints. Four things to verify. Whether running a proxy is lawful where you are and where your users are, since operating a relay for others is a different act from connecting through one. What the channel advertising tag does to your traffic, because the readme instructs you to obtain a tag and put it in the config, and that is a promotion inserted on behalf of your users. Whether you want the capability grant in the container build, since the file sets a bind-to-privileged-port capability on the system interpreter itself rather than on the program, which is a wider grant than it looks. And what the user list in the config actually restricts, because the readme tells you to set it without explaining it here. The licence is MIT, the newest release is v1.1.2 from 2026-03-16, and the last push was on 2026-05-30.

Frequently asked questions

How do I set up mtprotoproxy?

Clone the stable branch, optionally edit the config file to set the port, the user list and the advertising tag, then start it with docker-compose up -d or run python3 mtprotoproxy.py directly. Reading the container logs afterwards gives you a link to share.

What does the container build for the mtprotoproxy image?

It starts from a current Ubuntu release and installs Python, an event loop implementation, a cryptography library, a SOCKS library, a capability tool and certificate authorities. It then grants the bind-to-privileged-port capability to the system Python binary, creates an unprivileged user with a fixed identifier, and runs the proxy as that user.

How many users can the proxy handle?

The readme states it should comfortably serve about four thousand simultaneous users on a virtual server with one CPU core and 1024MB of RAM. It does not describe how that figure was measured, so treat it as a design target for that hardware rather than a benchmark result.

What is channel advertising in mtprotoproxy?

A promotion mechanism configured through the advertising tag in the config file. The readme says to get a tag from a named bot and put it in the config, and does not describe an opt-out for connected users, so the person running the proxy is choosing what their users are shown.

Can I run more than one mtprotoproxy instance?

Yes. The readme says the proxy can be launched several times and clients will be automatically balanced between instances, and that you can launch it with a custom config file path. That balancing is client-side selection among published endpoints rather than a load balancer in the compose file, which defines a single service on the host network.

What licence is mtprotoproxy released under?

MIT. The newest release is v1.1.2 from 2026-03-16, the one before it is from 2022, and the last push to the master branch was on 2026-05-30.

Official sources

  1. alexbers/mtprotoproxy on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/alexbers-mtprotoproxy.svg)](https://hysenlabs.com/projects/alexbers-mtprotoproxy)