▷ Cómo hacer un bot de Telegram en Python — De cero a tu primer bot 2026

Cómo hacer un bot de Telegram en Python — De cero a tu primer bot

Hacer un bot de Telegram en Python es una de las cosas más gratificantes que puedes programar como proyecto personal. En menos de 30 líneas tienes un bot funcionando en tu móvil, respondiéndote a comandos, enviándote alertas, conectado a una API de IA. Y a partir de ahí lo extiendes hasta donde quieras: recordatorios, traductor, asistente personal, monitor de servidores, alarma cuando un script falla, lo que se te ocurra.

En esta entrada te enseño los pasos que importan: crear el bot en BotFather, escribir tu primer comando, manejar mensajes, integrarlo con OpenAI/Claude para hacer un asistente, y los errores típicos al empezar.

Lo que vas a tener al final

Un bot que:

  1. Responde a /start con un saludo.
  2. Atiende un comando custom como /clima Madrid.
  3. Responde a cualquier mensaje libre usando un LLM (bonus).

Todo en ~50 líneas Python con la librería oficial python-telegram-bot (v22+, async/await).

Paso 1 — Crear el bot en BotFather

Abre Telegram y busca @BotFather (la cuenta oficial). Le mandas:

/newbot

Te pedirá:

  1. Un nombre (lo que se ve en el chat): Mi Asistente Python.
  2. Un username terminado en bot: mi_asistente_python_bot.

Te devolverá un token tipo:

1234567890:AAEhBP8q-ABCxyzWXYz1234abcdEFGHijk

Eso es la clave del bot. Igual que una contraseña: si se filtra, cualquiera puede controlar tu bot. Guárdala en una variable de entorno, nunca en código que vayas a subir a git.

Paso 2 — Instalar la librería

pip install python-telegram-bot

💡 ¿Sin venv aún? Antes de instalar nada, venv y pip sin liarte. Cinco comandos que te ahorran problemas.

📥 Llévate el cheatsheet de Python (gratis)

PDF de 6 páginas con lo esencial: tipos, condicionales, bucles, estructuras de datos, funciones y los errores que más vas a cometer. Para tener al lado mientras programas.

Sin spam. Te apuntas a la lista, descargas el cheatsheet y recibes contenido de Python cada semana.

Paso 3 — Tu primer bot funcional

import os
import logging
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes

logging.basicConfig(level=logging.INFO)

TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]


async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text(
        f"Hola {update.effective_user.first_name}, soy tu bot. Prueba /ayuda."
    )


async def ayuda(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await update.message.reply_text(
        "Comandos disponibles:\n"
        "/start — Saludo inicial\n"
        "/ayuda — Esta ayuda\n"
        "/eco <texto> — Te repite el texto"
    )


async def eco(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    texto = " ".join(context.args) if context.args else "(sin argumentos)"
    await update.message.reply_text(f"Eco: {texto}")


def main() -> None:
    app = ApplicationBuilder().token(TOKEN).build()

    app.add_handler(CommandHandler("start", start))
    app.add_handler(CommandHandler("ayuda", ayuda))
    app.add_handler(CommandHandler("eco", eco))

    app.run_polling()


if __name__ == "__main__":
    main()

Antes de ejecutarlo:

export TELEGRAM_BOT_TOKEN="1234567890:AAEhBP8q..."
python bot.py

Y en Telegram, abre el chat con tu bot (busca su username) y prueba /start. Te responde. ¡Bot funcionando!

💡 ¿Por qué if __name__ == "__main__"? Mira if __name__ == "__main__" en Python.

Cómo funciona por dentro

  • ApplicationBuilder().token(TOKEN).build() crea la app del bot conectándose a Telegram.
  • CommandHandler("start", funcion) registra qué función responde al comando /start.
  • run_polling() arranca el bot y empieza a escuchar mensajes (consultando Telegram cada poco tiempo).
  • Cada handler es una función async que recibe update (el mensaje recibido) y context (estado del bot + argumentos).

Tip-friki: python-telegram-bot v22+ es async por dentro. Por eso los handlers son async def. Si vienes nuevo a async, lee asyncio en Python desde cero primero.

Paso 4 — Manejar mensajes libres (no solo comandos)

Para que el bot responda a cualquier mensaje, no solo a /comandos:

from telegram.ext import MessageHandler, filters

async def manejar_mensaje(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    texto_recibido = update.message.text
    await update.message.reply_text(f"Recibí: {texto_recibido}")


app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, manejar_mensaje))

filters.TEXT & ~filters.COMMAND = “mensajes de texto que NO sean comandos”. Así no se duplica con los CommandHandler ya registrados.

Paso 5 — Bonus: bot conectado a un LLM (OpenAI)

Aquí es donde se vuelve interesante. Ahora el bot responde inteligentemente con un LLM:

pip install openai
import os
from openai import OpenAI
from telegram import Update
from telegram.ext import ContextTypes

cliente_llm = OpenAI(api_key=os.environ["OPENAI_API_KEY"])


async def manejar_con_llm(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    texto_usuario = update.message.text

    respuesta = cliente_llm.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "Eres un asistente útil y conciso, respondes en español."},
            {"role": "user", "content": texto_usuario},
        ],
        max_tokens=400,
    )

    await update.message.reply_text(respuesta.choices[0].message.content)

Con el handler de mensajes libres apuntando a manejar_con_llm, ya tienes un asistente personal en Telegram que responde con IA.

💡 ¿Quieres entender APIs de OpenAI/Claude a fondo? Mira API de OpenAI y Claude en Python.

