TLG_JoinCaptchaBot: a captcha gate for Telegram group sign-ups
Telegram Bot to verify if users joining a group are human. The Bot sends a captcha challenge to each new user and removes those who fail to solve it within a specified time.
At a glance
- What is it?
- TLG_JoinCaptchaBot is a Python Telegram bot that challenges every new group member with a captcha and removes those who fail, using python-telegram-bot, Manim and Pillow. It suits administrators of public groups tired of spam accounts, and it leans on Manim, which makes the setup heavier than a plain image captcha would.
- Who is it for?
- Adopt TLG_JoinCaptchaBot if you moderate a public Telegram group where automated sign-ups are a problem and you can run a Linux host with a graphics toolchain for Manim, and if you are prepared to keep a token in src/settings.py or the settings.json configuration. Do not adopt it for a small private group where the join list is already known, and do not adopt it without reading the accessibility escape hatch, because the bot owner can exempt users through /allowuserlist.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 46 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 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Every joiner gets a challenge, and non-solvers get removed
TLG_JoinCaptchaBot does one job, which is to confirm that the accounts arriving in a Telegram group are people. When a new user joins, the bot sends a captcha. If the challenge is not solved inside a configured time limit, the user is removed from the group.
Around that core, the bot adds the behaviours a group administrator ends up wanting anyway. Messages containing URLs are deleted when they come from users who have not yet completed the captcha, which is an anti-spam rule aimed at accounts that join and immediately post links. New users are blocked from sending media messages until they pass. The bot also removes its own captcha and bot messages after a while, so the group does not fill up with the bot's own output.
Configuration is per group, and the settings listed include the time allowed for solving the captcha, the captcha mode, difficulty, language and a welcome message. Multilanguage support covers close to 30 languages.
The mechanism is worth stating plainly, because it is a gate on membership, not a filter on content. A human who cannot see the challenge at all is indistinguishable from a bot that refuses to answer.
Captcha modes come from Manim and multicolorcaptcha
The captcha itself is not drawn by the project. The requirements file pins three libraries, and the choices in them explain the characteristics of the challenge:
manim-captcha == 1.2.2
multicolorcaptcha == 1.2.0
python-telegram-bot[all] == 22.6manim-captcha produces animated video captchas, which is where the Manim dependency and the Manim requirements come from in the setup. multicolorcaptcha covers the image captcha style. The bot also offers custom poll captchas, so a challenge can be a Telegram poll rather than a rendered image.
The rendering approach is the reason the installation section is so long. Manim is built on Cairo and Pango, and the README asks for libcairo2-dev, libpango1.0-dev, plus the usual image and font libraries, before Python itself is set up:
sudo apt install -y build-essential make libcairo2-dev libpango1.0-dev
sudo apt install -y libtiff5-dev libjpeg62-turbo-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tkThat is a graphics build stack for what a user sees as a small picture. A project that only generated static images with Pillow would need a fraction of it, and would lose the video mode.
Setup is a git clone, a make target and a token
The installation path has four steps. First the Python tooling, then the image and graphics libraries, then the project itself:
git clone https://github.com/J-Rios/TLG_JoinCaptchaBot
cd TLG_JoinCaptchaBot
make setupThe make setup target is a wrapper around the tools/setup script, which the Makefile makes executable before running it. The Makefile follows a consistent pattern for every target, chmod the script then run it, which is why the help output lists operations rather than a single binary.
The last configuration step is the bot token, which comes from BotFather and is written into the settings module:
'TOKEN' : 'XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'In practice the settings live in src/settings.json, and the README notes that advanced users can also drive the same values through environment variables, which is the route to take for a virtual environment or a Docker deployment. Keeping the token in a file inside a checkout is convenient for a first run and a bad habit afterwards, since that file is exactly the kind of thing that ends up committed or copied into an image layer.
The Makefile is the control surface once the bot runs
Running the bot is done through the Makefile rather than by invoking Python directly, and the targets map onto the things an administrator actually needs:
# View available commands
make
# Start the bot
make start
# Check bot status
make status
# Stop the bot
make stopThe Makefile also exposes monitor, which checks the users captcha process, error, which runs the check_errors script, and stats, which shows statistics. The distinction between status and monitor is worth noticing: status answers whether the process is alive, while monitor answers what is happening with the challenges in flight, which is the question you want answered when a group has gone quiet.
For a long running deployment, the README describes a systemd service. The unit file is written to /etc/systemd/system/tlg_joincaptcha_bot.service, runs the tools/start and tools/kill scripts as ExecStart and ExecReload, and is enabled with systemctl enable --now. The service type is forking, matching the way the start script backgrounds the bot. A Docker path also exists, with the details in the docker folder rather than in the main README.
Polling by default, webhook when the group is busy
Telegram bots receive updates in one of two ways, and the bot supports both. The default is polling, where the bot periodically asks Telegram for new updates. The README describes this as suitable for small to medium deployments. For larger ones, the bot can run in webhook mode, where Telegram pushes updates to an address the bot exposes.
Switching to webhook takes three pieces of configuration. A certificate, generated with OpenSSL and valid for ten years:
openssl req -newkey rsa:2048 -sha256 -nodes -keyout private.key -x509 -days 3650 -out cert.pemThen the settings, which point the bot at the certificate and choose the port and path:
"WEBHOOK_IP": "0.0.0.0",
"WEBHOOK_PORT": 8443,
"WEBHOOK_PATH": "/TLG_JoinCaptchaBot",
"WEBHOOK_CERT": SCRIPT_PATH + "/cert.pem",
"WEBHOOK_CERT_PRIV_KEY": SCRIPT_PATH + "/private.key",If a reverse proxy sits in front, a public URL can be supplied as well, and the mode is switched on with CAPTCHABOT_USE_WEBHOOK set to True. The 8443 port and the path both matter, since Telegram posts to that exact endpoint. The alternative to all of this is to keep polling, which costs a request loop but removes the certificate and proxy work entirely.
Private mode and the allowlist control who can use the bot
By default anyone can add the bot to any group they can add it to, which is reasonable for a personal deployment and not reasonable for a public one. The bot can be restricted in two steps. First set BOT_PRIVATE to True in the settings, then authorise groups with the /allow_group command.
There is an owner command set alongside it. The bot owner is set with the BOT_OWNER key in settings.py:
"BOT_OWNER": "@YourUsername",The owner can run /allowgroup to add groups to the allowed list, and /allowuserlist to exempt individual users from captcha verification. The documentation gives accessibility as the reason for the exemption list, and that is a real need: a video captcha that relies on motion and colour is hard or impossible to answer for some people, and a bot that removes people who cannot answer has no way to tell the difference.
One operational wrinkle is called out for private mode. If a public group is promoted to a supergroup, the chat ID can change, which means the group has to be authorised again. Bot permissions in a group also matter, since removing users and deleting messages are privileged actions that the bot has to be granted.
Maintenance rests on a single maintainer and a development branch
The repository is not archived, and the last push was on 2026-09-07. The default branch is development, while the README links point at master, which is a small inconsistency worth knowing about if you clone and find the layout differs from the documentation. The project publishes no GitHub releases, so there is no version to pin and no changelog to read beyond the commit history. The README links a star count and a fork count badge for the project, and the repository root carries a CONTRIBUTING-adjacent set of files and a separate tools folder for the operational scripts.
The licence is GPL-3.0, which is the significant legal difference from a typical bot script. If you run it unmodified as a network service for your own group, that is straightforward. If you want to modify it and keep it private, or to fold its code into a larger proprietary bot, the copyleft terms reach further than they would with a permissive licence. That question is yours or your lawyer to answer, but it is worth raising before you fork rather than after.
Finally, a bot that talks to Telegram on your behalf holds a token that can act as you in every group it is added to. Treat the settings file and the certificate key as secrets.
Editorial conclusion
Adopt TLG_JoinCaptchaBot if you moderate a public Telegram group where automated sign-ups are a problem and you can run a Linux host with a graphics toolchain for Manim, and if you are prepared to keep a token in src/settings.py or the settings.json configuration. Do not adopt it for a small private group where the join list is already known, and do not adopt it without reading the accessibility escape hatch, because the bot owner can exempt users through /allowuserlist. Before deploying, set BOT_OWNER and decide between polling and webhook mode, since switching to webhook requires an SSL certificate and a reverse proxy configuration that the bot does not provide for you.
Frequently asked questions
How do I install TLG_JoinCaptchaBot?
Install the Python and graphics dependencies listed in the README, then clone the repository, run `make setup`, and put your Telegram bot token into the settings file. The bot also ships a systemd unit and a Docker path for longer running deployments.
What happens when a new user joins a group with TLG_JoinCaptchaBot?
The bot automatically sends a captcha challenge to the new member. Users who fail to solve it within the configured time limit are removed, URL messages from users who have not completed the challenge are deleted, and media messages are blocked until the captcha is solved.
Does TLG_JoinCaptchaBot support video and image captchas?
Yes. The bot offers different captcha modes including visual animated video captchas, image captchas and custom poll captchas. The video mode comes from the manim-captcha library and the image mode from multicolorcaptcha, both pinned in the requirements file.
How do I switch TLG_JoinCaptchaBot from polling to webhook mode?
Generate an SSL certificate with OpenSSL, set the WEBHOOK_IP, WEBHOOK_PORT, WEBHOOK_PATH and certificate paths in the settings, optionally set WEBHOOK_URL for a reverse proxy, and enable CAPTCHABOT_USE_WEBHOOK. The default polling mode is described as suitable for small to medium deployments.
Can some users be exempted from the captcha in TLG_JoinCaptchaBot?
Yes. The bot owner can exempt individual users with the /allowuserlist command, which the documentation points at for accessibility needs, and can control which groups may use the bot through /allowgroup when the bot is set to private mode.
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/j-rios-tlg-joincaptchabot)Was this useful?