Un bot de Telegram con Python puede responder comandos, recopilar información, enviar avisos y automatizar conversaciones repetitivas. Telegram proporciona la plataforma y la Bot API, mientras que Python controla la lógica. Puedes comenzar con un bot pequeño para el terminal y, más adelante, conectar una base de datos, una API externa o un sistema de notificaciones.
Esta guía utiliza la biblioteca python-telegram-bot y su interfaz asíncrona. Aprenderás a crear el bot con BotFather, proteger el token, registrar comandos, responder mensajes, añadir botones, enviar archivos, almacenar datos temporales, registrar errores y preparar el proyecto para ejecutarse de manera continua.
Cómo funciona un bot de Telegram
Un bot es una cuenta especial controlada mediante la Telegram Bot API oficial. Cuando una persona envía un mensaje o pulsa un botón, Telegram genera una actualización. La aplicación recibe esa actualización y decide qué respuesta enviar.
Existen dos métodos habituales:
- Long polling: el programa consulta periódicamente si existen actualizaciones nuevas.
- Webhook: Telegram envía cada actualización a una URL HTTPS pública.
Para aprender y ejecutar un proyecto pequeño, el polling resulta más sencillo porque no exige un servidor público.
Crear el bot con BotFather
- Abre Telegram y busca la cuenta verificada @BotFather.
- Envía el comando
/newbot. - Elige un nombre visible.
- Elige un nombre de usuario terminado en
bot. - Copia el token generado.
El token permite controlar el bot. No lo publiques en repositorios, imágenes ni mensajes compartidos. Si se filtra, revócalo desde BotFather y crea otro.
Preparar el entorno
Crea un entorno virtual con la guía de venv en Python:
python -m venv .venv
python -m pip install python-telegram-bot python-dotenvLa documentación oficial de python-telegram-bot contiene ejemplos para la versión actual de la biblioteca. Es importante comprobarla porque ejemplos antiguos y síncronos pueden no funcionar con versiones modernas.
Guardar el token fuera del código
Crea un archivo .env:
TELEGRAM_BOT_TOKEN=tu_token_realAñádelo a .gitignore:
.env
.venv/
__pycache__/Después carga la variable:
import os
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
if not TOKEN:
raise RuntimeError("Falta TELEGRAM_BOT_TOKEN")La guía para leer variables de entorno en Python explica cómo proteger secretos y validar la configuración.
Crear el primer bot
import os
from dotenv import load_dotenv
from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes
load_dotenv()
TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
async def inicio(
update: Update,
context: ContextTypes.DEFAULT_TYPE,
) -> None:
usuario = update.effective_user
await update.message.reply_text(
f"Hola, {usuario.first_name}. Envía /ayuda."
)
async def ayuda(
update: Update,
context: ContextTypes.DEFAULT_TYPE,
) -> None:
await update.message.reply_text(
"/inicio - saludo\n"
"/ayuda - lista de comandos\n"
"/acerca - información del bot"
)
def main() -> None:
if not TOKEN:
raise RuntimeError("Token no configurado")
app = Application.builder().token(TOKEN).build()
app.add_handler(CommandHandler("inicio", inicio))
app.add_handler(CommandHandler("ayuda", ayuda))
app.run_polling()
if __name__ == "__main__":
main()Los handlers son asíncronos, por eso usan async def y await. La guía de asyncio en Python explica este modelo.
Responder mensajes normales
from telegram.ext import MessageHandler, filters
async def repetir(
update: Update,
context: ContextTypes.DEFAULT_TYPE,
) -> None:
texto = update.message.text
await update.message.reply_text(f"Escribiste: {texto}")
app.add_handler(
MessageHandler(filters.TEXT & ~filters.COMMAND, repetir)
)Registra primero los handlers específicos y después los generales. Un handler de texto demasiado amplio puede capturar mensajes que deberían procesarse de otra forma.
Crear reglas de conversación
async def conversar(update, context):
texto = update.message.text.strip().casefold()
if texto in {"hola", "buenas", "hey"}:
respuesta = "Hola. ¿En qué puedo ayudarte?"
elif "horario" in texto:
respuesta = "Atendemos de lunes a viernes."
elif "precio" in texto:
respuesta = "Indica qué producto deseas consultar."
else:
respuesta = "No entendí. Envía /ayuda."
await update.message.reply_text(respuesta)Los sets y diccionarios ayudan a organizar intenciones y respuestas. Consulta la comparación de listas, tuplas, sets y diccionarios.
Añadir botones
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import CallbackQueryHandler
async def menu(update, context):
teclado = [
[InlineKeyboardButton("Cursos", callback_data="cursos")],
[InlineKeyboardButton("Soporte", callback_data="soporte")],
]
await update.message.reply_text(
"Selecciona una opción:",
reply_markup=InlineKeyboardMarkup(teclado),
)
async def pulsar_boton(update, context):
consulta = update.callback_query
await consulta.answer()
if consulta.data == "cursos":
texto = "Consulta el catálogo de cursos."
else:
texto = "Describe tu problema para iniciar el soporte."
await consulta.edit_message_text(text=texto)Siempre llama a answer() para cerrar el indicador de carga del botón.
Procesar argumentos de comandos
async def sumar(update, context):
try:
numeros = [float(valor) for valor in context.args]
except ValueError:
await update.message.reply_text(
"Usa números: /sumar 10 25"
)
return
if not numeros:
await update.message.reply_text(
"Debes enviar al menos un número."
)
return
await update.message.reply_text(
f"Total: {sum(numeros):g}"
)Valida la entrada y explica cómo corregirla. La guía de try y except ayuda a capturar errores específicos sin ocultar fallos inesperados.
Guardar datos temporales
async def guardar_nombre(update, context):
if not context.args:
await update.message.reply_text(
"Usa /nombre seguido de tu nombre."
)
return
nombre = " ".join(context.args).strip()
context.user_data["nombre"] = nombre
await update.message.reply_text(f"Guardado: {nombre}")user_data sirve para información temporal. Los datos pueden desaparecer al reiniciar, salvo que configures persistencia. Para información importante, utiliza una base de datos y define políticas de privacidad y eliminación.
Enviar documentos
from pathlib import Path
async def enviar_informe(update, context):
ruta = Path("informes") / "mensual.pdf"
if not ruta.exists():
await update.message.reply_text(
"El informe todavía no está disponible."
)
return
with ruta.open("rb") as archivo:
await update.message.reply_document(document=archivo)La guía de pathlib en Python explica rutas y archivos portables. Comprueba tamaño, tipo y permisos antes de enviar contenido generado por usuarios.
Registrar eventos y errores
import logging
logging.basicConfig(
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
level=logging.INFO,
)
logger = logging.getLogger(__name__)
async def manejar_error(update, context):
logger.exception(
"Error no controlado",
exc_info=context.error,
)No registres tokens, contraseñas, mensajes privados ni información personal innecesaria. La guía del módulo logging explica niveles, archivos y rotación.
Organizar un proyecto mayor
telegram_bot/
├── bot.py
├── handlers/
│ ├── comandos.py
│ └── mensajes.py
├── servicios/
│ └── catalogo.py
├── tests/
├── .env
├── .gitignore
└── requirements.txtSepara handlers, reglas de negocio y acceso a datos. Así puedes probar funciones sin conectarte a Telegram. La guía de Pytest ayuda a automatizar estas comprobaciones.
Desplegar el bot
Para recibir actualizaciones, el proceso debe mantenerse activo. Puedes usar un servidor virtual, un contenedor o una plataforma administrada. En producción:
- guarda el token en el gestor de secretos;
- configura reinicio automático;
- registra errores sin exponer datos privados;
- utiliza almacenamiento duradero;
- actualiza dependencias de forma controlada;
- supervisa disponibilidad y tiempos de respuesta.
Problemas frecuentes
- Unauthorized: token incorrecto, revocado o con espacios adicionales.
- El bot no responde: proceso detenido, handler ausente o filtro incorrecto.
- Funciona en privado pero no en grupos: revisa privacidad y permisos en BotFather.
- Ejemplos antiguos fallan: comprueba la versión mayor instalada.
- Los datos desaparecen: configura persistencia o usa una base de datos.
Conclusión
Crear un bot de Telegram con Python comienza con un token, una aplicación y algunos handlers. A partir de esa base puedes añadir comandos, botones, archivos, estado y servicios externos. Mantén las credenciales fuera del código, valida todas las entradas, separa la lógica de los handlers y añade registros y pruebas antes de ofrecer el bot a usuarios reales.





