python-escpos: A Python Library for ESC/POS Receipt Printers
Python library to manipulate ESC/POS printers. python-escpos - Python library to manipulate ESC/POS Printers Description =========== ..
At a glance
- What is it?
- python-escpos is an MIT-licensed library that sends text, images, barcodes, and QR codes to ESC/POS receipt printers over USB, network, or serial. It uses a printer profile database to adapt commands, but its reliance on external dependencies and profile accuracy are key trade-offs.
- Who is it for?
- Adopt python-escpos if you need a Python-native way to drive ESC/POS printers over USB, network, or serial and you can supply a matching printer profile. Avoid it if you need offline dependency management, non-POS printers, or you cannot test against real hardware.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 14, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What It Solves and Who It Is For
python-escpos addresses a narrow but persistent problem: generating the exact byte sequences that ESC/POS thermal receipt printers expect. These printers, defined by Epson's command set, are everywhere in retail and hospitality, but they do not speak a high-level protocol. You either hand-assemble escape sequences or use a library. This project targets Python developers building point-of-sale systems, kitchen ticket printers, or label printing tools. The README positions it as a way to access all printers handled by ESC/POS commands from a Python application. It is not a general-purpose printing library; it is specifically for the Epson-defined command family. If your hardware does not understand ESC/POS, this is the wrong tool from the start.
How It Works: Profiles and Command Generation
The core mechanism is a translation layer. The library exposes high-level methods like text(), image(), barcode(), and qr(), and internally converts those calls into ESC/POS byte sequences. The important detail is the profile system. The README states that since supported commands differ from printer to printer, the software tries to automatically apply the right settings for the printer that you set. These settings come from a separate project, escpos-printer-db, which is also used by the PHP library escpos-php. When you instantiate a printer class, you pass a profile parameter, for example profile="TM-T88III". That profile tells the library which commands to emit for that specific model. Without a profile, the library falls back to generic behavior, which the README warns against: it is highly recommended to include a matching profile. This design means the library's correctness depends on the accuracy of an external database that you do not control.
Getting Started: Three Connection Types
The README shows three concrete ways to instantiate a printer. For USB, you need the vendor and product IDs: p = Usb(0x04b8, 0x0202, 0, profile="TM-T88III"). For network printers, you pass an IP address: kitchen = Network("192.168.1.100", profile="TM-T88III"). For serial, you specify the device file and serial parameters: p = Serial(devfile='/dev/tty.usbserial', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=1.00, dsrdtr=True, profile="TM-T88III"). Once the object exists, you call methods like p.text("Hello World\n"), p.image("logo.gif"), p.barcode('4006381333931', 'EAN13', 64, 2, '', ''), and p.qr("You can readme from your smartphone"). The barcode method takes the data, symbology, height, width, and two empty strings for alignment and position. The serial example shows a 9600 baud, 8N1 configuration with flow control enabled. These examples are direct from the README, so they are reliable starting points, but you will need to adjust the USB IDs and serial port names to your hardware.
Dependencies: Five External Libraries
The library does not implement everything from scratch. It depends on pyusb for USB printers, pyserial for serial printers, Pillow for image printing, qrcode for QR code generation, and python-barcode for barcode generation. This is a pragmatic choice: those libraries handle the low-level hardware communication and image encoding. But it also means installation is not a single pip install with no side effects. You need native USB or serial support, and Pillow is a heavy dependency for a receipt printer library. The README lists these as dependencies without version pins, so you may encounter version conflicts in an existing Python environment. If you are deploying to a locked-down POS terminal, pulling in five extra packages could be a problem. The upside is that you do not need to write your own barcode encoder or QR generator, which are non-trivial.
Limitations and Wrong Use Cases
The most obvious limitation is the reliance on profiles. If your printer is not in escpos-printer-db, or if the profile is wrong, the library may send commands that the printer interprets incorrectly, producing garbled output or no output at all. The README's note to include a matching profile implies that without one, behavior is unpredictable. Another limitation is that the library is focused on receipt printers. It will not handle label printers with different command sets, nor will it handle modern cloud-connected printers that use their own protocols. The README explicitly says it accesses printers handled by ESC/POS commands, so anything outside that is unsupported. Also, the library does not appear to handle bidirectional communication, such as reading printer status or paper-out sensors. The examples only send data; there is no mention of reading responses. For a POS system that needs to detect paper jams, that is a gap you must fill yourself.
Alternative: escpos-php and Direct Command Generation
The most direct alternative is escpos-php, which the README mentions as also using escpos-printer-db. That project is written in PHP, so it is not a drop-in replacement for a Python stack. The difference in approach is the language ecosystem: if your backend is PHP, you would use escpos-php; if it is Python, you use python-escpos. But there is a more fundamental alternative: writing raw ESC/POS bytes yourself. You can find the Epson command reference and send bytes directly over a socket or serial port. That gives you complete control over every byte, but you lose the convenience of high-level methods like image() and qr(). You also have to handle the same profile differences yourself. For a simple text-only receipt, raw bytes are trivial. For images and QR codes, you would need to implement the raster format conversion, which is exactly what python-escpos does for you. So the choice is between using this library and reimplementing its core logic.
Maintenance and License Considerations
The project is licensed under MIT, which is permissive and allows commercial use without copyleft obligations. The repository is not archived, and the last push was in December 2023 with release v3.1, so there is recent activity. However, the maintenance model depends on the escpos-printer-db project, which is external. If that database stops updating, new printer models will not gain profiles, and the library's usefulness will decline. The README does not specify a release cadence or a long-term support policy. As of the latest release, v3.1, the API appears stable, but the 3.0 release was a major version bump, which may have introduced breaking changes. You should check the changelog for migration notes before upgrading from a 2.x version. The license is clean, but the dependency chain means you are also relying on the licenses of pyusb, pyserial, Pillow, qrcode, and python-barcode, all of which are permissive, but you should verify each in your environment.
Editorial conclusion
Adopt python-escpos if you need a Python-native way to drive ESC/POS printers over USB, network, or serial and you can supply a matching printer profile. Avoid it if you need offline dependency management, non-POS printers, or you cannot test against real hardware. Before adopting, verify that your printer model has a profile in escpos-printer-db and that the required native dependencies (pyusb, pyserial, Pillow, qrcode, python-barcode) install cleanly in your environment. Also check the project's issue tracker for unresolved problems with your specific printer model, as the library's behavior depends heavily on profile accuracy.
Community notes