- -50%
What is QZ Tray Lite?
QZ Tray Lite is a local print server that fully emulates the QZ Tray protocol but without its massive infrastructure. It enables receipt printing to thermal printers directly from your browser using qz-tray.js — and your frontend code requires zero changes.
If you've ever configured the original QZ Tray for silent printing, you know the pain: generate key pairs, distribute certificates, set up a backend signing endpoint, collect {call, params, timestamp}, compute SHA-256 hex, sign it with RSA private key, return base64 to browser, and pray. Any mistake — and instead of a receipt, your user sees an "Allow?" dialog.
QZ Tray Lite removes all of this.
-
The
signatureandsignAlgorithmfields are ignored. Your client sends signatures as usual and receives successful responses — it never knows it's talking to a different implementation. -
No backend signing endpoint required. The trust chain reduces to just two parties: browser ↔ local process.
-
Reuses existing certificates — for example, from an installed QZ Tray (Windows already trusts
CN=localhost), or you can provide your own PKCS#12.
Key Advantages
| Feature | Original QZ Tray | QZ Tray Lite |
|---|---|---|
| Installation size | 164 MB, 232 files (including JRE) | 90 KB, 15 .py files |
| Runtime | Embedded Java | Python 3.12+ (already on your system) |
| Silent printing requirements | Certificate + signing backend + dialogs configuration | Nothing extra |
| Frontend changes | — | None — qz-tray.js works as-is |
| Code readability | 40 MB of bytecode | 2,600 lines with comments |
| Auto-port failover | Yes | Yes |
How It Works
Browser connects via WebSocket to localhost (wss://8181 or ws://8182). QZ Tray Lite responds to the same calls as the original:
-
getVersion— reports 2.2.6 (compatible with modernqz-tray.js); -
certificate— accepts client certificate and confirms; -
printers.find/printers.getDefault— enumerates system printers viawin32print; -
print— queues jobs for printing.
A per-printer sequential queue ensures copies don't interleave and long jobs don't block the WebSocket.
Supported Print Modes
1. Raw ESC/POS
-
Text with encoding selection (CP1250–CP1258, IBM8xx, ISO-8859-x, GBK, Big5, Shift_JIS, UTF-8).
-
Cyrillic:
CP1251+ESC tcommand in the receipt (page number depends on firmware). -
Images: full support for
ESC *(single/double/triple, including legacy) andGS v 0. Quantization:luma,alpha,black. -
Activated via
type: "raw"withoptions.language: "escpos".
2. Pixel (GDI) Printing
-
Raster printing through printer driver with
scaleContent,margins,units(inches or mm). -
No
options.languagerequired — ideal for logos, barcodes, labels. -
Activated via
type: "pixel".
Security Considerations
Important: QZ Tray Lite is designed for trusted cashier workstations in local networks. It deliberately does not validate:
-
request signatures (
signature,signAlgorithm); -
client certificates and trust chains;
-
timestamps (±15 minutes window in original);
-
allowed.dat/blocked.dataccess control.
Practical implication: any page open in the browser on this machine can print. This is an acceptable trade-off for a dedicated POS computer. However, do not expose the server on 0.0.0.0 or use it on machines where users browse arbitrary websites.
All actions are logged — each request, each byte, each URL loaded via format: "image" without explicit flavor.
Installation & Quick Start
Requirements: Windows 10/11, Python 3.12+
git clone <repository> cd qz-tray-lite python -m pip install -r requirements.txt
Run:
python main.py
The server automatically:
-
finds a free port (if 8181 is busy, tries 8282, etc.);
-
uses certificate from original QZ Tray if installed, or allows custom
--keystore/--storepass; -
starts both WSS and WS listeners for compatibility.
Background operation: included tools/service.ps1 installs QZ Tray Lite as a Windows Service or Scheduled Task (auto-selected based on environment). Supports log rotation, health monitoring, and restart policies.
What's NOT Implemented
We intentionally omitted features rarely used in POS scenarios:
-
serial,usb,hid,file,networking; -
printers.detail,startListening/getStatus; -
pixel printing from
pdfandhtml; -
imageEncoding: GS_L,quantization: dither,rotation/orientation.
Calls to these return clear errors rather than silently failing.
Testing & Debugging
The tools/probe.py utility:
-
performs QZ Tray handshake;
-
sends test print jobs (checkerboard logo detects bit shifts, frame detects edge clipping);
-
demonstrates that signatures aren't validated — even invalid signatures pass.
python tools/probe.py --print XP-58 # test receipt python tools/probe.py --print XP-58 --pixel # pixel mode
65 unit tests for ESC/POS image converter (831 lines) — expected bytes calculated manually against Epson specification.
Who Is This For?
-
POS system developers who want to eliminate bulky QZ Tray and simplify deployment across hundreds of workstations.
-
Integrators tired of configuring certificates and signing backends for each store.
-
Business owners who have a site with
qz-tray.jsbut need a stable, fast local print server for 58mm thermal receipts. -
Hobbyists who value transparent code and want to see exactly what's sent to the printer (logs show every byte and conversion parameter).
License
MIT License © 2026 IDNK Soft
Free for commercial use, modification, embedding — just retain the license text and copyright notice.
The QZ Tray protocol compatibility is based on the original qzind/tray project (LGPL-2.1). QZ Tray Lite is an independent Python implementation of the server-side protocol.
Choose QZ Tray Lite — the lightweight alternative that does exactly what your POS needs, and nothing more.
Web silent print server compatible with QZ Tray protocol, speaking the same WebSocket protocol.
Lightweight silent receipt printing server for POS terminals. Fully QZ Tray compatible – no code changes needed. Prints to 58mm thermal printers with text, images, Cyrillic support. No backend signing, no certificates, no dialogs. Just 90 KB, Python-powered. Auto-port detection.
Comments (0)
Your review appreciation cannot be sent
Report comment
Report sent
Your report cannot be sent