DEV Community

Serhii Kalyna
Serhii Kalyna

Posted on • Originally published at kalyna.pro

Building a Telegram Bot with Claude API (Python, 2026)

A Telegram bot powered by Claude gives you a personal AI assistant accessible from your phone. In this tutorial you'll build one from scratch — handling messages, keeping conversation history, and deploying it.


Prerequisites

  • Python 3.10+
  • Anthropic API key
  • Telegram account

Step 1: Create a Telegram Bot

  1. Open Telegram, search for @botfather
  2. Send /newbot and follow the prompts
  3. Copy the bot token (looks like 7123456789:AAF...)

Step 2: Install Dependencies

pip install python-telegram-bot anthropic
Enter fullscreen mode Exit fullscreen mode

Step 3: Basic Echo Bot

from telegram import Update
from telegram.ext import Application, MessageHandler, filters, ContextTypes

BOT_TOKEN = "YOUR_TELEGRAM_BOT_TOKEN"

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    text = update.message.text
    await update.message.reply_text(f"You said: {text}")

app = Application.builder().token(BOT_TOKEN).build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
app.run_polling()
Enter fullscreen mode Exit fullscreen mode

Test it first — make sure messages echo back before adding Claude.


Step 4: Add Claude

from telegram import Update
from telegram.ext import Application, MessageHandler, CommandHandler, filters, ContextTypes
import anthropic

BOT_TOKEN = "YOUR_TELEGRAM_BOT_TOKEN"
claude = anthropic.Anthropic()

conversations: dict[int, list] = {}

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    chat_id = update.effective_chat.id
    user_text = update.message.text

    if chat_id not in conversations:
        conversations[chat_id] = []
    conversations[chat_id].append({"role": "user", "content": user_text})

    history = conversations[chat_id][-20:]

    response = claude.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        system="You are a helpful assistant. Be concise — this is a Telegram chat.",
        messages=history,
    )

    reply = response.content[0].text
    conversations[chat_id].append({"role": "assistant", "content": reply})
    await update.message.reply_text(reply)


async def reset_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    conversations.pop(update.effective_chat.id, None)
    await update.message.reply_text("Conversation reset.")


app = Application.builder().token(BOT_TOKEN).build()
app.add_handler(CommandHandler("reset", reset_command))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
app.run_polling()
Enter fullscreen mode Exit fullscreen mode

Step 5: Add Typing Indicator

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await context.bot.send_chat_action(chat_id=update.effective_chat.id, action="typing")
    # ... rest of handler
Enter fullscreen mode Exit fullscreen mode

Step 6: Handle Long Responses

Telegram has a 4096-character limit. Split long responses:

def split_message(text: str, limit: int = 4000) -> list[str]:
    if len(text) <= limit:
        return [text]
    parts = []
    while text:
        parts.append(text[:limit])
        text = text[limit:]
    return parts

# In your handler:
for part in split_message(reply):
    await update.message.reply_text(part)
Enter fullscreen mode Exit fullscreen mode

Step 7: Deploy on a VPS

# /etc/systemd/system/claude-bot.service
[Unit]
Description=Claude Telegram Bot
After=network.target

[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/claude-bot
ExecStart=/usr/bin/python3 bot.py
Restart=always
Environment=ANTHROPIC_API_KEY=your-key
Environment=BOT_TOKEN=your-token

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode
sudo systemctl enable claude-bot
sudo systemctl start claude-bot
Enter fullscreen mode Exit fullscreen mode

Cost Estimate

With 100 daily messages (avg 200 input + 150 output tokens each) on Sonnet:

  • Input: ~$0.06/day
  • Output: ~$0.23/day
  • Total: ~$9/month

Add prompt caching on the system prompt to cut input costs by ~90%.


What to Build Next

  • /summarize command — paste a URL, get a summary
  • Image analysis — handle filters.PHOTO and use Claude's vision
  • Scheduled reminders — use job_queue from python-telegram-bot
  • Group chat mode — different system prompt for group vs private

Originally published at kalyna.pro

Top comments (0)