Enviar Mensagem WhatsApp com Python: Tutorial 2026

📚 Série: Automação & Marketing Digital → Evolution API | Automação WhatsApp | CRM Vendas

O que é Enviar Mensagem WhatsApp com Python?

Enviar mensagem WhatsApp com Python é a automação de envio de mensagens via código Python usando APIs como Evolution API ou Twilio. Permite enviar textos, imagens, áudios, documentos e localização para um ou milhares de contatos simultaneamente. É amplamente usado em notificações automáticas, marketing, atendimento e integrações com sistemas ERP/CRM.

Principais benefícios:

  • Automação total: Enviar 1.000+ mensagens sem intervenção manual
  • Personalização em massa: Cada mensagem única (nome, dados específicos)
  • Integração sistemas: Conectar ERP, CRM, banco dados existente
  • Baixo custo: R$ 60/mês vs R$ 500+ APIs pagas

Volume de busca: 720 buscas/mês no Brasil Tendência: +58% interesse últimos 12 meses


Por que implementar agora

Mercado brasileiro 2026

Segundo pesquisas de automação e dados de uso:

  • 84% das empresas brasileiras querem automatizar comunicação cliente
  • 70% dos desenvolvedores usam Python para automações
  • Economia média: R$ 3.200/mês vs soluções pagas (Twilio, Zenvia)
  • ROI típico: 420% no primeiro ano

Python vs outras linguagens para WhatsApp

CritérioPythonNode.jsPHP
Facilidade⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
Bibliotecasrequests, pandasaxios, expressguzzle
Comunidade BREnormeMédiaGrande
Curva aprendizadoBaixaMédiaBaixa

Como funciona (passo a passo)

Passo 1: Instalar Python e bibliotecas (10 minutos)

Instalar Python (se não tiver):

  • Python.org - Versão 3.9+
  • Verificar instalação: python --version

Instalar biblioteca requests:

pip install requests

Verificar instalação:

python -c "import requests; print(requests.__version__)"
# Output esperado: 2.31.0 (ou superior)

Passo 2: Configurar Evolution API (30 minutos)

Opção 1: Usar Evolution API existente

  • Se já tem Evolution configurada, pegar credenciais:
    • BASE_URL: Ex. https://api.seudominio.com.br
    • API_KEY: Chave secreta configurada no .env
    • INSTANCE: Nome da instância criada

Opção 2: Instalar Evolution do zero

Passo 3: Código Python básico - Enviar texto (5 minutos)

Arquivo: whatsapp_sender.py

import requests
import json

# CONFIGURAÇÕES (substituir pelos seus valores)
BASE_URL = "https://api.seudominio.com.br"  # URL Evolution API
API_KEY = "SUA_CHAVE_SECRETA_AQUI"           # Chave API
INSTANCE = "minha-empresa"                   # Nome instância

def enviar_texto(numero, mensagem):
    """
    Envia mensagem de texto via WhatsApp

    Args:
        numero (str): Número formato 5511999999999 (DDI + DDD + número)
        mensagem (str): Texto da mensagem

    Returns:
        dict: Resposta da API
    """
    url = f"{BASE_URL}/message/sendText/{INSTANCE}"

    headers = {
        "apikey": API_KEY,
        "Content-Type": "application/json"
    }

    payload = {
        "number": numero,
        "text": mensagem
    }

    try:
        response = requests.post(url, headers=headers, json=payload)
        response.raise_for_status()  # Levanta exceção se erro HTTP
        return response.json()

    except requests.exceptions.RequestException as e:
        print(f"❌ Erro ao enviar: {e}")
        return None

# EXEMPLO DE USO
if __name__ == "__main__":
    resultado = enviar_texto(
        numero="5511999999999",
        mensagem="Olá! Esta é uma mensagem de teste via Python."
    )

    if resultado:
        print("✅ Mensagem enviada com sucesso!")
        print(f"ID: {resultado['key']['id']}")
    else:
        print("❌ Falha no envio")

Executar:

python whatsapp_sender.py

Resposta esperada:

✅ Mensagem enviada com sucesso!
ID: 3EB0XXXXXXXXXXXXX

Passo 4: Enviar diferentes tipos de mídia

Enviar imagem:

import base64

def enviar_imagem(numero, caminho_imagem, legenda=""):
    """Envia imagem do disco local"""

    # Ler imagem e converter para base64
    with open(caminho_imagem, 'rb') as img_file:
        img_base64 = base64.b64encode(img_file.read()).decode('utf-8')

    url = f"{BASE_URL}/message/sendMedia/{INSTANCE}"

    headers = {
        "apikey": API_KEY,
        "Content-Type": "application/json"
    }

    payload = {
        "number": numero,
        "mediatype": "image",
        "mimetype": "image/jpeg",  # ou image/png
        "caption": legenda,
        "media": img_base64
    }

    response = requests.post(url, headers=headers, json=payload)
    return response.json()

# Uso
enviar_imagem(
    "5511999999999",
    "/caminho/foto_produto.jpg",
    "🎉 Promoção especial! R$ 99,90"
)

Enviar documento (PDF, Excel, etc):

def enviar_documento(numero, caminho_arquivo, nome_arquivo="documento.pdf"):
    """Envia documento (PDF, Excel, Word, etc)"""

    with open(caminho_arquivo, 'rb') as file:
        file_base64 = base64.b64encode(file.read()).decode('utf-8')

    # Detectar mimetype
    mimetypes_map = {
        '.pdf': 'application/pdf',
        '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        '.txt': 'text/plain'
    }

    extensao = caminho_arquivo[caminho_arquivo.rfind('.'):]
    mimetype = mimetypes_map.get(extensao, 'application/octet-stream')

    url = f"{BASE_URL}/message/sendMedia/{INSTANCE}"

    payload = {
        "number": numero,
        "mediatype": "document",
        "mimetype": mimetype,
        "fileName": nome_arquivo,
        "media": file_base64
    }

    headers = {"apikey": API_KEY, "Content-Type": "application/json"}
    response = requests.post(url, headers=headers, json=payload)
    return response.json()

# Uso
enviar_documento(
    "5511999999999",
    "/caminho/relatorio.pdf",
    "Relatorio_Mensal_Janeiro.pdf"
)

Enviar áudio (voz nativa - bolinha azul):

def enviar_audio_voz(numero, caminho_audio_mp3):
    """Envia áudio como mensagem de voz (aparece bolinha azul)"""

    with open(caminho_audio_mp3, 'rb') as audio:
        audio_base64 = base64.b64encode(audio.read()).decode('utf-8')

    url = f"{BASE_URL}/message/sendWhatsAppAudio/{INSTANCE}"

    payload = {
        "number": numero,
        "audio": audio_base64,
        "encoding": True  # Indica que está em base64
    }

    headers = {"apikey": API_KEY, "Content-Type": "application/json"}
    response = requests.post(url, headers=headers, json=payload)
    return response.json()

# Uso
enviar_audio_voz("5511999999999", "/caminho/mensagem_voz.mp3")

Enviar localização:

def enviar_localizacao(numero, latitude, longitude, nome_local=""):
    """Envia pin de localização"""

    url = f"{BASE_URL}/message/sendLocation/{INSTANCE}"

    payload = {
        "number": numero,
        "latitude": latitude,
        "longitude": longitude,
        "name": nome_local
    }

    headers = {"apikey": API_KEY, "Content-Type": "application/json"}
    response = requests.post(url, headers=headers, json=payload)
    return response.json()

# Uso: Enviar localização da loja
enviar_localizacao(
    "5511999999999",
    latitude=-16.6869,
    longitude=-49.2648,
    nome_local="Nossa Loja - Centro"
)

Passo 5: Envio em massa com delay (10 minutos)

Código completo envio bulk:

import time
import pandas as pd

def enviar_massa_personalizado(arquivo_csv):
    """
    Envia mensagens em massa personalizadas

    CSV deve ter colunas: numero, nome, mensagem
    Exemplo CSV:
    numero,nome,mensagem
    5511999999999,João,Olá João! Seu pedido #123 está pronto.
    5511888888888,Maria,Olá Maria! Promoção especial para você!
    """

    # Ler CSV
    df = pd.read_csv(arquivo_csv)

    print(f"📊 Total de mensagens: {len(df)}")

    enviados = 0
    erros = 0

    for index, row in df.iterrows():
        numero = str(row['numero'])
        mensagem = row['mensagem']

        print(f"\n[{index+1}/{len(df)}] Enviando para {numero}...")

        resultado = enviar_texto(numero, mensagem)

        if resultado:
            enviados += 1
            print(f"✅ Enviado")
        else:
            erros += 1
            print(f"❌ Erro")

        # IMPORTANTE: Delay para evitar bloqueio WhatsApp
        if index < len(df) - 1:  # Não esperar no último
            delay = 3  # 3 segundos entre mensagens
            print(f"⏳ Aguardando {delay}s...")
            time.sleep(delay)

    print(f"\n📈 RESUMO:")
    print(f"✅ Enviados: {enviados}")
    print(f"❌ Erros: {erros}")
    print(f"📊 Taxa sucesso: {(enviados/len(df)*100):.1f}%")

# Uso
enviar_massa_personalizado("contatos.csv")

Criar CSV de exemplo:

# Script criar CSV teste
import pandas as pd

dados = {
    'numero': ['5511999999999', '5511888888888', '5511777777777'],
    'nome': ['João', 'Maria', 'Carlos'],
    'mensagem': [
        'Olá João! Seu pedido #123 chegou.',
        'Olá Maria! Promoção 20% OFF hoje.',
        'Olá Carlos! Reunião amanhã 14h.'
    ]
}

df = pd.DataFrame(dados)
df.to_csv('contatos.csv', index=False)
print("✅ CSV criado: contatos.csv")

Caso real: Empresa enviou 5.000 notificações/dia

Empresa: Clínica médica (8 consultórios, Brasília)

Situação anterior:

  • Confirmação consultas 100% manual (ligação telefônica)
  • Tempo gasto: 6 horas/dia ligando para 120 pacientes
  • Taxa confirmação: 60% (40% não atendiam telefone)
  • Custo: R$ 2.400/mês (salário recepcionista só ligações)

Problema principal: Recepcionista gastava manhã inteira ligando para confirmar consultas do dia seguinte. 40% dos pacientes não atendiam, gerando retrabalho. Consultas não confirmadas resultavam em 15% de faltas (perda R$ 18.000/mês).

Implementação:

  • Ferramenta: Python + Evolution API + Planilha Google Sheets
  • Tempo setup: 4 horas (1 tarde para programar)
  • Investimento: R$ 60/mês (VPS Evolution API)

Workflow criado:

1. Sistema clínica exporta consultas dia seguinte (CSV)
2. Script Python roda às 18h (cron automático)
3. Para cada paciente:
   - Buscar nome, horário, médico no CSV
   - Montar mensagem personalizada
   - Enviar via WhatsApp
   - Delay 3 segundos
4. Relatório enviado email gerência (quantos enviados)

Código simplificado:

import pandas as pd
from datetime import datetime, timedelta

def confirmar_consultas_dia_seguinte():
    """Envia confirmação automática consultas"""

    # Ler consultas do sistema (CSV exportado)
    df = pd.read_csv('consultas_amanha.csv')
    # Colunas: paciente_nome, paciente_whatsapp, horario, medico

    amanha = (datetime.now() + timedelta(days=1)).strftime('%d/%m/%Y')

    for _, row in df.iterrows():
        nome = row['paciente_nome']
        numero = row['paciente_whatsapp']
        horario = row['horario']
        medico = row['medico']

        mensagem = f"""Olá {nome}! 👋

🏥 Lembrete de consulta:
📅 Data: {amanha}
⏰ Horário: {horario}
👨‍⚕️ Dr(a). {medico}

Por favor, confirme sua presença respondendo SIM.

Caso precise remarcar, ligue: (61) 3333-4444"""

        enviar_texto(numero, mensagem)
        time.sleep(3)  # Delay 3 segundos

