How to print raw ESC/POS commands from Javascript
Product JSPrintManager Published 07/30/2018 Updated 11/05/2026 Author Neodynamic
Overview
Many kind of printers like dot-matrix, impact, kiosk, thermal, inkjet, etc; do internally handle ESC/POS (a.k.a. ESC/P) commands which are processed to produce the output printing. ESC/POS was designed by EPSON and is widely used by many other printer brands mainly on POS (Point Of Sales or Point of Services) scenarios like retail, banking, hospitality, and healthcare.
ESC/POS commands are very simple and the main character you'll find in each command is ESC i.e. ASCII hex 1B. Almost any ESC/POS command will start with the ESC (hex 1B) character although it's not the only one as you'll see in the next sample later. The main advantage of using raw ESC/POS commands for printing instead of using the built-in browser javascript printing (window.print();) is that the printing performance will be way faster; a factor that is key in the aforementioned scenarios. No matter which Web Platform/Framework you use (ASP.NET, PHP, Django, Ruby On Rails (RoR), Express.js, AngularJS/SPA, etc.), you'll be able to use raw printing feature with the help of our JSPrintManager solution that was specially designed for this kind of printing needs.
In this walkthrough, you'll learn how to print raw ESC/POS commands from Javascript directly to the client printer without displaying a print dialog at all. You'll be able to print ESC/POS commands to the Default client printer as well as to any other installed printer at the client machine. This solution works with any popular browser like Chrome, Edge, Firefox & Safari on Windows, Linux, Raspberry Pi and Mac systems!
NOTE
If you don't know how to write ESC/POS commands, then you can take advantage of our JSESCPOSBuilder project to generate the ESC/POS commands by writing simple and dev-friendly Javascript code. Please refer to this article How to generate (JSESCPOSBuilder) and print raw ESC/POS commands from JavascriptThe ESC/POS commands that we'll use in this article will print out a simple retail receipt that will look like this:

