A self-hosted web application for managing Bambu Lab 3D printers over your local network. Provides a REST API and web dashboard for monitoring printer status and submitting print jobs.
Works with any Bambu Lab printer in developer/LAN mode (or in Bambu Cloud mode with experimental support).
An iOS client is also available: BambuGateway iOS — print 3MF files from MakerWorld directly from your phone.
- Real-time printer status (state, temperatures, print progress, preparation stages)
- Pause, resume, cancel, and adjust speed of active prints
- AMS unit info (humidity, temperature) and external spool holder support
- AMS filament drying control (AMS 2 Pro and AMS HT)
- Upload, slice and print 3MF files from the browser, including custom filament profiles through orcaslicer-headless
- Automatic AMS tray matching for project filaments
- Multi-printer support
- Optional iOS Live Activities and push notifications via APNs
- REST API for automation and integration
- Runs entirely on your local network
You'll need a Bambu Lab printer with Developer Mode enabled — the access code and IP are in the printer's network settings.
docker run -d --name bambu-gateway \
-p 4844:4844 \
-v $(pwd)/data:/data \
ghcr.io/leolobato/bambu-gateway:latestOr with docker compose:
docker compose up -dOpen http://localhost:4844 and add your printer from the Settings page.
Requires Python 3.12+.
git clone https://github.com/leolobato/bambu-gateway.git
cd bambu-gateway
pip install -r requirements.txt
python -m appOpen http://localhost:4844 and add your printer from the Settings page. Runtime state — printer configuration, slice jobs, and their cached 3MF blobs — is saved under ./data/ (gitignored).
The gateway can send push notifications and Live Activity updates to the companion iOS app when a print changes state — paused, failed, completed, cancelled, offline, or flagged by the printer's health-monitoring system. When enabled, the iPhone shows a Live Activity on the Lock Screen and Dynamic Island with progress, remaining time, and current layer, updated in real time even when the app is closed.
Enabling this requires a paid Apple Developer account so you can mint an APNs Auth Key. The four required env vars are:
APNS_KEY_PATH=/path/to/AuthKey_KEYID.p8
APNS_KEY_ID=KEYID
APNS_TEAM_ID=TEAMID
APNS_BUNDLE_ID=org.yourname.BambuGateway
APNS_ENVIRONMENT=sandbox # or "production" for TestFlight / App Store buildsLeaving any of them empty disables push entirely. The iOS app degrades gracefully in that case — Live Activities still run locally while the app is foregrounded, but remote updates and notifications aren't delivered.
See docs/APNS.md for the full walkthrough: creating the
.p8 key, choosing sandbox vs. production, installing the key for Docker
deployments, rotating keys, and troubleshooting.
By default the gateway talks to printers directly over your LAN, which requires Developer Mode on each printer. If you'd rather not enable Developer Mode — or your printer isn't on the same network — you can instead connect through your Bambu Cloud account. The gateway logs in to Bambu's cloud and reaches your printers through it, so no IP, access code, or Developer Mode is needed.
Experimental, but working. Cloud mode is opt-in. Printer status, AMS, control commands (pause/resume/cancel/speed), camera, and cloud printing all function today, but the feature is newer and less battle-tested than LAN mode. If it fails to start, the gateway falls back to LAN mode automatically and the cloud endpoints return
503.
Cloud mode works by loading Bambu's official closed-source network plugin
(libbambu_networking.so) in an isolated subprocess. The approach — and the
Linux bridge that makes the plugin usable outside Bambu's own apps — is based on
Jarczak's fork of OrcaSlicer (OrcaSlicer-bambulab),
which first demonstrated authenticating and driving cloud printers through that
plugin on Linux. The plugin binary is downloaded from Bambu's CDN and verified (ELF magic
- SHA-256 manifest + pinned ABI version) before use.
x86_64 hosts only. Bambu ships
libbambu_networking.sofor x86_64 (amd64) only — there is no ARM build, so cloud mode does not work on ARM hosts (Apple Silicon, ARM64 Linux, Raspberry Pi)
Add these to your .env (or -e flags) and restart the container:
BAMBU_CLOUD_ENABLED=true
BAMBU_CLOUD_REGION=US # use CN for the China regionIn cloud mode the LAN printer settings (BAMBU_PRINTER_IP, access code, serial)
are ignored — your printers come from your Bambu account instead. The login
session is saved under ./data/ and survives restarts, so you only do the steps
below once.
Open the Settings page and use the Cloud Account section:
- Click Open Bambu sign-in and log in with your Bambu email and password (including any verification code) in the browser tab that opens.
- After signing in, your browser will try to open
http://localhost:13618/?ticket=…and show a "this site can't be reached" / "connection refused" page. That's expected. Copy the full URL from the browser's address bar — it contains your one-time login ticket. - Paste that URL into the field and click Complete sign-in.
Once signed in, the Cloud Account section shows your profile and region, and your
cloud printers start appearing on the dashboard. The login session is saved under
./data/, so you only do this once.
Printers are stored in data/printers.json by default (see
printers.example.json for the format). The file is created automatically on
first run — either seeded from environment variables or empty if none are set.
After that, manage printers through the Settings page at /settings. The
slice-job store (data/slice_jobs.json plus the data/slice_jobs/ blob dir)
is rooted at the same parent.
To use a custom path (e.g. a Docker volume mounted at /data):
python -m app -c /data/printers.json| Variable | Default | Description |
|---|---|---|
BAMBU_PRINTER_IP |
Printer IP(s), comma-separated — seeds initial config | |
BAMBU_PRINTER_ACCESS_CODE |
Printer access code(s), comma-separated | |
BAMBU_PRINTER_SERIAL |
Printer serial number(s), comma-separated | |
SERVER_HOST |
0.0.0.0 |
Server bind address |
SERVER_PORT |
4844 |
Server bind port |
LOG_LEVEL |
INFO |
Logging level |
MAX_FILE_SIZE_MB |
200 |
Maximum upload file size in MB |
ORCASLICER_API_URL |
OrcaSlicer Headless API URL (e.g. http://10.0.1.9:8070) — required for slicing |
|
BAMBU_CLOUD_ENABLED |
false |
Connect through your Bambu Cloud account instead of LAN — see Bambu Cloud mode |
BAMBU_CLOUD_REGION |
US |
Bambu account region: US or CN |
APNS_KEY_PATH |
Path to APNs Auth Key .p8 — see docs/APNS.md. All four APNS_* vars must be set to enable push |
|
APNS_KEY_ID |
10-character Key ID from the Apple Developer portal | |
APNS_TEAM_ID |
10-character Team ID from the Apple Developer portal | |
APNS_BUNDLE_ID |
Bundle ID of the iOS app receiving push | |
APNS_ENVIRONMENT |
production |
sandbox for dev builds, production for TestFlight / App Store |
Environment variables only seed the config on first run when no printers.json
exists.
| Method | Path | Description |
|---|---|---|
GET |
/api/health |
Health check |
GET |
/api/printers |
List printers with live status |
GET |
/api/printers/{id} |
Status for a single printer |
POST |
/api/printers/{id}/pause |
Pause current print |
POST |
/api/printers/{id}/resume |
Resume paused print |
POST |
/api/printers/{id}/cancel |
Cancel current print |
POST |
/api/printers/{id}/speed |
Set print speed (1–4: silent/standard/sport/ludicrous) |
GET |
/api/ams |
AMS units, trays, and external spool info |
POST |
/api/printers/{id}/ams/{ams_id}/start-drying |
Start AMS filament drying |
POST |
/api/printers/{id}/ams/{ams_id}/stop-drying |
Stop AMS filament drying |
POST |
/api/filament-matches |
Match project filaments to AMS trays |
POST |
/api/print |
Upload 3MF to default printer |
POST |
/api/print-stream |
Upload and print with SSE progress |
POST |
/api/print-preview |
Slice and preview without printing |
POST |
/api/parse-3mf |
Parse 3MF metadata without printing |
POST |
/api/stl-drafts |
Import an STL into an orcaslicer-headless draft for preview |
GET |
/api/stl-drafts/{id}/source.stl |
Stream the cached STL bytes for browser rendering |
POST |
/api/stl-drafts/{id}/layout |
Apply a preset layout action (auto-orient, rotate, center, arrange, reset) |
POST |
/api/stl-drafts/{id}/3mf |
Materialize the draft to a 3MF the print flow can consume |
GET |
/api/slicer/machines |
List slicer machine profiles |
GET |
/api/slicer/processes |
List slicer process profiles |
GET |
/api/slicer/filaments |
List slicer filament profiles |
GET |
/api/slicer/plate-types |
List available plate types |
GET |
/api/settings/printers |
List configured printers |
POST |
/api/settings/printers |
Add a printer |
PUT |
/api/settings/printers/{serial} |
Update a printer |
DELETE |
/api/settings/printers/{serial} |
Remove a printer |
GET |
/api/uploads/{id} |
Poll FTP upload progress |
Interactive API docs are available at /docs (Swagger UI).
Bambu Gateway integrates with orcaslicer-headless, a headless slicing server built on OrcaSlicer's engine. This enables:
- Custom filament profiles — use your own filament settings (temperature, flow, pressure advance, etc.) instead of being limited to built-in profiles
- Headless slicing — slice 3MF files on the server without needing OrcaSlicer's GUI, ideal for running on a Raspberry Pi or NAS
- Preview before printing — slice a file and review the result before sending it to the printer
Run the orcaslicer-headless server (see the orcaslicer-headless docs for full setup instructions), then point Bambu Gateway to it:
ORCASLICER_API_URL=http://10.0.1.9:8070When a slicer URL is configured, the web UI will show machine and filament profile selectors, and unsliced 3MF files will be sliced automatically before printing. Without it, only pre-sliced 3MF files can be printed.
bambu-gateway does not open .3mf ZIPs. All metadata extraction
(plates, filaments, thumbnails, used-filament dispatch, print
estimates) goes through orcaslicer-headless's HTTP API, which links
libslic3r directly. Set ORCASLICER_API_URL to point at it.
Required endpoints (consumed by app/slicer_client.py):
POST /3mf— upload, returns tokenGET /3mf/{token}/inspect— structured summaryGET /3mf/{token}/plates/{n}/thumbnail— PNG bytesDELETE /3mf/{token}— drop cached uploadPOST /slice/v2— slice, returns estimate + output token
Dropping a .stl on the Print page kicks off a draft preview owned by
orcaslicer-headless. The gateway proxies the import, caches the source
STL bytes locally so the browser can render them with Three.js, and
forwards layout actions to the slicer:
- Upload —
POST /api/stl-drafts(withmachine_profile,process_profile, optionalplate_type,auto_orient,arrange,center) imports the STL into the slicer and returns the initial scene plus asource_urlfor the cached STL bytes. - Preview — the SPA loads
source_urlwithSTLLoader, draws the printable bed, and applies each object'smesh_transformthen its instancetransformso the browser shows what the slicer sees. - Layout —
POST /api/stl-drafts/{id}/layoutruns preset actions (auto_orient,rotate_x_90,rotate_x_minus_90,rotate_y_90,rotate_y_minus_90,rotate_z_90,rotate_z_minus_90,center,arrange,reset) and returns the updated scene. - Accept —
POST /api/stl-drafts/{id}/3mfmaterializes the draft insideorcaslicer-headlessand returns a JSON payload with the slicer'sinput_token, a suggested filename, and the parsedThreeMFInfo. The SPA forwards an optional preview-render PNG (thumbnail_png_data_url) so the materialized 3MF carries a thumbnail that matches what the user accepted. From there the imported state carries the token forward — slice jobs reference the token instead of re-uploading bytes — and filament mapping, slicing settings, and printer upload work as with an uploaded 3MF.
Slice-job “original” downloads are prepared originals. For uploaded 3MF files and STL-derived projects, the gateway stores a 3MF after applying the selected machine, process, plate type, process overrides, and any STL preview thumbnail, but before slicing. The Jobs page downloads that prepared input so it matches the settings used for the slice.
V1 supports preset actions only — there is no freehand drag/rotate/scale in the browser; orcaslicer-headless remains the authority for STL orientation, arrange, and 3MF generation.
Bambu Gateway is the printer control plane and slicing web app in a suite of self-hosted projects that together replace the Bambu Handy app for printers in Developer Mode — keeping everything on your LAN, with no Bambu cloud.
Self-hosted services
- Bambu Gateway — this project.
- orcaslicer-headless — Headless OrcaSlicer wrapped in a REST API. Owns the filament/process/machine profile catalog (including custom user profiles) and does the actual slicing. Other services in the suite call it for slicing and profile data.
- bambu-spool-helper — Bridge between Spoolman and the printer's AMS. Links real spools to Bambu filament profiles (via
orcaslicer-headless) and pushes the settings to a chosen tray over MQTT.
iOS apps
- bambu-gateway-ios — Phone client for
bambu-gateway. Browse printers, import 3MF files (including from MakerWorld), preview G-code, and start prints. Live Activities and push notifications for print state changes. - spool-browser — Phone client for
bambu-spool-helperand Spoolman. Browse the spool inventory, link Bambu profiles to spools, activate filaments on the AMS, and print physical spool labels over Bluetooth.
Bambu Gateway is available under the MIT License. See LICENSE for details.