Skip to content

How to Send Push Notifications from Python Using Slack Webhooks

Problem

I run a lot of long Python scripts on remote servers - data processing jobs, model training, backups. The problem? I never know when they finish. I either keep checking the terminal obsessively, or I miss when tasks complete (or fail).

Email notifications are slow and clunky. SMS services cost money. I needed something instant, free, and already integrated into my workflow.

What I Tried First

My first attempt was a simple email notification:

notify_email.py
import smtplib
from email.mime.text import MIMEText
def send_email(subject, body):
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
smtp = smtplib.SMTP('smtp.example.com', 587)
smtp.send_message(msg)
smtp.quit()

But this had several problems:

  • Email delivery is slow (sometimes 5-10 minutes)
  • My phone’s email notifications are buried in spam
  • I needed to configure SMTP credentials on every server
  • Corporate firewalls sometimes block SMTP ports

I also looked at paid services like Pushover and Pushbullet. They work well, but I didn’t want to pay a monthly fee just for script notifications.

The Solution: Slack Webhooks

Then I found a Reddit thread where someone mentioned using Slack webhooks for push notifications. The idea is brilliant:

  1. Create a free Slack workspace
  2. Set up an incoming webhook URL
  3. Use Python’s requests library to POST a message to that URL
  4. Install the Slack mobile app for instant push notifications

The setup takes 5 minutes and costs nothing.

Step 1: Create Slack Workspace

If you don’t already have a Slack workspace:

  1. Go to slack.com and create a free workspace
  2. Install the Slack mobile app on your phone
  3. Sign in and enable notifications

Step 2: Create Incoming Webhook

This is the key part:

  1. Go to api.slack.com/apps
  2. Click “Create New App” and select “From scratch”
  3. Name it something like “Notifier” and select your workspace
  4. Navigate to “Incoming Webhooks” in the sidebar
  5. Toggle “On” to enable incoming webhooks
  6. Click “Add New Webhook to Workspace”
  7. Select a channel (I created a #notifications channel for this)
  8. Copy the webhook URL - it looks like https://hooks.slack.com/services/T000/B000/XXX

Step 3: Basic Python Script

Here’s the simplest working example:

notify.py
#!/usr/bin/env python3
import sys
import requests
WEBHOOK_URL = "https://hooks.slack.com/services/YOUR/WEBHOOK/HERE"
def send_notification(message):
payload = {"text": message}
response = requests.post(WEBHOOK_URL, json=payload)
return response.status_code == 200
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: notify 'your message here'")
sys.exit(1)
message = " ".join(sys.argv[1:])
if send_notification(message):
print(f"Notification sent: {message}")
else:
print("Failed to send notification")
sys.exit(1)

Make it executable and add to PATH:

terminal
chmod +x notify.py
sudo mv notify.py /usr/local/bin/notify

Step 4: Usage Patterns

Now I can use it anywhere:

terminal
# Basic usage
notify "Task completed successfully"
# After long-running process
python train_model.py; notify "Model training complete"
# With error handling
python process_data.py && notify "Success: Data processed" || notify "Error: Processing failed"
# Chain multiple commands
make build && make test && notify "All tests passed" || notify "Build or tests failed"

Better Error Handling

The basic script works, but I found I needed better error handling and richer formatting. Here’s my improved version:

notify_enhanced.py
import os
import requests
from datetime import datetime
def get_webhook_url():
"""Get webhook URL from environment variable."""
url = os.environ.get("SLACK_WEBHOOK_URL")
if not url:
raise ValueError("SLACK_WEBHOOK_URL environment variable not set")
return url
def send_notification(message, title=None, status="info"):
"""
Send a notification to Slack.
Args:
message: The notification text
title: Optional title for the notification
status: One of 'info', 'warning', 'error', 'success'
"""
colors = {
"info": "#36a64f",
"warning": "#ff9900",
"error": "#dc3545",
"success": "#28a745"
}
payload = {
"attachments": [{
"color": colors.get(status, "#36a64f"),
"text": message,
"footer": "Python Notifier",
"ts": int(datetime.now().timestamp())
}]
}
if title:
payload["attachments"][0]["title"] = title
try:
response = requests.post(get_webhook_url(), json=payload, timeout=10)
return response.status_code == 200
except requests.RequestException as e:
print(f"Failed to send notification: {e}")
return False
# Convenience functions
def notify_success(message, title=None):
return send_notification(message, title, "success")
def notify_warning(message, title=None):
return send_notification(message, title, "warning")
def notify_error(message, title=None):
return send_notification(message, title, "error")

Now I can send color-coded notifications:

usage_example.py
from notify import notify_success, notify_error, notify_warning
# Success notification
notify_success("Build completed successfully", title="CI Pipeline")
# Warning notification
notify_warning("Memory usage above 90%", title="Server Monitor")
# Error notification
notify_error("Database connection failed", title="Critical Error")

Usage in Long-Running Scripts

Here’s how I integrate notifications into my data pipelines:

data_pipeline.py
from notify import notify_success, notify_error
def main():
try:
# Long-running process
process_large_dataset()
train_model()
notify_success(
"Pipeline completed successfully",
title="Data Pipeline"
)
except Exception as e:
notify_error(
f"Pipeline failed: {str(e)}",
title="Data Pipeline"
)
raise
if __name__ == "__main__":
main()

Security Best Practice

Never hardcode webhook URLs in your code. Use environment variables:

.bashrc
# Add to .bashrc or .zshrc
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/HERE"

Or use a .env file with python-dotenv:

.env
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/HERE
load_env.py
from dotenv import load_dotenv
load_dotenv() # Loads from .env file

Common Mistakes I Made

MistakeImpactFix
Hardcoding webhook URL in public reposSecurity breach, webhook abuseUse environment variables
No error handlingSilent failures, missed notificationsAlways check response status code
Sending too many notificationsNotification fatigue, ignored alertsBatch notifications or use meaningful thresholds
Using webhook for two-way communicationWebhooks are one-way onlyUse Slack Bot API for interactive features
Not testing webhook before deploymentDiscover failures too lateTest with simple message first

Why This Works So Well

The key benefits I’ve found:

  • Zero cost: Free Slack workspace, no paid notification services
  • Instant delivery: Push notifications arrive within seconds
  • Mobile-first: Get notified anywhere via Slack mobile app
  • Simple integration: Single line of code or command
  • Flexible: Works with any language or script, not just Python
  • Audit trail: All notifications logged in Slack channel
  • No infrastructure: No servers, databases, or authentication to manage

Summary

In this post, I showed how to set up Python push notifications via Slack webhooks. The setup takes 5 minutes: create a free Slack workspace, generate a webhook URL, use the requests library to POST messages, and you get instant mobile notifications when your scripts finish - no paid services required.

The best part? This approach works with any programming language, not just Python. As long as you can make HTTP POST requests, you can send notifications to Slack.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments