Getting Started


  • ✅ 2.2 | ✅ 2.1 | ✅ 2.0 | ⛔ 1.9 | ...

Video tutorials:


  • What is QZ Tray? It's a cross-browser, cross-platform plugin for printing (and talking to serial/usb devices).
  • QZ Tray ships with a sample.html page to demonstrate its features.
  • The sample.html is bundled with the desktop software located in:
    • Windows: C:\Program Files\QZ Tray\demo
    • MacOS: /Applications/QZ
      • 2.1 and older is located at /Applications/QZ
    • Linux: /opt/qz-tray/demo
  • Need to test HTTPS support? Visit
  • For raw printing, some systems may require the Linux, Windows or Mac raw printer setup guide.


Illustrate how to print from a web browser or web app with QZ Tray.

The Code

  1. In the demo folder of QZ Tray (QZ Tray/demo/js) there are several JavaScript files. Only one is essential for QZ Tray.

    File Description Required
    js/qz-tray.js QZ Tray websocket wrapper ✅ Yes

    Note: Optionally, you may npm install qz-tray

      <script type="text/javascript" src="js/qz-tray.js"></script>
(deprecated) Click to expand dependencies for 2.0 version
File Description Required
js/dependencies/rsvp-3.1.0.min.js ECMAScript 6 Promise lib ✅ Yes, unless overriden.
js/dependencies/sha-256.min.js SHA-256 hashing lib ✅ Yes, unless overriden.
js/qz-tray.js QZ Tray websocket wrapper ✅ Yes

Note: Optionally, you may npm install qz-tray sha ws and optionally q|bluebird|rsvp.

  <meta charset="UTF-8">
  <script type="text/javascript" src="js/dependencies/rsvp-3.1.0.min.js"></script>
  <script type="text/javascript" src="js/dependencies/sha-256.min.js"></script>
  <script type="text/javascript" src="js/qz-tray.js"></script>
  1. This next portion of the code deploys QZ Tray by calling qz.websocket.connect() to bind to a local websocket instance of the running software.


    qz.websocket.connect().then(function() {

    💡 Note: To keep trying the connection after failure:

  2. This next code snippet calls qz.printer.find(..) to find a printer name containing the word "zebra" (e.g. Zebra LP2844, etc) . This can only be called after a successful connection.

    Find Printer

    qz.printers.find("zebra").then(function(found) {
       alert("Printer: " + found);
    • You can also list all of the printers attached to the system:
     function findPrinters() {
       qz.printers.find().then(function(data) {
          var list = '';
          for(var i = 0; i < data.length; i++) {
             list += "&nbsp; " + data[i] + "<br/>";
         displayMessage("<strong>Available printers:</strong><br/>" + list);
      }).catch(function(e) { console.error(e); });

    ⚠️ Warning: Mac users: Due to discrepancies in printer search behavior, the printer may be listed differently to Java versus the System Preferences. e.g. Zebra LP2844 may list in Java as Zebra_LP2844. See qz-print/131 for more information.

  3. Finally, we send the printer some data using qz.print(...). This can only be called after a successful connection.

    Send Data

    var config = qz.configs.create("Zebra LP2844-Z");               // Exact printer name from OS
    var data = ['^XA^FO50,50^ADN,36,20^FDRAW ZPL EXAMPLE^FS^XZ'];   // Raw commands (ZPL provided)
    qz.print(config, data).then(function() {
       alert("Sent data to printer");
  4. That's it! Now chain them all together.

    Chaining Requests

    qz.websocket.connect().then(function() { 
       return qz.printers.find("zebra");              // Pass the printer name into the next Promise
    }).then(function(printer) {
       var config = qz.configs.create(printer);       // Create a default config for the found printer
       var data = ['^XA^FO50,50^ADN,36,20^FDRAW ZPL EXAMPLE^FS^XZ'];   // Raw ZPL
       return qz.print(config, data);
    }).catch(function(e) { console.error(e); });
(deprecated) Click to expand 1.9 to 2.0 migration guide

Migration Guide

Function matrix
1.9 2.0
Callback driven, synchronous Promise driven, asynchronous
deployQZ() qz.websocket.connect()
qz.findPrinter(...) qz.printers.find(..)
qz.append(...) No direct equivalent. See Raw Printing example.
qz.appendImage(...) No direct equivalent. See Image Printing example.
qz.appendHTML(...) No direct equivalent. See HTML Printing example.
qz.print() qz.print(config, data)
qz.printPS() qz.print(config, data)
qz.printHTML() qz.print(config, data)
qz.setPaperSize(...) qz.configs.create(..., { units: 'in', size: { width: 8.5, height: 11 } });
qz.setAutoSize(...) qz.configs.create(..., { scaleContent: ... });
qz.setOrientation(...) qz.configs.create(..., { orientation: ... });
qz.setEncoding(...) qz.configs.create("...", { encoding: 'UTF-8' /* etc */ });
qz.findPorts() qz.serial.findPorts()
qz.openPort(...) qz.serial.openPort(...)
qz.closePort(...) qz.serial.closePort(...)
qzReady() qz.websocket.connect().then(function() { ... })
qzDoneFinding() qz.printers.find(...).then(function() { ... })
qzDoneAppending() No direct equivalent, resolves promise at print time.
qzDoneFindingPorts() qz.serial.findPorts().then(function() { ... })
qzDoneOpeningPort() qz.serial.openPort(..., ...).then(function() { ... })

What Next?

Edit this page