Paso 6 — Mantener contexto de conversación

Por defecto cada mensaje es independiente. Para que el bot recuerde la conversación dentro del chat:

from collections import defaultdict

historial = defaultdict(list)   # chat_id → lista de mensajes


async def manejar_con_historial(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    chat_id = update.effective_chat.id
    texto_usuario = update.message.text

    historial[chat_id].append({"role": "user", "content": texto_usuario})

    respuesta = cliente_llm.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "Eres un asistente útil."},
            *historial[chat_id][-20:],   # últimos 20 mensajes
        ],
    )

    contenido = respuesta.choices[0].message.content
    historial[chat_id].append({"role": "assistant", "content": contenido})

    await update.message.reply_text(contenido)

Limitamos a 20 mensajes de historial para que el contexto no crezca infinito (ni la factura de tokens).

⚡ Para producción seria, persiste el historial en BBDD (no en un dict en memoria). Si reinicias el bot, todo el historial se pierde.

Errores típicos al empezar

# 1. Hardcodear el token
TOKEN = "1234:abc..."           # ❌ no subir a git
TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]   # ✓

# 2. Usar handlers síncronos en v22+
def start(update, context):     # ❌ falta async
    update.message.reply_text("Hola")
async def start(update, context):
    await update.message.reply_text("Hola")    # ✓

# 3. Olvidar await en métodos asíncronos
update.message.reply_text("X")   # ❌ se queda pendiente
await update.message.reply_text("X")   # ✓

# 4. Filters mal combinados (sin negar comandos)
MessageHandler(filters.TEXT, manejar)
# ❌ los comandos /start, /ayuda… también disparan este handler
MessageHandler(filters.TEXT & ~filters.COMMAND, manejar)   # ✓

# 5. Bot no responde
# Razones típicas:
# - Token mal copiado (con espacios o salto de línea)
# - run_polling() falla silenciosamente sin logging
# Soluciona: logging.basicConfig(level=logging.INFO) al principio.

# 6. Lanzar dos instancias del mismo bot
# Telegram limita a UN polling activo por bot. La segunda da error 409.
# Para tener varios entornos, crea bots separados (uno dev, uno prod).

# 7. Pasar credenciales del bot a getUpdates público
# El token NO debe aparecer ni en URLs ni en logs. Si se filtra, regenerarlo
# en BotFather con /revoke.

Cuándo te merece la pena un bot de Telegram

Casos donde es el camino más rápido:

  • Notificaciones de scripts/crons que corren en servidores. Más rápido y mejor que email para alertas.
  • Asistente personal integrado con APIs (calendario, recordatorios, traductor).
  • Bot de equipo que entiende preguntas y conecta con la BBDD interna.
  • Comandos rápidos: “qué tiempo hace en X”, “cuánto vale Bitcoin”, “cómo va mi servidor”.
  • Frontend para automatización: en vez de scripts CLI, le mandas comandos a Telegram.

Casos donde no suele tener sentido:

  • Producto B2B con muchos usuarios (Telegram tiene límites de rate).
  • Volumen masivo (miles de mensajes/segundo).
  • UI compleja con tablas, formularios estilo web.

Deploy básico

Para que el bot esté siempre encendido (en lugar de en tu portátil):

  • VPS sencillo (DigitalOcean, Hetzner): copia el código, instala dependencias, lanza con systemd o supervisor para que reinicie solo si se cae.
  • Docker container orquestado en un VPS o un PaaS gratuito (Render, Railway, Fly.io).
  • Webhook + servidor web en lugar de polling: más eficiente para tráfico alto.

💡 Patrón de servicio systemd para bot 24/7 + alertas si se cae con email: combina con enviar emails desde Python con smtplib y logging en Python para producción seria.

Resumen

Tarea Sintaxis
Crear bot @BotFather/newbot → token
Instalar pip install python-telegram-bot
Comando CommandHandler("start", funcion_async)
Mensaje libre MessageHandler(filters.TEXT & ~filters.COMMAND, ...)
Argumentos context.args (lista de strings)
Responder await update.message.reply_text("...")
Arrancar app.run_polling()
Token os.environ["TELEGRAM_BOT_TOKEN"]
Contexto LLM dict por chat_id + últimos N mensajes
Deploy 24/7 VPS con systemd, o webhook

¿Te ha valido esto?

Si te ha resultado útil, llévate el cheatsheet de Python en PDF — 6 páginas con tipos, condicionales, bucles, estructuras de datos, funciones y los errores típicos. Para tener al lado mientras programas. Gratis.

Sin spam. Email + cheatsheet + un correo por semana con tutoriales nuevos.

Tu siguiente paso

Si has llegado hasta aquí, ya tienes la base para escribir cualquier bot que se te ocurra. La gran mayoría de proyectos personales con bots se construyen sobre estos cuatro patrones (CommandHandler, MessageHandler, async/await, integración con APIs). Lo que cambia es la lógica de dentro.

Si quieres aprender Python desde la base hasta proyectos reales con APIs, deploy y bots, en El Pythonista lo enseño paso a paso.

Un abrazo,
Oscar

¿Quieres aprender Python en orden, no a saltos?

Esto que has leído es solo una pieza. En El Pythonista lo verás todo encadenado: 11 módulos, 35+ lecciones, código revisado, ejercicios y un proyecto real (MovieTracker) que crece contigo desde la primera variable hasta el deploy a producción.

Ver el curso completo →

35+ lecciones · Proyecto real · Acceso de por vida · 14 días de garantía

Compartir

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Publicar un comentario