# Agendar para rodar todo dia 18h (crontab Linux)
# 0 18 * * * /usr/bin/python3 /scripts/confirmar_consultas.py

Resultados (após 6 meses):

  • Tempo confirmação: 6 horas/dia → 0 horas (-100%)
  • Taxa confirmação: 60% → 92% (+53%)
  • Faltas consulta: 15% → 4% (-73%)
  • Economia mensal: R$ 2.400 (recepcionista) + R$ 13.140 (menos faltas) = R$ 15.540/mês
  • ROI: 25.900% (R$ 15.540 economia vs R$ 60 custo)
  • Payback: 2 horas (recuperou investimento em menos de 1 dia)

Depoimento:

“Antes gastávamos 6 horas TODOS OS DIAS ligando. Hoje é automático: 18h roda sozinho e envia pra todos. Taxa de confirmação subiu 50% e faltas despencaram.” — Gerente, Clínica Médica


Melhores práticas (checklist)

1. Validar número antes de enviar

Erro comum: Enviar para número inválido/inexistente ✅ Correto: Validar se número tem WhatsApp antes

Código validação:

def validar_numero_whatsapp(numero):
    """Verifica se número existe no WhatsApp"""

    url = f"{BASE_URL}/chat/whatsappNumbers/{INSTANCE}"

    payload = {"numbers": [numero]}
    headers = {"apikey": API_KEY, "Content-Type": "application/json"}

    response = requests.post(url, headers=headers, json=payload)
    data = response.json()

    if len(data) > 0 and data[0].get('exists'):
        return True
    return False

# Uso
if validar_numero_whatsapp("5511999999999"):
    enviar_texto("5511999999999", "Olá!")
else:
    print("❌ Número não tem WhatsApp")

2. Implementar delay adequado

Evitar bloqueio WhatsApp:

  • Delay mínimo: 2 segundos entre mensagens
  • Delay recomendado: 3-5 segundos
  • Limite diário: Máximo 1.000 mensagens/dia para novos contatos
  • Limite horário: Máximo 100 mensagens/hora para números novos

Código com delay variável:

import random

def delay_aleatorio(min_seg=2, max_seg=5):
    """Delay aleatório para parecer mais humano"""
    tempo = random.uniform(min_seg, max_seg)
    time.sleep(tempo)

# Uso
for contato in contatos:
    enviar_texto(contato['numero'], contato['mensagem'])
    delay_aleatorio(3, 6)  # Entre 3-6 segundos aleatório

3. Personalizar cada mensagem

Impacto personalização:

  • Mensagem genérica: Taxa abertura 45%
  • Mensagem com nome: Taxa abertura 78% (+73%)

Exemplo personalização avançada:

def gerar_mensagem_personalizada(dados_cliente):
    """
    dados_cliente: dict com nome, empresa, valor_divida, dias_atraso
    """

    template = f"""Olá {dados_cliente['nome']}! 👋

Identificamos um pagamento pendente:

🏢 Empresa: {dados_cliente['empresa']}
💰 Valor: R$ {dados_cliente['valor_divida']:.2f}
📅 Vencimento: há {dados_cliente['dias_atraso']} dias

Para regularizar, acesse:
https://pagar.seusite.com.br/{dados_cliente['codigo_boleto']}

Dúvidas? Responda esta mensagem!"""

    return template

# Uso
for cliente in clientes_inadimplentes:
    msg = gerar_mensagem_personalizada(cliente)
    enviar_texto(cliente['whatsapp'], msg)
    time.sleep(4)

4. Registrar logs

Salvar histórico envios:

import logging
from datetime import datetime

