A Python library for Brother P-touch label printers.
- Support for Brother P-touch label printers (PT-E550W, PT-P750W, PT-P900, PT-P900W, PT-P910BT, PT-P950NW)
- Network (TCP/IP) and USB connections
- Text labels with customizable fonts and alignment
- Image label printing
- Multi-label printing with half-cut support (saves tape)
- Heat shrink tube support (HSe 2:1 and 3:1 series on PT-E550W/P750W/P900/P900W/P950NW)
- High resolution mode support
- TIFF compression for efficient data transfer
pip install ptouch- Python 3.11+
- Pillow
- packbits
For USB support:
- pyusb
Comprehensive documentation is available at ptouch.readthedocs.io including:
| Printer | Resolution | High-Res | Pins | Max Tape Width | Class |
|---|---|---|---|---|---|
| PT-E550W | 180 DPI | 360 DPI | 128 | 24mm | PTE550W |
| PT-P750W | 180 DPI | 360 DPI | 128 | 24mm | PTP750W |
| PT-P900 | 360 DPI | 720 DPI | 560 | 36mm | PTP900 |
| PT-P900W | 360 DPI | 720 DPI | 560 | 36mm | PTP900W |
| PT-P910BT | 360 DPI | 720 DPI | 560 | 36mm | PTP910BT |
| PT-P950NW | 360 DPI | 720 DPI | 560 | 36mm | PTP950NW |
| Type | Widths | Class | Notes |
|---|---|---|---|
| TZe (Laminated) | 3.5mm, 6mm, 9mm, 12mm, 18mm, 24mm, 36mm | Tape*mm |
All printers |
| HSe 2:1 (Heat Shrink) | 5.8mm, 8.8mm, 11.7mm, 17.7mm, 23.6mm | HeatShrinkTube*mm |
E550W/P750W/P900/P900W/P950NW |
| HSe 3:1 (Heat Shrink) | 5.2mm, 9.0mm, 11.2mm, 21.0mm, 31.0mm | HeatShrinkTube3_1_*mm |
E550W/P750W: up to 21mm; P900: all |
To add support for a new P-touch printer, create a subclass of LabelPrinter in ptouch/printers.py:
from ptouch.printer import LabelPrinter, TapeConfig
from ptouch.tape import Tape12mm, Tape24mm # etc.
class PTP710BT(LabelPrinter):
"""Brother PT-P710BT label printer."""
# USB product ID (required for USB connections)
USB_PRODUCT_ID = 0x20XX # Replace with actual product ID
# Print head specifications (from Brother raster command reference)
TOTAL_PINS = 128 # Total pins in print head
BYTES_PER_LINE = 16 # TOTAL_PINS / 8
RESOLUTION_DPI = 180 # Base resolution
RESOLUTION_DPI_HIGH = 360 # High resolution (0 if not supported)
# Capability flags - what the printer supports
SUPPORTS_AUTO_CUT = True
SUPPORTS_HALF_CUT = True
SUPPORTS_PAGE_NUMBER_CUTS = True
# Default values for each feature (used when not specified at print time)
DEFAULT_USE_COMPRESSION = True
DEFAULT_AUTO_CUT = True
DEFAULT_HALF_CUT = True
DEFAULT_HIGH_RESOLUTION = False
DEFAULT_PAGE_NUMBER_CUTS = False
# Pin configuration for each tape width
# Values from Brother raster command reference PDF
PIN_CONFIGS = {
Tape12mm: TapeConfig(left_pins=29, print_pins=70, right_pins=29),
Tape24mm: TapeConfig(left_pins=0, print_pins=128, right_pins=0),
# Add more tape sizes as needed
}The pin configuration values (left_pins, print_pins, right_pins) can be found in the
Brother raster command reference documentation for your printer model.
To add a new tape type, create a subclass of Tape in ptouch/tape.py:
from ptouch.tape import Tape
class Tape48mm(Tape):
"""48mm tape."""
width_mm = 48Then add the corresponding TapeConfig entries to each printer class that supports the tape
When the package is installed, the ptouch command is available (or use python -m ptouch when running from source):
# Print text label via network (uses PIL default font)
ptouch "Hello World" --host 192.168.1.100 --printer P900 --tape-width 36
# Print with custom font
ptouch "Hello World" --host 192.168.1.100 --printer P900 \
--tape-width 36 --font /path/to/font.ttf
# Print multiple labels (half-cut between, full cut after last)
ptouch "Label 1" "Label 2" "Label 3" --host 192.168.1.100 \
--printer P900 --tape-width 12
# Print multiple labels with full cuts between each
ptouch "Label 1" "Label 2" --full-cut --host 192.168.1.100 \
--printer P900 --tape-width 12
# Print image label via USB
ptouch --image logo.png --usb --printer E550W --tape-width 12
# Print with fixed font size (disables auto-sizing)
ptouch "Test" --host 192.168.1.100 --printer P900 --tape-width 24 \
--font-size 48 --high-resolution --align left top --margin 5
# Print 5 copies of a label
ptouch "Asset Tag" --copies 5 --host 192.168.1.100 \
--printer P900 --tape-width 12
# Print label with fixed width (50mm)
ptouch "Short" --width 50 --host 192.168.1.100 \
--printer P900 --tape-width 12from ptouch import (
ConnectionNetwork,
PTP900,
TextLabel,
Tape36mm,
)
# Connect to printer
connection = ConnectionNetwork("192.168.1.100")
printer = PTP900(connection, high_resolution=True)
# Create and print text label
label = TextLabel(
"Hello World",
Tape36mm,
font="/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
align=TextLabel.Align.CENTER,
)
printer.print(label)
# Or use a pre-loaded ImageFont (auto-sized by default)
from PIL import ImageFont
font = ImageFont.truetype("/path/to/font.ttf", size=48)
label = TextLabel("Custom Font", Tape36mm, font=font)
# Use ImageFont with its built-in size (disable auto-sizing)
label = TextLabel("Fixed Size", Tape36mm, font=font, auto_size=False)
# For quick testing, use the default font (requires Pillow 10.1+)
label = TextLabel("Quick Test", Tape36mm, font=ImageFont.load_default())from PIL import Image
from ptouch import ConnectionNetwork, PTP900, Label, Tape36mm
connection = ConnectionNetwork("192.168.1.100")
printer = PTP900(connection)
image = Image.open("label.png")
label = Label(image, Tape36mm)
printer.print(label, margin_mm=3.0)from ptouch import ConnectionUSB, PTE550W, TextLabel, Tape12mm
connection = ConnectionUSB()
printer = PTE550W(connection)
label = TextLabel(
"USB Label",
Tape12mm,
font="/path/to/font.ttf",
)
printer.print(label)Print multiple labels in a single job with half-cuts between labels to save tape:
from ptouch import ConnectionNetwork, PTP900, TextLabel, Tape12mm
connection = ConnectionNetwork("192.168.1.100")
printer = PTP900(connection)
labels = [
TextLabel("Label 1", Tape12mm, font="/path/to/font.ttf"),
TextLabel("Label 2", Tape12mm, font="/path/to/font.ttf"),
TextLabel("Label 3", Tape12mm, font="/path/to/font.ttf"),
]
# Half-cuts between labels (default), full cut after last
printer.print_multi(labels)
# Or use full cuts between all labels
printer.print_multi(labels, half_cut=False)Text alignment can be combined using the | operator:
from ptouch import TextLabel
# Horizontal: LEFT, HCENTER, RIGHT
# Vertical: TOP, VCENTER, BOTTOM
# Combined: CENTER (= HCENTER | VCENTER)
align = TextLabel.Align.LEFT | TextLabel.Align.TOP
align = TextLabel.Align.RIGHT | TextLabel.Align.BOTTOM
align = TextLabel.Align.CENTER # centered both waysNote: Align is also available as a backwards-compatible alias at package level.
usage: ptouch [-h] [--image FILE] (--host IP | --usb) --printer {E550W,P750W,P900,P900W,P950NW}
--tape-width {3.5,6,9,12,18,24,36} [--font PATH] [--font-size PX]
[--align H V] [--high-resolution] [--margin MM] [--no-compression]
[--full-cut] [--copies N] [--width MM] [text ...]
positional arguments:
text Text to print. Multiple strings create multiple labels
with half-cut between (required unless --image is used)
options:
--image, -i FILE Image file to print instead of text
--host, -H IP Printer IP address for network connection
--usb Use USB connection
--printer, -p Printer model
--tape-width, -t Tape width in mm
--font, -f PATH Path to TrueType font file (uses PIL default if not specified)
--font-size PX Font size in pixels (disables auto-sizing to 80% of print height)
--align, -a H V Horizontal and vertical alignment (default: center center)
--high-resolution Enable high resolution mode
--margin, -m MM Margin in mm (default: 2mm)
--no-compression Disable TIFF compression
--full-cut Use full cuts between labels instead of half-cuts
--copies, -c N Number of copies to print (default: 1)
--width, -w MM Fixed label width in mm (default: auto-sized to content)
The library provides a hierarchy of exception classes for targeted error handling:
from ptouch import (
PrinterConnectionError, # Base exception for all connection errors
PrinterNotFoundError, # Printer device not found
PrinterPermissionError, # Permission denied (USB requires sudo/udev rules)
PrinterNetworkError, # Network connection/communication errors
PrinterTimeoutError, # Connection or operation timeout
PrinterWriteError, # Failed to write data to printer
)
try:
printer.print(label)
except PrinterPermissionError:
print("Permission denied. Try running with sudo or configure udev rules.")
except PrinterTimeoutError:
print("Printer not responding. Check connection and power.")
except PrinterNotFoundError:
print("Printer not found. Check if device is connected.")
except PrinterConnectionError:
print("General connection error occurred.")All specific exceptions inherit from PrinterConnectionError, allowing you to catch all connection-related errors with a single except clause, or handle specific error types individually for more targeted error handling.
LGPL-2.1-or-later - see LICENSE for details.
Nicolai Buchwitz nb@tipi-net.de