Self-hosted push notifications for Bambu Lab printers
Your printer already knows when it's done.
Now your phone will too.
bambu-ntfy watches your Bambu Lab printer's local MQTT status feed and pushes a notification to your own ntfy server the moment something changes without needing the Bambu Lab cloud.
Bambu Lab printers expose a local MQTT broker over TLS once LAN mode is enabled. bambu-ntfy stays connected to it, watches every status report, and turns the changes that matter into a push notification through ntfy.
The printer knows exactly what's happening. You have to go look.
Bambu Handy will tell you what's going on if you use the bambu cloud, but that means trusting Bambu's servers with your data. If you use LAN-only / developer mode you lose Bambu Handy and it's notifications.
bambu-ntfy fixes that issue: it stays connected to the printer's local MQTT broker and turns the events that matter into a push notification, entirely on your own network.
One connection per printer
Each configured printer gets its own persistent MQTT connection, authenticated as bblp with the printer's access code. A dropped connection reconnects automatically with backoff.
Reports, not polling
On connect it asks the printer for a full status push, then just listens. Every subsequent report is diffed against the last known state in memory.
Only real changes notify
State transitions, new or cleared print errors, and new or cleared HMS conditions each fire exactly one notification, pushed to a topic on a self-hosted ntfy server you control.
Everything worth knowing about a print, pushed to your phone.
Full print state tracking
Follows the printer’s own state including idle, preparing, slicing, running, paused, finished, and failed, then notifies on every transition.
Print error codes
Surfaces print_error / mc_print_error_code as soon as the printer reports one, and logs when it clears.
HMS warnings, with severity
Decodes Health Management System entries into a readable code, severity (fatal/serious/common/info), and a friendly description where known, then notifies again when they clear.
Connection loss & recovery
Notifies you the moment the MQTT connection to a printer drops, and again once it reconnects, so silence never looks like "all is well".
Multiple printers, one instance
Configure up to nine printers with numbered environment variables. Each gets its own MQTT connection on its own thread, all sharing one ntfy target.
Bring your own ntfy
Notifications post to a topic on any self-hosted (or hosted) ntfy server you point it at. Both token or basic-auth are supported, and nothing routes through a third party.
Local network only
Talks to the printer over its LAN-mode MQTT broker with the on-device access code. Nothing about the printer connection touches Bambu's cloud.
Minimal container
A small non-root Alpine image with pip, setuptools, and wheel stripped from the final image after install; nothing but the app and its two dependencies at runtime.
Notification events
Every notification is prefixed with the printer's configured name and sent to your ntfy topic with an ntfy priority that matches how urgently it deserves your attention.
gcode_state → notification
IDLEIdle 2PREPAREPreparing 3SLICINGSlicing 3RUNNINGPrint started 3PAUSEPrint paused 4FINISHPrint finished 3FAILEDPrint FAILED 5Unrecognized states still notify, using the raw state name and default priority.
Known HMS codes
0300-2000AMS communication error0500-4000Heatbed temperature abnormal0700-4000Nozzle temperature abnormal0C00-2000Filament runout0E00-2000Toolhead communication error1200-8000Nozzle clog / extrusion abnormalAll other HMS code will still triggers a notification with the raw code and decoded severity but without a friendly description. Look codes up at wiki.bambulab.com/en/hms.
Technical info
Stack
Python 3.13python:3.13-alpine3.24 base imagepaho-mqttMQTT client, TLS connection to the printerrequestsPosts notifications to the ntfy HTTP APIthreadingOne daemon thread per configured printer
Container image
- Runs as a non-root user on
python:3.13-alpine3.24. - No exposed ports — the container only makes outbound MQTT and HTTPS connections.
pip,setuptools, andwheelare uninstalled after dependencies are installed, so the runtime image ships with no package manager at all.- Only two runtime dependencies:
paho-mqttandrequests.
Configuration
NTFY_URLBase URL of your ntfy instance, e.g. https://ntfy.example.com. Required.NTFY_TOPICTopic to publish notifications to. Required.NTFY_TOKENBearer token for ntfy, if your instance requires auth. Alternative to username/password.NTFY_USERNAME / NTFY_PASSWORDBasic auth for ntfy, used if no token is set.PRINTER_IP / PRINTER_SERIAL / PRINTER_ACCESS_CODESingle-printer connection details. Serial and access code come from the printer's network settings screen.PRINTER_NAME / PRINTER_PORTOptional for single printer use. Friendly name for notifications, and MQTT port (defaults to 8883).PRINTER_1_IP … PRINTER_9_IP (+ _SERIAL, _ACCESS_CODE, _NAME, _PORT)Numbered variables for multiple printers. Can be combined with the single-printer set above.LOG_LEVELPython logging level. Defaults to INFO.Installation
First, enable LAN Only Mode (or Developer Mode, depending on firmware) on the printer under Settings → Network. That screen also shows the 8-digit Access Code and the printer's Serial Number you'll need below.
Run the container:
docker run -d \ --name bambu-ntfy \ -e NTFY_URL=https://ntfy.example.com \ -e NTFY_TOPIC=bambu-printer \ -e PRINTER_IP=192.168.1.50 \ -e PRINTER_SERIAL=00M00A000000000 \ -e PRINTER_ACCESS_CODE=12345678 \ -e PRINTER_NAME="Bambu X1C" \ pocketsized/bambupushnotifier
No ports to be published as bambu-ntfy only makes outbound connections to the printer and to your ntfy server. Add NTFY_TOKEN or NTFY_USERNAME /NTFY_PASSWORD if your ntfy instance requires auth.
Run the container:
services: bambu-ntfy: image: pocketsized/bambupushnotifier container_name: bambu-ntfy restart: unless-stopped environment: # --- ntfy (shared across all printers) --- NTFY_URL: "https://ntfy.example.com" NTFY_TOPIC: "bambu-printer" NTFY_TOKEN: "" # or use NTFY_USERNAME / NTFY_PASSWORD # NTFY_USERNAME: "" # NTFY_PASSWORD: "" # --- One printer --- PRINTER_IP: "192.168.1.50" PRINTER_SERIAL: "00M00A000000000" PRINTER_ACCESS_CODE: "12345678" PRINTER_NAME: "Bambu X1C" # --- Or multiple printers (numbered, up to _9) --- # PRINTER_1_IP: "192.168.1.50" # PRINTER_1_SERIAL: "00M00A000000000" # PRINTER_1_ACCESS_CODE: "12345678" # PRINTER_1_NAME: "X1C Upstairs" # # PRINTER_2_IP: "192.168.1.51" # PRINTER_2_SERIAL: "00M00B000000000" # PRINTER_2_ACCESS_CODE: "87654321" # PRINTER_2_NAME: "P1S Garage" LOG_LEVEL: "INFO"
The single-printer and numbered variables can be combined — a plainPRINTER_* set plus any number of PRINTER_1_* … PRINTER_9_*sets all run side by side.
About the AI use here
I understand the reservations surrounding AI-generated software. Relying on a tool to write code without fully understanding either the tool or the output is risky and many wish to avoid it. However, developer assistance tools like autocomplete or online reference platforms have been standard practice for years before AI came on the scene.
Both the notifier and this website were developed with the help of AI coding assistants. Depending on the task, this assistance ranged from simple word completion to refactoring functions for modern best practices. Crucially, every line of code was individually reviewed, vetted, and thoroughly tested by me.
Finally, AI involvement is strictly confined to the build process: bambu-ntfy itself contains no embedded AI features or runtime models.