Blog Python Telegram Bot: Build a Group Management Bot (2026)
Editorial

Python Telegram Bot: Build a Group Management Bot (2026)

Admin {{ $post->author->username }} 8 min read

Python Telegram Bot: Build a Group Management Bot (2026)

Group management is one of the most practical applications for a custom Telegram bot. A well-built group management bot can welcome new members, enforce rules, kick spammers, restrict flooding, pin announcements, and run polls โ€” automating the administrative overhead that comes with running a large Telegram group.

In this tutorial you'll build a fully functional group management bot in Python using the python-telegram-bot library. You'll add a welcome message system, anti-spam protection, and member management features. Browse related bots in Developer Tools and Group Management.

Setting Up python-telegram-bot Library

This tutorial uses python-telegram-bot version 21+, which uses asyncio throughout.

pip install "python-telegram-bot[job-queue]"

Create a project structure:

group-bot/
  bot.py          # Main entry point
  handlers.py     # Message and command handlers
  spam_filter.py  # Anti-spam logic
  .env            # BOT_TOKEN (never commit this)

Install python-dotenv for environment variable loading:

pip install python-dotenv

Building a Welcome Message Bot in Python

The welcome handler fires when new members join the group:

# handlers.py
from telegram import Update, ChatPermissions
from telegram.ext import ContextTypes
import asyncio

# Welcome message configuration
WELCOME_MESSAGE = """
Welcome to the group, {name}! ๐ŸŽ‰

Please read the rules:
1. Be respectful to all members
2. No spam or self-promotion
3. Stay on topic

Enjoy the community!
"""

