CLI and GUI for printing text, to-do lists, and images on MXW01 58mm BLE thermal printers from macOS.
A Python tool for sending text or images to a cheap 58mm Bluetooth Low Energy thermal printer (the kind sometimes sold as "cat printers"). It renders text to a 384px-wide bitmap using Pillow, then sends it over BLE using bleak.
This targets the MXW01 printer specifically. The MXW01 uses a different protocol from the more common GB01/GB02/GB03 family. See "Protocol differences" below.
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtGrant Bluetooth permission to your terminal app under System Settings > Privacy & Security > Bluetooth.
These printers use BLE, not classic Bluetooth. Do not try to pair them through the macOS Bluetooth panel. The scripts connect directly.
# Print text
python catprint.py "Hello world"
# With a title header
python catprint.py -t "Shopping List" "- Milk\n- Eggs\n- Bread"
# From a file
python catprint.py -f notes.txt
# Pipe from stdin
echo "Remember to call Mom" | python catprint.py
# Print an image
python catprint.py --image photo.png
# Print from clipboard
python catprint.py --clipboard
# Adjust font size, font, and intensity
python catprint.py --font-size 16 --font helvetica --intensity 0x80 "Small and light"
# Preview without printing (saves preview.png)
python catprint.py --preview -t "Test" "some text"| Flag | Description | Default |
|---|---|---|
-t, --title |
Bold title with separator line | none |
-f, --file |
Read text from a file | none |
-i, --image |
Print an image file directly | none |
--clipboard |
Print image from clipboard | off |
--font-size |
Body text size in points | 20 |
--font |
Font name or path (see presets in source) | menlo |
--dither |
Dithering for images: threshold, floyd-steinberg, atkinson | floyd-steinberg |
--intensity |
Print darkness (1-255, or hex like 0x5d) | 0x5d |
--preview |
Save preview.png instead of printing | off |
python catprint_gui.pyTabbed interface with text and image modes, live preview, adjustable font/size/intensity, and clipboard paste.
The MXW01 does not use the standard GB01/GB02/GB03/GT01 protocol (0x51 0x78 header). Key differences:
| GB02 family | MXW01 | |
|---|---|---|
| Header bytes | 0x51 0x78 |
0x22 0x21 |
| Control commands | single characteristic | characteristic ae01 |
| Image data | same characteristic as control | separate characteristic ae03 |
| Notifications | varies | characteristic ae02 |
| Data encoding | run-length or byte-packed per row | raw 48-byte rows (384 bits) |
| Print flow | lattice start/end wrapping | PrintRequest with line count, then raw data, then FlushData |
This project builds on protocol research and code from several open source projects:
clementvp/mxw01-thermal-printer (MIT)
https://github.com/clementvp/mxw01-thermal-printer
By Clement van Peuter. TypeScript library for the MXW01 printer. This was the primary reference for the MXW01-specific protocol: the 0x22 0x21 packet format, BLE characteristic UUIDs (ae01/ae02/ae03), command IDs (0xA1 through 0xAD), and the CRC8 lookup table. The protocol handling in catprint.py is a Python port of this work.
rbaron/catprinter (MIT) https://github.com/rbaron/catprinter By rbaron. Python CLI for GB01/GB02 thermal printers using bleak. This project inspired the general approach (Python + bleak + Pillow, render to bitmap then send over BLE). The GB02 protocol code itself was not used since the MXW01 speaks a different protocol, but the project structure and the idea of using bleak on macOS came from here.
NaitLee/Cat-Printer (GPL-3.0) https://github.com/NaitLee/Cat-Printer By NaitLee. Broader thermal printer tool supporting many models. Referenced during development for understanding the wider cat-printer ecosystem and model detection, but no code was taken from this project.
This is not a fork of any single project. It is a new Python implementation that combines ideas from the projects listed above. Here is what is new or different:
- MXW01 protocol ported to Python. The protocol logic (packet construction, CRC8, BLE characteristics, command sequence) was translated from clementvp's TypeScript into Python. The original is a full framework-agnostic library with adapters for Web Bluetooth, Node, etc. This version is a simple single-file script using bleak.
- Text rendering. None of the reference projects handle text input directly. This project renders plain text to a 384px bitmap using Pillow, with word wrapping, configurable fonts (15 macOS system font presets), title headers, and separator lines.
- Dithering. Floyd-Steinberg and Atkinson dithering implementations for printing photographs and grayscale images. These are original implementations (standard algorithms, not copied from any of the reference repos).
- Clipboard printing. Grab an image from the macOS clipboard and print it directly.
- tkinter GUI. A tabbed GUI (
catprint_gui.py) with live preview, font/size controls, image browsing, clipboard paste, and a print button. Not present in any of the reference projects. - macOS-only. The reference projects target multiple platforms. This one only targets macOS on Apple Silicon and uses macOS system fonts.
MIT. See LICENSE.
The MXW01 protocol implementation is derived from clementvp/mxw01-thermal-printer (MIT). The general approach is inspired by rbaron/catprinter (MIT).