# Configurar log
logging.basicConfig(
    filename='whatsapp_envios.log',
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

def enviar_com_log(numero, mensagem):
    """Envia mensagem e registra em log"""

    logging.info(f"Tentando enviar para {numero}")

    resultado = enviar_texto(numero, mensagem)

    if resultado:
        logging.info(f"✅ Enviado com sucesso para {numero}")
    else:
        logging.error(f"❌ Erro ao enviar para {numero}")

    return resultado

Arquivo log gerado (whatsapp_envios.log):

2026-01-26 14:30:15 - INFO - Tentando enviar para 5511999999999
2026-01-26 14:30:16 - INFO - ✅ Enviado com sucesso para 5511999999999
2026-01-26 14:30:19 - INFO - Tentando enviar para 5511888888888
2026-01-26 14:30:20 - ERROR - ❌ Erro ao enviar para 5511888888888

5. Tratar erros gracefully

Try/except completo:

def enviar_seguro(numero, mensagem, max_tentativas=3):
    """Tenta enviar com retry automático"""

    for tentativa in range(1, max_tentativas + 1):
        try:
            resultado = enviar_texto(numero, mensagem)

            if resultado:
                return True

        except requests.exceptions.Timeout:
            print(f"⏱️ Timeout na tentativa {tentativa}")
            time.sleep(2)
            continue

        except requests.exceptions.ConnectionError:
            print(f"🔌 Erro conexão na tentativa {tentativa}")
            time.sleep(5)
            continue

        except Exception as e:
            print(f"❌ Erro desconhecido: {e}")
            break

    return False

# Uso
if not enviar_seguro("5511999999999", "Teste", max_tentativas=3):
    # Salvar em fila para reenvio posterior
    salvar_fila_reenvio(numero, mensagem)

Ferramentas complementares

1. Evolution API Tutorial

Quando usar: Configurar backend Evolution API Custo: Grátis (VPS R$ 60/mês) Setup: 30 minutos

Funcionalidades Python + Evolution:

  • Enviar texto, mídia, localização, contato
  • Receber mensagens via webhook → processar Python
  • Criar grupos programaticamente
  • Buscar histórico conversas

2. Automação N8N

Quando usar: Workflows visuais sem código Python Custo: Grátis (self-hosted) Setup: 1 hora

N8N vs Python:

  • N8N: Visual, sem código, ideal não-programadores
  • Python: Máxima flexibilidade, lógica complexa

3. CRM HubSpot

Quando usar: Integrar envios WhatsApp com CRM Custo: Grátis (plano Free) Setup: 2 horas

Integração Python + HubSpot:

# Buscar contatos HubSpot e enviar WhatsApp
import requests

HUBSPOT_KEY = "SUA_CHAVE_HUBSPOT"

def buscar_contatos_hubspot():
    """Busca contatos HubSpot API"""
    url = "https://api.hubapi.com/crm/v3/objects/contacts"
    headers = {"Authorization": f"Bearer {HUBSPOT_KEY}"}

    response = requests.get(url, headers=headers)
    return response.json()['results']

# Enviar para todos contatos HubSpot
contatos = buscar_contatos_hubspot()

for contato in contatos:
    whatsapp = contato['properties'].get('phone')
    nome = contato['properties'].get('firstname')

    if whatsapp:
        mensagem = f"Olá {nome}! Novidade para você..."
        enviar_texto(whatsapp, mensagem)
        time.sleep(3)

Próximos passos

  1. Instalar Evolution API - Backend WhatsApp (30 min)
  2. Instalar Python + requests - pip install requests (5 min)
  3. Testar envio simples - Código básico enviar_texto() (10 min)
  4. Criar CSV contatos - Planilha com números + mensagens (20 min)
  5. Rodar envio massa - Script completo com delay (30 min)

Tempo total setup: 2 horas Resultado esperado: Enviar 100+ mensagens/hora automatizadas


Recursos adicionais

Documentação oficial:

Tutoriais Python WhatsApp:

Comunidades:

Suporte:


Sobre o autor: Felipe Zanoni é desenvolvedor Python especializado em automações WhatsApp, com 150+ scripts desenvolvidos processando 2M+ mensagens/mês para empresas brasileiras.


💬 Precisa de Ajuda para Implementar?

A Agência Café Online já ajudou dezenas de empresas a implementarem soluções de automação e IA, com resultados reais e mensuráveis.

Fale comigo:

💡 Consultoria inicial gratuita para avaliar seu caso e propor uma solução personalizada.