async def welcome_new_member(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Greet new members when they join."""
    for member in update.message.new_chat_members:
        if member.is_bot:
            continue  # Don't welcome other bots

        name = member.mention_html()  # @username clickable link
        chat_id = update.effective_chat.id

        # Send welcome message
        msg = await context.bot.send_message(
            chat_id=chat_id,
            text=WELCOME_MESSAGE.format(name=name),
            parse_mode="HTML"
        )

        # Auto-delete welcome message after 5 minutes
        context.job_queue.run_once(
            delete_message,
            when=300,
            data={"chat_id": chat_id, "message_id": msg.message_id}
        )

async def delete_message(context: ContextTypes.DEFAULT_TYPE):
    """Delete a message (used for auto-cleanup)."""
    job_data = context.job.data
    try:
        await context.bot.delete_message(
            chat_id=job_data["chat_id"],
            message_id=job_data["message_id"]
        )
    except Exception:
        pass  # Message may already be deleted

Adding Anti-Spam Features

Anti-spam protection is the most critical feature for any group management bot. Here's a multi-layer approach:

# spam_filter.py
from collections import defaultdict
from datetime import datetime, timedelta
from telegram import Update, ChatPermissions
from telegram.ext import ContextTypes

# Track messages per user
message_tracker: dict[int, list[datetime]] = defaultdict(list)

# Config
MAX_MESSAGES = 5        # messages
TIME_WINDOW  = 10       # seconds
MUTE_DURATION = 300     # seconds (5 minutes)

async def check_flood(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Mute users who send too many messages in a short window."""
    if not update.effective_user or not update.effective_message:
        return

    user_id = update.effective_user.id
    chat_id = update.effective_chat.id
    now = datetime.now()
    window_start = now - timedelta(seconds=TIME_WINDOW)

    # Clean old entries, add current
    message_tracker[user_id] = [
        t for t in message_tracker[user_id] if t > window_start
    ]
    message_tracker[user_id].append(now)

    if len(message_tracker[user_id]) > MAX_MESSAGES:
        # Mute the user
        until = now + timedelta(seconds=MUTE_DURATION)
        try:
            await context.bot.restrict_chat_member(
                chat_id=chat_id,
                user_id=user_id,
                permissions=ChatPermissions(can_send_messages=False),
                until_date=until
            )
            await update.effective_message.reply_text(
                f"โš ๏ธ {update.effective_user.mention_html()} has been muted "
                f"for 5 minutes due to flooding.",
                parse_mode="HTML"
            )
        except Exception as e:
            print(f"Could not mute user {user_id}: {e}")

async def check_links(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Delete messages containing Telegram invite links from new members."""
    if not update.effective_message or not update.effective_message.text:
        return

    text = update.effective_message.text
    user = update.effective_user

    # Check for Telegram invite links
    invite_patterns = ["t.me/+", "t.me/joinchat", "telegram.me/joinchat"]
    if any(pattern in text for pattern in invite_patterns):
        try:
            await update.effective_message.delete()
            warning = await context.bot.send_message(
                chat_id=update.effective_chat.id,
                text=f"โ›” {user.mention_html()}: Invite links are not allowed.",
                parse_mode="HTML"
            )
            # Auto-delete the warning after 30 seconds
            context.job_queue.run_once(
                lambda ctx: ctx.bot.delete_message(
                    warning.chat_id, warning.message_id
                ),
                when=30
            )
        except Exception as e:
            print(f"Link filter error: {e}")

Managing Group Members with Python

Admin commands for banning, kicking, and muting specific users:

# admin_handlers.py
from telegram import Update
from telegram.ext import ContextTypes
from telegram.constants import ChatMemberStatus
from functools import wraps

def admin_only(func):
    """Decorator to restrict command to group admins."""
    @wraps(func)
    async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE):
        user = update.effective_user
        chat = update.effective_chat
        member = await chat.get_member(user.id)
        if member.status not in (
            ChatMemberStatus.ADMINISTRATOR,
            ChatMemberStatus.OWNER
        ):
            await update.message.reply_text("โ›” This command is for admins only.")
            return
        return await func(update, context)
    return wrapper

@admin_only
async def ban_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Ban replied-to user. Usage: reply to a message with /ban [reason]."""
    if not update.message.reply_to_message:
        await update.message.reply_text("Reply to a message to ban that user.")
        return

    target = update.message.reply_to_message.from_user
    reason = " ".join(context.args) if context.args else "No reason given"

    await context.bot.ban_chat_member(
        chat_id=update.effective_chat.id,
        user_id=target.id
    )
    await update.message.reply_text(
        f"๐Ÿšซ {target.mention_html()} has been banned.\nReason: {reason}",
        parse_mode="HTML"
    )

@admin_only
async def kick_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Kick (remove without ban) replied-to user."""
    if not update.message.reply_to_message:
        await update.message.reply_text("Reply to a message to kick that user.")
        return

    target = update.message.reply_to_message.from_user
    await context.bot.ban_chat_member(update.effective_chat.id, target.id)
    # Immediately unban to allow rejoining
    await context.bot.unban_chat_member(update.effective_chat.id, target.id)
    await update.message.reply_text(
        f"๐Ÿ‘ข {target.mention_html()} has been kicked.",
        parse_mode="HTML"
    )

@admin_only
async def warn_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Issue a warning. 3 warnings = auto-ban."""
    if not update.message.reply_to_message:
        await update.message.reply_text("Reply to a message to warn that user.")
        return

    target = update.message.reply_to_message.from_user
    chat_id = str(update.effective_chat.id)

    # Retrieve or initialize warns from bot_data
    warns = context.bot_data.setdefault("warns", {})
    key = f"{chat_id}:{target.id}"
    warns[key] = warns.get(key, 0) + 1
    count = warns[key]

    if count >= 3:
        await context.bot.ban_chat_member(update.effective_chat.id, target.id)
        del warns[key]
        await update.message.reply_text(
            f"๐Ÿšซ {target.mention_html()} reached 3 warnings and has been banned.",
            parse_mode="HTML"
        )
    else:
        await update.message.reply_text(
            f"โš ๏ธ {target.mention_html()} warned. ({count}/3 warnings)",
            parse_mode="HTML"
        )

Assembling the Bot

# bot.py
import os
from dotenv import load_dotenv
from telegram.ext import (
    Application, CommandHandler, MessageHandler,
    ChatMemberHandler, filters
)
from handlers import welcome_new_member
from spam_filter import check_flood, check_links
from admin_handlers import ban_user, kick_user, warn_user

load_dotenv()
TOKEN = os.environ["BOT_TOKEN"]

def main():
    app = Application.builder().token(TOKEN).build()

    # Welcome new members
    app.add_handler(MessageHandler(
        filters.StatusUpdate.NEW_CHAT_MEMBERS, welcome_new_member
    ))

    # Anti-spam (runs on every text message)
    app.add_handler(MessageHandler(filters.TEXT, check_flood), group=1)
    app.add_handler(MessageHandler(filters.TEXT, check_links), group=2)

    # Admin commands
    app.add_handler(CommandHandler("ban", ban_user))
    app.add_handler(CommandHandler("kick", kick_user))
    app.add_handler(CommandHandler("warn", warn_user))

    print("Bot started. Press Ctrl+C to stop.")
    app.run_polling(drop_pending_updates=True)

if __name__ == "__main__":
    main()

Deploying Your Python Bot

For a VPS (Ubuntu/Debian):

# Install dependencies
sudo apt update && sudo apt install python3 python3-pip -y
pip3 install "python-telegram-bot[job-queue]" python-dotenv

# Create systemd service for auto-restart
sudo nano /etc/systemd/system/telegram-bot.service
[Unit]
Description=Telegram Group Management Bot
After=network.target

[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/group-bot
ExecStart=/usr/bin/python3 bot.py
Restart=always
RestartSec=10
EnvironmentFile=/home/ubuntu/group-bot/.env

[Install]
WantedBy=multi-user.target
sudo systemctl enable telegram-bot
sudo systemctl start telegram-bot
sudo systemctl status telegram-bot

FAQ

My bot can't ban or kick users. What's wrong?

The bot must be a group administrator with the "Ban users" permission. Add the bot to your group, then go to Group Settings โ†’ Administrators โ†’ Add Admin โ†’ select your bot โ†’ enable "Ban users" and "Delete messages".

How do I make certain commands admin-only?

Use the @admin_only decorator shown above. It checks the user's role in the chat using get_member() before executing the command handler.

Can the bot work in multiple groups simultaneously?

Yes. Telegram sends updates with the chat.id identifying which group the message came from. The same bot instance handles all groups โ€” your warning/ban counters just need to be keyed by f"{chat_id}:{user_id}" as shown in the warn handler.

How do I store warns and data persistently across restarts?

python-telegram-bot supports persistence via PicklePersistence: Application.builder().token(TOKEN).persistence(PicklePersistence("bot_data.pkl")).build(). For production, use SQLite or Redis via a custom persistence class.

My bot is deleting messages but missing some. Why?

The bot must receive every message to filter them. Make sure "Privacy Mode" is disabled โ€” in BotFather, send /mybots โ†’ select your bot โ†’ Bot Settings โ†’ Group Privacy โ†’ Turn off. With privacy mode enabled, the bot only receives messages that start with /.

Share this article

Share on X