Skip to content

About

Self-hosted Telegram bot tracking parcels across 24+ couriers worldwide — offline route maps, carrier auto-detect, auto-quarantine, plugin architecture

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

287 Commits

Folders and files

Repository files navigation

parcel-tracker-bot — know where every parcel is, and let your customers know too

parcel-tracker-bot

CI Security codecov License: MIT Python 3.11+

A self-hosted parcel tracker for people and small online shops. Send it a tracking number on Telegram and it follows the parcel with the carrier, tells you when something changes, and draws the route on a map. Turn on the web dashboard and it becomes a shipment control room: every parcel you sent, the ones that need you, and a tracking page for each customer.

  • Any carrier. The carrier is detected from the code; 17track covers 2,000+ carriers, with direct sources for DHL and 20 national posts and couriers.
  • Smart alerts. Status changes with a route map, a warning when a parcel stops moving, and failed deliveries that are never mistaken for deliveries.
  • For sellers. Order numbers, customers, tags and notes; CSV import and export; seller mode; delivery-time statistics per carrier.
  • Customer tracking pages under your shop name, showing carrier data and nothing of yours.
  • Web dashboard and JSON API, signed in from Telegram with no passwords.
  • Private by design. One Docker container, one SQLite file, no third-party analytics, offline geocoding, English and Italian.

Web dashboard: KPIs, shipments that need attention, weekly chart, carriers

Quick start

You need Docker with Compose, a bot token from @BotFather and your numeric Telegram user ID.

git clone https://github.com/bernalli/parcel-tracker-bot.git
cd parcel-tracker-bot
cp .env.example .env
# Edit .env: TELEGRAM_BOT_TOKEN, OWNER_ID and (recommended) TRACK17_API_KEY.
docker compose up -d

Send /start to your bot, then paste a tracking number. Don't know your ID? Start the bot anyway and send /whoami.

To open the web dashboard, add these to .env, run docker compose up -d again, and send /web to the bot:

WEB_ENABLED=true
WEB_PUBLIC_URL=http://localhost:8080

Releases are also published as signed images on ghcr.io/bernalli/parcel-tracker-bot (latest or a version such as 0.4.0). For a public address, HTTPS and backups, read operations.

Using the bot

Everything is reachable from /menu with buttons. You can also just type:

You send The bot
A tracking number, also with spaces, after a label or inside a carrier link Starts tracking it and asks for a name
Several codes, one per line, as a list or separated by commas Adds them all
A .csv file Imports the shipments it contains
/list Shows your active parcels
/web Sends a one-time sign-in link for the dashboard
/export Sends all your shipments as CSV
/forgetme Deletes everything stored about you
/help Lists everything else

Each parcel card has Update now, Events, Map, Rename, Details (order, customer, destination, tags, notes), Share (customer tracking link) and Remove. Notifications can be muted per status in Settings → Notifications.

Intercontinental route Out for delivery
Route map of an air shipment, drawn by the bot Map of a parcel out for delivery in Milan

Status updates come with a map of the route, rendered by the bot itself from OpenStreetMap data.

For online sellers

Turn on Seller mode in the settings: delivered parcels are archived automatically with a short notice, instead of the "did you receive it?" question meant for buyers. Then:

  • add shipments by pasting codes, uploading your shop's CSV export, or from your shop through the JSON API;
  • check Need attention for carrier problems and parcels with no news for a week, and get a Telegram warning when one stalls;
  • send customers a tracking link with your shop name on it;
  • compare carriers by delivery time and success rate.

The full workflow is in the sellers guide.

Shipment list with status, customer, carrier and last news

Customer tracking page under the shop's name, with progress and history
The tracking page your customer sees: your shop name, the carrier's data, nothing else.

Tracking sources

Source Setup Covers
17track API (recommended) TRACK17_API_KEY 2,000+ carriers worldwide, and the fallback for every parcel
DHL official API DHL_API_KEY DHL Express, DHL Paket / Deutsche Post, DHL eCommerce
Built-in web scrapers none UPS, USPS, FedEx, Royal Mail, La Poste, Deutsche Post, DPD, GLS, Correos, Correios, Canada Post, Australia Post, PostNL, bpost, Swiss Post, Österreichische Post, Aramex, Evri, Yodel, DHL
Detection only via 17track Amazon Logistics, China Post, EMS, Japan Post, Singapore Post

The scrapers are best effort: carriers change their sites and some only render tracking with JavaScript. When a scraper cannot read a parcel, 17track takes over. International postal codes (RR…IT, CP…DE, LX…CN) are validated and show their postal operator straight away. Missing a courier? Write a plugin in about 50 lines. Details and patterns are in trackers and api-keys.

Configuration

.env.example lists every setting with its default. The essentials:

Variable Default Purpose
TELEGRAM_BOT_TOKEN required Bot token from @BotFather
OWNER_ID required Your Telegram ID; always an admin
TRACK17_API_KEY empty Universal tracking source and fallback
MAX_ACTIVE_SHIPMENTS 20 Per user; 0 for no limit
STALL_ALERT_DAYS 7 Warn about parcels with no news; 0 turns it off
WEB_ENABLED / WEB_PUBLIC_URL false / http://localhost:8080 Web dashboard and the base of the links the bot sends
DEFAULT_LANGUAGE en en or it; each user can switch
DATA_RETENTION_DAYS 180 Delete archived parcels after N days

Privacy and security

  • Only tracking numbers leave your server, to the carrier or 17track. Names, customers, addresses and notes stay in your SQLite file.
  • Geocoding is offline (GeoNames); map tiles are fetched by the server, never by a visitor's browser.
  • The container runs as a non-root user with a read-only filesystem, no capabilities and resource limits.
  • The dashboard uses single-use sign-in links, hashed sessions and tokens, CSRF protection and a strict Content-Security-Policy.
  • /forgetme erases a user; archived parcels expire after DATA_RETENTION_DAYS.

Found a vulnerability? Please report it privately: see SECURITY.

Documentation

Contributing

Bug reports, couriers, translations and documentation fixes are welcome. Read CONTRIBUTING for the development setup, and try the dashboard on demo data with python scripts/demo_web.py. This project follows the code of conduct.

License

MIT — see LICENSE. Copyright © 2026 Samuele Martinalli and contributors. Map data © OpenStreetMap contributors, © CARTO; place names from GeoNames (CC BY 4.0), see NOTICE.

About

Self-hosted Telegram bot tracking parcels across 24+ couriers worldwide — offline route maps, carrier auto-detect, auto-quarantine, plugin architecture

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages