Skip to main content

puragram

Fast, dependency-light Telegram Bot API framework built on urllib3. No aiohttp. No requests. No httpx.

PyPI version Python versions License Downloads


Why puragram?

Most Telegram Python libraries pull in aiohttp or requests. puragram talks directly to the Telegram Bot API through urllib3 with a keep-alive connection pool. That means:

  • Small — no heavy dependencies, just urllib3
  • Fast — direct JSON requests, no middleware layers
  • Sync — simple, predictable, easy to debug

Features

  • Long-polling and webhook (pure stdlib http.server)
  • Inline mode — @yourbot query with results
  • Built-in FSM: State, StatesGroup, MemoryStorage, FileStorage, SQLiteStorage
  • Middleware: logging, throttling, timing
  • Filters: Command, Text, Regexp, ContentTypes, ChatType, ChatId, UserId, CallbackData, CallbackDataPrefix, Func
  • Filter operators: & (and), | (or), ~ (not)
  • File sending: photo, document, video, audio, voice, sticker
  • Extras: poll, location, contact, dice
  • Auto-split for long messages (send_long_message)
  • Security: path traversal guard, size limits, ReDoS protection, token redaction, dedup, safe SQLite
  • Zero dependencies except urllib3

Install

pip install puragram

Requires Python 3.9+.

Quick start

from puragram import Bot

bot = Bot("YOUR_TOKEN", parse_mode="HTML")

@bot.message_handler(commands=["start"])
def start(msg):
    bot.send_message(msg.chat.id, f"Hi, <b>{msg.from_user.first_name}</b>!")

@bot.message_handler(content_types=["text"])
def echo(msg):
    bot.send_message(msg.chat.id, f"You said: <b>{msg.text}</b>")

if __name__ == "__main__":
    bot.run_polling()

FSM example

from puragram import Bot, RemoveKeyboard, State, StatesGroup

bot = Bot("YOUR_TOKEN", parse_mode="HTML")

class Form(StatesGroup):
    name = State()
    age = State()

@bot.message_handler(commands=["start"])
def start(msg, data):
    data["state"].set_state(Form.name)
    bot.send_message(msg.chat.id, "What's your name?")

@bot.message_handler(state=Form.name)
def on_name(msg, data):
    data["state"].update_data(name=msg.text)
    data["state"].set_state(Form.age)
    bot.send_message(msg.chat.id, f"Nice to meet you, {msg.text}. How old are you?")

@bot.message_handler(state=Form.age)
def on_age(msg, data):
    ctx = data["state"]
    if not msg.text.isdigit():
        bot.send_message(msg.chat.id, "Please enter a number.")
        return
    ctx.update_data(age=int(msg.text))
    info = ctx.get_data()
    ctx.clear()
    bot.send_message(
        msg.chat.id,
        f"Done!\nName: {info['name']}\nAge: {info['age']}",
        reply_markup=RemoveKeyboard(),
    )

bot.run_polling()

Inline mode example

from puragram import Bot, InlineQueryResultArticle

bot = Bot("YOUR_TOKEN")

@bot.inline_query_handler()
def on_inline(q):
    results = [
        InlineQueryResultArticle(
            id="1",
            title="Send hello",
            input_message_content={"message_text": "Hello!"},
        ),
    ]
    bot.answer_inline_query(q.id, results)

bot.run_polling()

Middleware

from puragram import Bot, LoggingMiddleware, ThrottlingMiddleware

bot = Bot("YOUR_TOKEN")
bot.middleware(LoggingMiddleware())
bot.middleware(ThrottlingMiddleware(rate=0.5))

@bot.message_handler(content_types=["text"])
def echo(msg):
    bot.send_message(msg.chat.id, msg.text)

bot.run_polling(workers=4)

Webhook

from puragram import Bot, WebhookServer

bot = Bot("YOUR_TOKEN")

@bot.message_handler(commands=["start"])
def start(msg):
    bot.send_message(msg.chat.id, "Hello via webhook!")

if __name__ == "__main__":
    server = WebhookServer(
        bot,
        host="0.0.0.0",
        port=8080,
        path="/webhook",
        secret_token="change-me-to-random-32-chars",
    )
    server.install("https://your-domain.com/webhook")
    server.start(blocking=True)

Security

  • Path traversal — safe_path() rejects /etc, /proc, /sys, /root, /dev
  • Upload size — 50 MB limit enforced
  • Callback data — validated to ≤64 UTF-8 bytes
  • ReDoS — compile_safe_regex() rejects nested quantifiers
  • Webhook forgery — hmac.compare_digest on secret token
  • Token leakage — bot tokens redacted from logs
  • Idempotency — duplicate update_id dropped via LRU
  • SQL injection — parameterized queries only

Documentation

See ABOUT.md for a full beginner's guide: Python essentials, HTTP, JSON, Telegram Bot API, FSM, middleware, webhooks, security, testing, and deployment.

License

MIT — see LICENSE.

Release files for puragram 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for puragram 1.1.1
File Size Uploaded
puragram-1.1.1.tar.gz 26.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for puragram 1.1.1
File Interpreter ABI Platform
puragram-1.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 51.3 kB

Release files / puragram-1.1.1.tar.gz

Download URL puragram-1.1.1.tar.gz
Size 26.8 kB
Tags Source
SHA-256 checksum
How to use checksums
e616443030cc56d27877d4f30f55257684d4b7c66fe6b2b25ecb2d1bc782a3bc
BLAKE2b-256 checksum
How to use checksums
08dbf0146eaba2154082e8c3b86ba071afd3c0df30b8911a2a54272c1bc0f421
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / puragram-1.1.1-py3-none-any.whl

Download URL puragram-1.1.1-py3-none-any.whl
Size 24.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0722eef70ad63483227a2037ee0a726b7f3f2c7dc4c8378a711040e3f68ff0d6
BLAKE2b-256 checksum
How to use checksums
9b073326b33ca3a927618783c715d6124306fb421bf44a0cbf6f4fdcb0197017
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release history Release notifications | RSS feed

1.2.1

2 release files

1.2.0

2 release files

1.1.2

2 release files

This release

1.1.1 This release

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page