A Sample Receipt printed from Javascript and created by using ESC/POS commands
How to specify ESC/POS commands in Javascript
ESC/POS commands are composed of a set of simple bytes (from 00 up to FF in hex notation) and most of them always starts with ESC which is byte 1B.
Some commands require additional parameters which have to be expressed in bytes too. For example, the following shows how the ESC/POS command for "emphasized text " is found in the reference manual and how it should be specified in bytes.
- ESC/POS command for: "Emphasized mode selected."
-
From the ESC/POS Reference Manual:
ESC ! 8
-
It must be specified in bytes (HEX notation) as:
\x1B!\x08Notice that ESC needs to be specified as \x1B and the integer parameter value is NOT digit 8 char (hex 38) BUT byte hex 08!!! Be aware of the way you must specify commands & params values as a misunderstanding on this subject might carry unexpected printing results or no printing output at all.
Step-by-step
- Be sure you install in your dev machine JSPrintManager (JSPM) (Available for Windows, Linux, Raspberry Pi & Mac)
This small app must be installed on each client that will print from your website!
Since Chrome 142, browsers ask the user to allow Local Network Access the first time your website connects to the JSPrintManager App. - By using your favorite Web Development IDE or Text Editor, create a new HTML file like index.html
Copy/paste the following code snippets:HTML Code
<div style="text-align:center"> <h1>Print ESC/POS commands from Javascript</h1> <hr /> <label for="printerType">Client printer:</label> <select id="printerType" onchange="showPrinterSettings();"> <option value="0">Default printer</option> <option value="1">Let the user select it (OS print dialog)</option> <option value="2" selected>Installed printer</option> <option value="3">IP/Ethernet printer</option> <option value="4">Parallel port (LPT) printer</option> <option value="5">Serial port (RS-232) printer</option> <option value="6">Bluetooth printer</option> </select> <div id="printer-settings-2" class="printer-settings"> <label>Installed printer: <select id="installedPrinterName"></select></label> </div> <div id="printer-settings-3" class="printer-settings" style="display:none"> <label>IP address: <input id="netIp" value="10.0.0.1" /></label> <label>Port: <input id="netPort" value="9100" /></label> <label>or DNS name: <input id="netDns" /></label> </div> <div id="printer-settings-4" class="printer-settings" style="display:none"> <label>Parallel port: <input id="lptPort" value="LPT1" /></label> </div> <div id="printer-settings-5" class="printer-settings" style="display:none"> <label>Serial port: <select id="serialPort"></select></label> <label>Baud rate: <input id="serialBaudRate" value="9600" /></label> <label>Data bits: <select id="serialDataBits"> <option value="Eight">8</option> <option value="Seven">7</option> <option value="Six">6</option> <option value="Five">5</option> </select> </label> <label>Parity: <select id="serialParity"> <option>None</option> <option>Odd</option> <option>Even</option> <option>Mark</option> <option>Space</option> </select> </label> <label>Stop bits: <select id="serialStopBits"> <option value="One">1</option> <option value="OnePointFive">1.5</option> <option value="Two">2</option> </select> </label> <label>Flow control: <select id="serialFlowControl"> <option value="None">None</option> <option value="XOnXOff">XOn/XOff</option> <option value="RequestToSend">RTS (Request to send)</option> <option value="RequestToSendXOnXOff">RTS + XOn/XOff</option> </select> </label> </div> <div id="printer-settings-6" class="printer-settings" style="display:none"> <label>Bluetooth address: <input id="btAddress" placeholder="00:00:00:00:00:00" /></label> <label>Channel: <input id="btChannel" value="1" /></label> </div> <br /><br /> <button type="button" onclick="doPrinting();">Print Now...</button> </div>Script References
- Download JSPrintManager.js
- Copy all of these *.js files to the same folder where your html page is located and then add the following script references to your page.
<!-- JSPrintManager.js (download it or install it with: npm install jsprintmanager) --> <script src="JSPrintManager.js"></script>Script Code
<script> // Start the connection with the JSPrintManager Client App JSPM.JSPrintManager.auto_reconnect = true; JSPM.JSPrintManager.start(); JSPM.JSPrintManager.WS.onStatusChanged = function () { if (jspmWSStatus()) { // get the client installed printers JSPM.JSPrintManager.getPrinters().then(function (printersList) { fillSelect('installedPrinterName', printersList); }); // get the client serial ports (if any) JSPM.JSPrintManager.getSerialPorts().then(function (portsList) { fillSelect('serialPort', portsList); }); } }; // Do printing... function doPrinting() { if (jspmWSStatus()) { // Create a ClientPrintJob var cpj = new JSPM.ClientPrintJob(); // Set the target client printer cpj.clientPrinter = getClientPrinter(); // Set the raw printer commands // ESC/POS commands for a sample receipt var esc = '\x1B'; // ESC byte in hex notation var gs = '\x1D'; // GS byte in hex notation var newLine = '\x0A'; // LF byte in hex notation var cmds = esc + "@"; // Initializes the printer (ESC @) cmds += esc + '!' + '\x38'; // Emphasized + Double-height + Double-width mode selected (ESC ! (8 + 16 + 32)) 56 dec => 38 hex cmds += 'BEST DEAL STORES'; // text to print cmds += newLine + newLine; cmds += esc + '!' + '\x00'; // Character font A selected (ESC ! 0) cmds += 'COOKIES 5.00'; cmds += newLine; cmds += 'MILK 65 Fl oz 3.78'; cmds += newLine + newLine; cmds += 'SUBTOTAL 8.78'; cmds += newLine; cmds += 'TAX 5% 0.44'; cmds += newLine; cmds += 'TOTAL 9.22'; cmds += newLine; cmds += 'CASH TEND 10.00'; cmds += newLine; cmds += 'CASH DUE 0.78'; cmds += newLine + newLine; cmds += esc + '!' + '\x18'; // Emphasized + Double-height mode selected (ESC ! (16 + 8)) 24 dec => 18 hex cmds += '# ITEMS SOLD 2'; cmds += esc + '!' + '\x00'; // Character font A selected (ESC ! 0) cmds += newLine + newLine; cmds += '11/03/13 19:53:17'; cmds += newLine + newLine + newLine; cmds += gs + 'V' + '\x41' + '\x03'; // Feed paper and partial cut (GS V 65 3) cpj.printerCommands = cmds; // Trace the print job status (optional) traceJob(cpj); // Send the print job to the client printer cpj.sendToClient(); } } // Check the connection status with the JSPrintManager Client App function jspmWSStatus() { var status = JSPM.JSPrintManager.websocket_status; if (status == JSPM.WSStatus.Open) { return true; } else if (status == JSPM.WSStatus.WaitingForUserResponse) { console.info('Waiting for the user to allow this website (JSPrintManager dialog or browser Local Network Access prompt)...'); } else if (status == JSPM.WSStatus.Blocked) { alert('JSPrintManager has blocked this website!'); } else if (status == JSPM.WSStatus.NotInstalled || status == JSPM.WSStatus.Closed) { alert('JSPrintManager Client App is not installed or not running! Download it from https://neodynamic.com/downloads/jspm'); } else if (status == JSPM.WSStatus.CertificateError) { alert('A TLS/SSL certificate error prevented the connection with JSPrintManager Client App.'); } else if (status == JSPM.WSStatus.ConnectionError) { alert('A network error (e.g. a firewall) prevented the connection with JSPrintManager Client App.'); } return false; } // Show the settings of the selected printer type function showPrinterSettings() { var panels = document.querySelectorAll('.printer-settings'); for (var i = 0; i < panels.length; i++) { panels[i].style.display = (panels[i].id == 'printer-settings-' + val('printerType')) ? '' : 'none'; } } // Create the client printer for the selected printer type function getClientPrinter() { switch (val('printerType')) { case '0': return new JSPM.DefaultPrinter(); case '1': return new JSPM.UserSelectedPrinter(); case '2': return new JSPM.InstalledPrinter(val('installedPrinterName')); case '3': return new JSPM.NetworkPrinter(parseInt(val('netPort')), val('netIp'), val('netDns')); case '4': return new JSPM.ParallelPortPrinter(val('lptPort')); case '5': return new JSPM.SerialPortPrinter(val('serialPort'), parseInt(val('serialBaudRate')), JSPM.Serial.Parity[val('serialParity')], JSPM.Serial.StopBits[val('serialStopBits')], JSPM.Serial.DataBits[val('serialDataBits')], JSPM.Serial.Handshake[val('serialFlowControl')]); case '6': return new JSPM.BluetoothPrinter(val('btAddress'), parseInt(val('btChannel'))); } } // Log the print job status updates (optional) function traceJob(cpj) { cpj.onUpdated = function (data) { console.info(data); }; cpj.onFinished = function (data) { console.info(data); }; cpj.onError = function (data, isCritical) { console.error(data); }; } // Helpers function val(id) { return document.getElementById(id).value; } function checked(id) { return document.getElementById(id).checked; } // Fill a <select> element with a list of items function fillSelect(id, items, getText) { var select = document.getElementById(id); select.innerHTML = ''; for (var i = 0; i < items.length; i++) { var text = getText ? getText(items[i]) : items[i]; select.add(new Option(text, text)); } } </script> - That's it! Run your website and test it. Click on Print Now... to print the ESC/POS Commands without print dialog. You can print it to the Default client printer, to any installed printer available at the client machine, or directly to an IP/Ethernet, LPT, RS-232 or Bluetooth printer.
NOTE Besides the Default printer and any installed printer, this sample also lets you print through the OS print dialog and directly to an IP/Ethernet printer (e.g. port 9100), a Parallel Port (LPT), a Serial Port (RS-232) or a Bluetooth printer.
Useful? Share it!
| Tweet |
|
Related Articles
How to generate (JSESCPOSBuilder) and print raw ESC/POS commands from JavascriptHow to configure RAW printing mode in Windows
How to configure RAW printing mode in Linux and Raspberry Pi
How to configure RAW printing mode in macOS and OSX
Need help? Contact Support
We provide best-in-class customer service and support directly from members of our dev team! If we are available when you contact us, you will get a response in few minutes; otherwise the maximum turnaround is 24hs in most cases.