## Introduction to Real-Time Shipment Tracking
In today's fast-paced logistics world, keeping tabs on shipments in real time is crucial for businesses and individuals alike. Imagine receiving instant notifications on your phone whenever your package moves—whether it's out for delivery or delayed. This guide walks you through constructing a Telegram bot that achieves exactly that, leveraging the power of Python, the python-telegram-bot library, and the AfterShip tracking API.
We'll cover everything from bot creation to deployment, ensuring you end up with a fully functional tool. This project not only simplifies personal tracking but also scales for e-commerce applications, providing updates on carriers like USPS, FedEx, or DHL. By the end, you'll have hands-on experience with webhooks, APIs, and cloud deployment, making it a great entry into bot development.
## Essential Prerequisites
Before diving in, ensure you have:
- A Telegram account.
- Python 3.7+ installed.
- Basic familiarity with pip for package management.
- A free [AfterShip](https://www.aftership.com/) account for tracking API access.
- Heroku account for deployment (free tier works fine).
Key libraries we'll use:
```bash
pip install python-telegram-bot requests flask gunicorn
```
The [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) library simplifies Telegram API interactions, while Flask handles webhooks efficiently. Requests manages API calls to AfterShip.
## Step 1: Register Your Telegram Bot
Start by interacting with Telegram's BotFather:
1. Open Telegram and search for @BotFather.
2. Send `/newbot` and follow prompts to name your bot (e.g., "ShipmentTrackerBot") and choose a username (e.g., shipment_tracker_bot).
3. BotFather provides a **BOT_TOKEN**—save it securely, as it's your bot's access key.
Test it: Message your bot `/start`. It won't respond yet, but this confirms setup.
Pro tip: For production, enable privacy mode via `/setprivacy` in BotFather to restrict group message access.
## Step 2: Configure AfterShip for Tracking
AfterShip aggregates data from 1000+ carriers, offering a unified API.
1. Sign up at AfterShip and create a new tracker via their dashboard or API.
2. Get your **AFTERSHIP_API_KEY** from the API Keys section.
To add a shipment:
```bash
curl -X POST 'https://api.aftership.com/v4/trackings' \\
-H 'aftership-api-key: YOUR_API_KEY' \\
-H 'Content-Type: application/json' \\
-d '{"tracking":{"tracking_number":"JP0005900000000000","slug":"japan-post"}}'
```
Retrieve updates:
```bash
curl -X GET 'https://api.aftership.com/v4/trackings/JP0005900000000000' \\
-H 'aftership-api-key: YOUR_API_KEY'
```
This returns JSON with status, ETA, and checkpoints. Our bot will poll or use webhooks for live data.
## Step 3: Architect the Bot's Core Functionality
The bot handles:
- `/start`: Welcome message.
- `/track <tracking_number> <carrier_slug>`: Add shipment.
- `/status <id>`: Check updates.
- `/list`: Show all trackings.
- `/remove <id>`: Delete tracking.
We'll store trackings in memory initially (use a database like Redis for production).
Create `bot.py`:
```python
import logging
from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes
import requests
logging.basicConfig(level=logging.INFO)
BOT_TOKEN = 'YOUR_BOT_TOKEN'
AFTERSHIP_API_KEY = 'YOUR_API_KEY'
AFTERSHIP_URL = 'https://api.aftership.com/v4'
trackings = {} # {user_id: [{'id': 'xxx', 'number': 'yyy', 'slug': 'zzz'}]}
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text('Welcome! Use /track <number> <carrier> to start.')
async def track(update: Update, context: ContextTypes.DEFAULT_TYPE):
args = context.args
if len(args) != 2:
await update.message.reply_text('Usage: /track <tracking_number> <carrier_slug>')
return
number, slug = args
user_id = update.effective_user.id
tracking_id = f'{user_id}_{number}'
# Add to AfterShip
response = requests.post(f'{AFTERSHIP_URL}/trackings',
headers={'aftership-api-key': AFTERSHIP_API_KEY},
json={'tracking': {'tracking_number': number, 'slug': slug}})
if response.status_code == 200:
data = response.json()['tracking']
if user_id not in trackings:
trackings[user_id] = []
trackings[user_id].append({'id': data['id'], 'number': number, 'slug': slug})
await update.message.reply_text(f'Tracking {number} added! ID: {data["id"]}')
else:
await update.message.reply_text('Failed to add tracking.')
# Similar handlers for status, list, remove...
def main():
app = Application.builder().token(BOT_TOKEN).build()
app.add_handler(CommandHandler('start', start))
app.add_handler(CommandHandler('track', track))
# Add others
app.run_polling()
if __name__ == '__main__':
main()
```
This polls Telegram; for production, switch to webhooks.
Enhancement: Add carrier slug lookup. Common slugs: `usps` (USPS), `fedex` (FedEx), `dhl`. Use AfterShip's [carrier list](https://api.aftership.com/v4/carriers/list) endpoint.
## Step 4: Implement Real-Time Updates via Webhooks
Polling works for testing, but webhooks push updates instantly.
AfterShip supports tracking webhooks: Configure in dashboard to POST to your endpoint on status changes.
For Telegram, set a webhook URL:
```python
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
async def webhook():
update = Update.de_json(request.get_json(), app.bot)
await handle_update(update)
return 'OK'
```
Set webhook: `https://api.telegram.org/bot<token>/setWebhook?url=https://yourapp.herokuapp.com/webhook`
Handle AfterShip webhooks similarly to notify users.
## Step 5: Persist Data and Enhance Reliability
In-memory storage resets on restarts. Use SQLite or Heroku Postgres.
Example SQLite integration:
```python
import sqlite3
conn = sqlite3.connect('trackings.db')
conn.execute('CREATE TABLE IF NOT EXISTS trackings (user_id INT, tracking_id TEXT, number TEXT, slug TEXT)')
```
Query/insert as needed. For scalability, migrate to Redis.
Add error handling: Retry failed API calls, validate inputs.
## Step 6: Deploy to Heroku for Always-On Operation
Heroku makes deployment seamless.
1. Create `Procfile`: `web: gunicorn bot:app` (adapt for Flask).
2. `requirements.txt`: List all pip installs.
3. `runtime.txt`: `python-3.10.0`.
4. Git init, commit, `heroku create your-bot-app`.
5. Set env vars: `heroku config:set BOT_TOKEN=xxx AFTERSHIP_API_KEY=yyy`.
6. `git push heroku main`.
7. Set Telegram webhook to `https://your-bot-app.herokuapp.com/webhook`.
For dyno sleep prevention (free tier), use UptimeRobot to ping `/` every 5 mins.
Test end-to-end: Track a test package and watch updates flow.
## Advanced Features and Best Practices
- **Multi-user Support**: User IDs isolate data.
- **Scheduled Checks**: Use APScheduler for periodic polls if webhooks unavailable.
- **Rich Messages**: Send photos of packages or maps via Telegram's API.
- **Security**: Never hardcode tokens; use env vars. Rate-limit commands.
Real-world application: Integrate with Shopify for order fulfillment notifications.
Full source code available at [https://github.com/ahmedmansouri/shipment-tracker-bot](https://github.com/ahmedmansouri/shipment-tracker-bot).
Explore more Telegram bots at [https://github.com/topics/telegram-bot?l=python](https://github.com/topics/telegram-bot?l=python).
## Conclusion
You've now built a robust, real-time shipment tracker. This project demonstrates API orchestration, async programming, and serverless deployment—skills transferable to countless automation tasks. Customize further: Add voice commands or multi-language support. Start tracking today and streamline your logistics!
---
<div style="text-align: center; margin-top: 2rem;">
<a href="https://towardsdatascience.com/build-a-real-time-shipment-tracking-tool-using-a-telegram-bot-beb6ab29fca3/" target="_blank" rel="noopener noreferrer" class="view-full-resource-btn" style="display: inline-block; background-color: #f97316; color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; transition: background-color 0.2s;">View Full Resource</a>
</div>