Crear un bot de WhatsApp con Python es un proyecto útil para aprender automatización, programación de mensajes, validación de datos y manejo de errores. Sin embargo, WhatsApp es una plataforma de comunicación personal y comercial con reglas específicas. La automatización debe utilizarse únicamente con destinatarios que hayan dado su consentimiento, respetando límites, horarios, privacidad y las políticas oficiales. Un bot no debe enviar mensajes masivos no solicitados ni intentar eludir controles de la plataforma.
Antes de comenzar, conviene dominar las funciones en Python, el manejo de excepciones, las variables de entorno, la instalación mediante pip y la creación de entornos virtuales.
Dos formas de automatizar WhatsApp
Para pruebas personales sencillas, algunas bibliotecas controlan WhatsApp Web desde el navegador. Una opción conocida es PyWhatKit, cuyo código y documentación están disponibles en su repositorio oficial de GitHub. Esta estrategia depende de una sesión abierta, de la interfaz web y del comportamiento del navegador, por lo que puede romperse cuando la página cambia.
Para proyectos comerciales o integraciones estables, la alternativa adecuada es la WhatsApp Cloud API oficial de Meta. La API utiliza solicitudes HTTP, tokens, plantillas aprobadas y webhooks. Sus requisitos, precios y límites pueden cambiar, así que debes consultar siempre la documentación oficial antes de desplegar.
Preparar el entorno
python -m venv .venv
.venv\Scripts\activate
python -m pip install pywhatkit
En macOS o Linux, activa el entorno con source .venv/bin/activate. Mantener las dependencias aisladas evita conflictos con otros proyectos.
Enviar un mensaje programado con PyWhatKit
import pywhatkit
telefono = "+34123456789"
mensaje = "Hola, este es un recordatorio autorizado."
pywhatkit.sendwhatmsg(
telefono,
mensaje,
18,
30,
wait_time=15,
tab_close=True,
)
El número debe incluir el código internacional. El equipo necesita conexión, navegador compatible y una sesión válida de WhatsApp Web. La hora debe estar algunos minutos por delante para que la biblioteca pueda abrir la página y preparar el envío.
Validar el número y el texto
import re
def validar_telefono(telefono: str) -> str:
limpio = telefono.strip().replace(" ", "")
if not re.fullmatch(r"\+[1-9]\d{7,14}", limpio):
raise ValueError("Número internacional inválido")
return limpio
def validar_mensaje(texto: str) -> str:
limpio = texto.strip()
if not limpio:
raise ValueError("El mensaje no puede estar vacío")
if len(limpio) > 1000:
raise ValueError("El mensaje es demasiado largo")
return limpio
La validación reduce errores accidentales, pero no sustituye el consentimiento del destinatario. Guarda una lista explícita de contactos autorizados y una fecha de consentimiento.
Manejar errores
import logging
logging.basicConfig(
filename="whatsapp_bot.log",
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
encoding="utf-8",
)
def enviar_programado(telefono, mensaje, hora, minuto):
try:
telefono = validar_telefono(telefono)
mensaje = validar_mensaje(mensaje)
pywhatkit.sendwhatmsg(
telefono,
mensaje,
hora,
minuto,
wait_time=20,
tab_close=True,
)
logging.info("Mensaje preparado para %s", telefono[-4:])
except ValueError as error:
logging.warning("Datos inválidos: %s", error)
except Exception:
logging.exception("No se pudo preparar el mensaje")
No registres el número completo, el contenido sensible ni tokens. Los logs deben ayudar a diagnosticar sin crear una nueva base de datos de información privada.
Usar la Cloud API
Una integración oficial realiza una solicitud HTTP a un endpoint proporcionado por Meta. El token debe almacenarse en una variable de entorno:
import os
import requests
TOKEN = os.getenv("WHATSAPP_TOKEN")
PHONE_NUMBER_ID = os.getenv("WHATSAPP_PHONE_NUMBER_ID")
def enviar_con_api(destino: str, texto: str):
if not TOKEN or not PHONE_NUMBER_ID:
raise RuntimeError("Faltan credenciales de WhatsApp")
url = (
"https://graph.facebook.com/vXX.X/"
f"{PHONE_NUMBER_ID}/messages"
)
headers = {
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
}
payload = {
"messaging_product": "whatsapp",
"to": destino,
"type": "text",
"text": {"body": texto},
}
respuesta = requests.post(
url,
headers=headers,
json=payload,
timeout=20,
)
respuesta.raise_for_status()
return respuesta.json()
La versión del endpoint cambia con el tiempo; reemplaza vXX.X por la versión indicada en la documentación oficial. No copies tokens en tutoriales, repositorios ni capturas de pantalla.
Plantillas y ventanas de conversación
La plataforma puede exigir plantillas aprobadas para iniciar conversaciones empresariales. No supongas que cualquier texto puede enviarse en cualquier momento. El sistema debe registrar el tipo de mensaje, la plantilla utilizada y la autorización correspondiente.
Crear una cola de mensajes
En lugar de enviar directamente desde la interfaz, guarda solicitudes en una cola:
from dataclasses import dataclass
from datetime import datetime
@dataclass
class MensajePendiente:
destino: str
texto: str
programado_para: datetime
intentos: int = 0
Un trabajador puede procesar la cola, aplicar límites y reintentar fallos temporales. Evita reintentar inmediatamente muchas veces, porque podrías duplicar mensajes o superar límites. Usa espera progresiva y un identificador único.
Evitar duplicados
import hashlib
def crear_id(destino, texto, fecha):
contenido = f"{destino}|{texto}|{fecha.isoformat()}"
return hashlib.sha256(contenido.encode("utf-8")).hexdigest()
Guarda ese identificador con el estado. Antes de enviar, comprueba que no haya sido completado. Esto es especialmente importante cuando una respuesta HTTP se pierde después de que el servicio procesó el mensaje.
Webhooks para recibir eventos
La Cloud API utiliza webhooks para notificar mensajes entrantes y estados de entrega. El endpoint debe verificar las solicitudes, responder rápidamente y procesar el trabajo pesado en segundo plano. Nunca confíes en datos externos sin validar su estructura.
Privacidad y seguridad
Recoge la menor cantidad de información posible. Cifra credenciales, limita permisos, rota tokens y separa desarrollo de producción. Si el bot procesa información personal, define una política de retención y una forma sencilla de solicitar eliminación. No uses mensajes privados para entrenar sistemas ni para otros fines sin autorización explícita.
Pruebas
Los tests no deben enviar mensajes reales. Simula la llamada HTTP y verifica que el payload sea correcto:
from unittest.mock import patch
@patch("requests.post")
def test_envio_api(post_falso):
post_falso.return_value.json.return_value = {"messages": [{"id": "1"}]}
post_falso.return_value.raise_for_status.return_value = None
resultado = enviar_con_api("34123456789", "Prueba")
assert resultado["messages"][0]["id"] == "1"
Errores frecuentes
Los problemas más comunes son guardar credenciales en el código, automatizar sin consentimiento, depender de selectores visuales, omitir timeouts, enviar duplicados y registrar datos privados. También es un error presentar una automatización de navegador como solución empresarial estable.
Conclusión
Un bot de WhatsApp con Python puede servir para recordatorios, soporte y notificaciones autorizadas. PyWhatKit es útil para experimentar localmente, mientras la Cloud API oficial es la base adecuada para integraciones mantenibles. Valida números, protege credenciales, usa colas, evita duplicados y respeta las políticas de la plataforma. La calidad del bot no se mide solo por enviar mensajes, sino por hacerlo de forma segura, útil y responsable.






