How to Make a Telegram Bot in Python (with Shingram)

This is a complete, production-grade guide on how to make a Telegram bot in Python using Shingram, a minimalist and explicit Telegram Bot API wrapper.

Official resources:


How to Create a Telegram Bot in Python (Quick Steps)

  1. Create a bot with @BotFather
  2. Install Shingram
  3. Register event handlers
  4. Start polling with bot.run()

This guide explains each step in depth.


How Telegram Bots Work

A Telegram bot works by processing updates sent by Telegram.
Each update represents an event such as:

  • A message
  • A command
  • A callback query
  • An inline query

Shingram uses long polling, meaning:

  • No webhook
  • No server setup required
  • The bot continuously fetches updates from Telegram

This makes Shingram ideal for local development, VPS deployments, and simple production setups.


Why Use Shingram

Shingram focuses on explicitness and simplicity.

Key Characteristics

  • Single normalized Event object
  • Synchronous API (no async/await)
  • No hardcoded Telegram methods
  • Automatic support for new Telegram API methods
  • Full access to raw Telegram JSON

Shingram is ideal if you want control, clarity, and predictable behavior.


Requirements

  • Python 3.8+
  • A Telegram account
  • A bot token from @BotFather

Install Shingram:

pip install shingram

Creating a Bot Token with BotFather

  1. Open Telegram
  2. Search for @BotFather
  3. Send /start
  4. Run /newbot
  5. Choose a name and username
  6. Copy the BOT TOKEN

Basic Bot Setup

Create a file called bot.py:

from shingram import Bot

bot = Bot("YOUR_BOT_TOKEN")

This initializes a Telegram bot using long polling.


Event Object Explained

Shingram provides a single normalized Event object for all updates.

Event Structure

@dataclass
class Event:
    type: str
    name: str
    chat_id: int
    user_id: int
    text: str
    raw: dict

    reply_to: Optional[int]
    chat_type: Optional[str]
    inline_query_id: Optional[str]
    callback_query_id: Optional[str]
    message_id: Optional[int]
    username: Optional[str]
    first_name: Optional[str]
    chat_title: Optional[str]
  • Only 14 fields
  • Covers 80% of use cases
  • Full Telegram data is always available in event.raw

Handling the /start Command

@bot.on("command:start")
def handle_start(event):
    bot.send_message(
        chat_id=event.chat_id,
        text="Hello! This bot is running with Shingram."
    )

Handling Messages (Echo Bot)

@bot.on("message")
def echo(event):
    bot.send_message(
        chat_id=event.chat_id,
        text=event.text
    )

Handling Callback Queries

Callback queries occur when users press inline buttons.

@bot.on("callback")
def handle_callback(event):
    bot.answer_callback_query(
        callback_query_id=event.callback_query_id,
        text="Action received"
    )

Access callback data:

callback_data = event.text

Handling Inline Queries

Inline queries do not have a chat_id.

@bot.on("inline_query")
def handle_inline(event):
    bot.answer_inline_query(
        inline_query_id=event.inline_query_id,
        results=[]
    )

Using event.raw for Advanced Data

event.raw contains the full Telegram update.

Example: Message Entities

entities = event.raw["message"].get("entities", [])

Example: Media Access

message = event.raw["message"]

if "photo" in message:
    file_id = message["photo"][-1]["file_id"]

Dynamic Telegram API Methods

Shingram dynamically converts Python method names to Telegram API calls.

bot.send_message(chat_id=123, text="Hello")

Automatically maps to:

sendMessage

No methods are hardcoded.
If Telegram adds a new method, it works instantly.


Full Minimal Working Bot

from shingram import Bot

bot = Bot("YOUR_BOT_TOKEN")

@bot.on("command:start")
def start(event):
    bot.send_message(event.chat_id, "Bot started")

@bot.on("message")
def echo(event):
    bot.send_message(event.chat_id, event.text)

bot.run()

Deploying a Telegram Bot

Common deployment options:

  • VPS (Hetzner, DigitalOcean)
  • systemd
  • tmux or screen
  • Docker

Shingram works without webhooks.


Polling vs Webhook

FeaturePollingWebhook
SetupSimpleComplex
ServerNot requiredRequired
Shingram✅ Supported❌ Not native
Use caseSmall/medium botsLarge scale

Common Problems and Fixes

Bot Not Responding

  • Check bot token
  • Ensure bot.run() is called
  • Ensure only one instance is polling
  • Check logs for exceptions

Shingram vs Other Frameworks

FeatureShingrampython-telegram-botaiogram
Async
ComplexityLowMediumHigh
AbstractionsMinimalManyMany
LearningEasyMediumHard

Frequently Asked Questions

Is Shingram asynchronous?

No. Shingram is synchronous.

Is Shingram production-ready?

Yes. Many bots benefit from explicit control.

Does Shingram support all Telegram API methods?

Yes. Methods are resolved dynamically.

Do Telegram bots need a server?

No. Polling works on any machine.

Can I access full Telegram updates?

Yes, via event.raw.

Is Shingram beginner-friendly?

Yes, especially if you want to learn how updates work.


References