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:
import smtplibfrom email.mime.text import MIMEText
def send_email(subject, body): msg = MIMEText(body) msg['Subject'] = subject
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:
- Create a free Slack workspace
- Set up an incoming webhook URL
- Use Python’s
requestslibrary to POST a message to that URL - 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:
- Go to slack.com and create a free workspace
- Install the Slack mobile app on your phone
- Sign in and enable notifications
Step 2: Create Incoming Webhook
This is the key part:
- Go to api.slack.com/apps
- Click “Create New App” and select “From scratch”
- Name it something like “Notifier” and select your workspace
- Navigate to “Incoming Webhooks” in the sidebar
- Toggle “On” to enable incoming webhooks
- Click “Add New Webhook to Workspace”
- Select a channel (I created a
#notificationschannel for this) - 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:
#!/usr/bin/env python3import sysimport 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:
chmod +x notify.pysudo mv notify.py /usr/local/bin/notifyStep 4: Usage Patterns
Now I can use it anywhere:
# Basic usagenotify "Task completed successfully"
# After long-running processpython train_model.py; notify "Model training complete"
# With error handlingpython process_data.py && notify "Success: Data processed" || notify "Error: Processing failed"
# Chain multiple commandsmake 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:
import osimport requestsfrom 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 functionsdef 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:
from notify import notify_success, notify_error, notify_warning
# Success notificationnotify_success("Build completed successfully", title="CI Pipeline")
# Warning notificationnotify_warning("Memory usage above 90%", title="Server Monitor")
# Error notificationnotify_error("Database connection failed", title="Critical Error")Usage in Long-Running Scripts
Here’s how I integrate notifications into my data pipelines:
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:
# Add to .bashrc or .zshrcexport SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/HERE"Or use a .env file with python-dotenv:
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/HEREfrom dotenv import load_dotenv
load_dotenv() # Loads from .env fileCommon Mistakes I Made
| Mistake | Impact | Fix |
|---|---|---|
| Hardcoding webhook URL in public repos | Security breach, webhook abuse | Use environment variables |
| No error handling | Silent failures, missed notifications | Always check response status code |
| Sending too many notifications | Notification fatigue, ignored alerts | Batch notifications or use meaningful thresholds |
| Using webhook for two-way communication | Webhooks are one-way only | Use Slack Bot API for interactive features |
| Not testing webhook before deployment | Discover failures too late | Test 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