DEV Community

Apollo
Apollo

Posted on

The fastest way to build a Telegram Bot natively

The Fastest Way to Build a Telegram Bot Natively

Telegram bots are powerful tools for automation, customer service, and integrations. While frameworks like python-telegram-bot exist, building natively with Telegram's HTTP API gives you maximum speed and control. Below is a zero-dependency approach using pure Python and requests.


1. Prerequisites

Before diving in, ensure you have:

  • A Telegram account
  • Bot Token from @BotFather
  • Python 3.8+ installed

2. Understanding Telegramโ€™s Bot API

Telegram bots communicate via HTTPS requests to:

https://api.telegram.org/bot<TOKEN>/<METHOD>
Enter fullscreen mode Exit fullscreen mode

Key methods:

  • getUpdates โ€“ Fetch new messages
  • sendMessage โ€“ Reply to users
  • setWebhook โ€“ For real-time updates (optional)

3. Building the Bot (Pure Python)

Step 1: Setup & Fetch Updates

import requests

TOKEN = "YOUR_BOT_TOKEN"
BASE_URL = f"https://api.telegram.org/bot{TOKEN}"

def get_updates(offset=None):
    url = f"{BASE_URL}/getUpdates"
    params = {"offset": offset, "timeout": 30}  # Long polling
    response = requests.get(url, params=params).json()
    return response.get("result", [])
Enter fullscreen mode Exit fullscreen mode

Step 2: Process Messages & Reply

def send_message(chat_id, text):
    url = f"{BASE_URL}/sendMessage"
    payload = {"chat_id": chat_id, "text": text}
    requests.post(url, json=payload)

def handle_updates(updates):
    for update in updates:
        chat_id = update["message"]["chat"]["id"]
        text = update["message"].get("text", "")

        if text == "/start":
            send_message(chat_id, "๐Ÿš€ Bot is live!")
        elif text == "/ping":
            send_message(chat_id, "๐Ÿ“ Pong!")
Enter fullscreen mode Exit fullscreen mode

Step 3: Run the Bot in a Loop

def main():
    offset = None
    while True:
        updates = get_updates(offset)
        if updates:
            handle_updates(updates)
            offset = updates[-1]["update_id"] + 1  # Skip old updates

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

4. Optimizing for Speed

a) Use Webhooks Instead of Polling

Polling (getUpdates) introduces latency. Webhooks push updates instantly:

WEBHOOK_URL = "https://your-server.com/webhook"

# Set webhook (run once)
requests.get(f"{BASE_URL}/setWebhook?url={WEBHOOK_URL}")

# Flask example for handling webhooks
from flask import Flask, request

app = Flask(__name__)

@app.route("/webhook", methods=["POST"])
def webhook():
    update = request.json
    handle_updates([update])
    return "OK"
Enter fullscreen mode Exit fullscreen mode

b) Async Requests with httpx

For high-throughput bots:

import httpx

async def async_send_message(chat_id, text):
    async with httpx.AsyncClient() as client:
        await client.post(
            f"{BASE_URL}/sendMessage",
            json={"chat_id": chat_id, "text": text}
        )
Enter fullscreen mode Exit fullscreen mode

c) Rate Limit Handling

Telegram enforces 30 messages/sec per bot. Implement a queue:

from queue import Queue
import threading

message_queue = Queue()

def worker():
    while True:
        chat_id, text = message_queue.get()
        send_message(chat_id, text)
        message_queue.task_done()

threading.Thread(target=worker, daemon=True).start()

# Usage: message_queue.put((chat_id, "Hello!"))
Enter fullscreen mode Exit fullscreen mode

5. Advanced Features

a) Inline Keyboards

from json import dumps

def send_keyboard(chat_id):
    keyboard = {
        "inline_keyboard": [[
            {"text": "Option 1", "callback_data": "opt1"},
            {"text": "Option 2", "callback_data": "opt2"}
        ]]
    }
    payload = {
        "chat_id": chat_id,
        "text": "Choose:",
        "reply_markup": dumps(keyboard)
    }
    requests.post(f"{BASE_URL}/sendMessage", json=payload)
Enter fullscreen mode Exit fullscreen mode

b) File Uploads

def send_photo(chat_id, photo_path):
    with open(photo_path, "rb") as photo:
        requests.post(
            f"{BASE_URL}/sendPhoto",
            files={"photo": photo},
            data={"chat_id": chat_id}
        )
Enter fullscreen mode Exit fullscreen mode

6. Deployment

a) Local Testing with Ngrok

ngrok http 5000  # Exposes localhost:5000
Enter fullscreen mode Exit fullscreen mode

b) Production (AWS Lambda + API Gateway)

# lambda_function.py
def lambda_handler(event, context):
    handle_updates([event["body"]])
    return {"statusCode": 200}
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

By avoiding bloated libraries, this native approach ensures minimal latency and full control. For scaling:

  • Use async I/O (httpx, aiohttp)
  • Implement Redis for state management
  • Monitor with Telegramโ€™s getWebhookInfo

Now go build something fast! ๐Ÿš€


Further Reading:


๐Ÿš€ Stop Writing Boilerplate Prompts

If you want to skip the setup and code 10x faster with complete AI architecture patterns, grab my Senior React Developer AI Cookbook ($19). It includes Server Action prompt libraries, UI component generation loops, and hydration debugging strategies.

Browse all 10+ developer products at the Apollo AI Store | Or snipe Solana tokens free via @ApolloSniper_Bot.

Top comments (0)