How to Detect Printer Status (Online, Offline, Paper Out, or Errors) in Node.js with Kiosk Nov 18, 2025 | 13 minutes read 8 Likes Printer Status Monitoring with Node.jsWhen managing kiosks, retail terminals, or POS systems, it is essential to know whether your printer is online, offline, or out of paper. We’ll build a Node.js-based printer status monitor using SNMP, ESC/POS commands, and Express.js to expose a simple API. What We’ll BuildAutomatically discovers printers via SNMPUses ESC/POS status commands to detect:○   Online/offline state○   Paper out / paper near the end○   Cover open○   Mechanical or cutter errorsServes a REST API endpoint (/) that returns real-time printer information in JSON. Project Setup:1. Environment VariablesCreate a .env file # Printer SNMP settings PRINTER_SNMP_COMMUNITY=public PRINTER_IP=192.168.10.148 PRINTER_INTERVAL=60000 PRINTER_START_INTERVAL=15000 PORT=9100 2. Printer Discovery via SNMP File: printers/discovery.js const snmp = require('net-snmp'); const { getEscPosStatus, getEscPosInfo } = require('./status'); let printers = []; // ---------------------- // Helper: Add or update printer (deduplicate by IP + port) // ---------------------- function addOrUpdatePrinter(newPrinter) { const existing = printers.find(p => p.ip === newPrinter.ip && p.port === newPrinter.port); if (existing) { // Prefer Bonjour info if available if (newPrinter.protocol === "Bonjour") { existing.name = newPrinter.name || existing.name; existing.protocol = newPrinter.protocol; } existing.model = newPrinter.model || existing.model; existing.firmware = newPrinter.firmware || existing.firmware; } else { printers.push(newPrinter); } } function discoverSNMP(printerIp = process.env.PRINTER_IP) { return new Promise((resolve) => { const found = []; let completed = 0; // SNMP OIDs const OIDS = { sysName: "1.3.6.1.2.1.1.5.0", // Hostname sysDescr: "1.3.6.1.2.1.1.1.0", // System description (model/firmware) sysLocation: "1.3.6.1.2.1.1.6.0", // Location string prtGeneralPrinterName: "1.3.6.1.2.1.43.5.1.1.16.1", // Printer name prtGeneralSerialNumber: "1.3.6.1.2.1.43.5.1.1.17.1", // Serial number }; const ip = printerIp; const session = snmp.createSession(ip, process.env.PRINTER_SNMP_COMMUNITY); session.get(Object.values(OIDS), (err, varbinds) => { if (!err && varbinds && varbinds.length > 0) { const printer = { id: `${ip}:9100`, ip, port: process.env.PORT, protocol: "SNMP", name: varbinds[0]?.value?.toString() || "", // sysName model: varbinds[1]?.value?.toString() || "", // sysDescr location: varbinds[2]?.value?.toString() || "", // sysLocation printerName: varbinds[3]?.value?.toString() || "", // prtGeneralPrinterName serialNumber: varbinds[4]?.value?.toString() || "", // prtGeneralSerialNumber }; addOrUpdatePrinter(printer); found.push(printer); } session.close(); completed++; if (completed >= 254) resolve(found); }); // Safety timeout setTimeout(() => resolve(found), 8000); }); } // ---------------------- // Periodic discovery & cleanup (keep only online printers) // ---------------------- function discoverPrintersPeriodic(interval = process.env.PRINTER_INTERVAL, ip = process.env.PRINTER_IP) { async function discover() { // await discoverBonjour(); await discoverSNMP(ip); // Check status for all printers and remove offline ones for (let i = printers.length - 1; i >= 0; i--) { const p = printers[i]; try { const status = await getEscPosStatus(p); if (!status.online) printers.splice(i, 1); } catch { printers.splice(i, 1); } } setTimeout(discover, interval); } discover(); } module.exports = { printers, discoverPrintersPeriodic, addOrUpdatePrinter }; 3. Checking Printer Status via ESC/POS CommandsFile: printers/status.js const net = require('net'); // ESC/POS commands const STATUS_COMMANDS = { printer: Buffer.from([0x10, 0x04, 0x01]), offline: Buffer.from([0x10, 0x04, 0x02]), error: Buffer.from([0x10, 0x04, 0x03]), paper: Buffer.from([0x10, 0x04, 0x04]), }; const GS_I_MODEL = Buffer.from([0x1D, 0x49, 0x01]); const GS_I_FIRMWARE = Buffer.from([0x1D, 0x49, 0x02]); async function queryEscPos(ip, port, command) { return new Promise((resolve, reject) => { const client = new net.Socket(); let buffer = Buffer.alloc(0); client.setTimeout(2000, () => { client.destroy(); reject(new Error("Timeout")); }); client.connect(port, ip, () => client.write(command)); client.on('data', data => { buffer = Buffer.concat([buffer, data]); client.destroy(); resolve(buffer.toString().trim()); }); client.on('error', reject); }); } async function getEscPosInfo(printer) { try { const model = await queryEscPos(printer.ip, printer.port, GS_I_MODEL); const firmware = await queryEscPos(printer.ip, printer.port, GS_I_FIRMWARE); return { model, firmware }; } catch { return {}; } } async function getEscPosStatus(printer) { const commands = [STATUS_COMMANDS.printer, STATUS_COMMANDS.offline, STATUS_COMMANDS.error, STATUS_COMMANDS.paper]; const results = []; try { for (const cmd of commands) { const res = await queryEscPos(printer.ip, printer.port, cmd); results.push(res.charCodeAt(0) || 0); } const [printerB, offline, error, paper] = results; const status = { online: !(offline & 0x08), coverOpen: !!(error & 0x04), paperOut: !!(paper & 0x60), paperNearEnd: !!(paper & 0x0C), mechanicalError: !!(error & 0x40), cutterError: !!(error & 0x08), unrecoverableError: !!(error & 0x20), }; status.error = status.coverOpen || status.paperOut || status.mechanicalError || status.cutterError || status.unrecoverableError; return status; } catch { return { online: false, error: true }; } } module.exports = { getEscPosInfo, getEscPosStatus }; 4. Logging Printer EventsFile: printers/events.js function logPrinterStatus(printer, status) { const symbol = status.error ? '✖' : '✔'; const color = status.error ? '\x1b[31m' : '\x1b[32m'; console.log(`${color}${symbol} [${printer.protocol}] ${printer.name}: ${status.error ? 'ERROR' : 'OK'}\x1b[0m`); } module.exports = { logPrinterStatus }; 5. Creating the Express API EndpointFile: routes/printers.js const express = require('express'); const router = express.Router(); const { printers } = require('../printers/discovery'); const { getEscPosStatus, getEscPosInfo } = require('../printers/status'); const { logPrinterStatus } = require('../printers/events'); const fs = require('fs'); const path = require('path'); router.get('/', async (req, res) => { const debug = req.query.debug === 'true'; const enriched = []; const configPath = path.join(__dirname, '../config.json'); const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); const kioskName = config.KIOSK_NAME; for (const p of printers) { try { // Get printer status const status = await getEscPosStatus(p); if (!status.online) continue; // Get ESC/POS info (model, firmware) const escposInfo = await getEscPosInfo(p); // Build enriched printer object const printerData = { id: p.id, ip: p.ip, port: p.port, protocol: p.protocol, name: p.name || p.printerName || "", model: escposInfo.model && escposInfo.model.length > 2 ? escposInfo.model : p.model || p.printerName || "Unknown", firmware: escposInfo.firmware && /^[\x20-\x7E]+$/.test(escposInfo.firmware) ? escposInfo.firmware : undefined, serialNumber: p.serialNumber || "", kioskId: kioskName, location: p.location || "", online: status.online, coverOpen: status.coverOpen || false, paperOut: status.paperOut || false, paperNearEnd: status.paperNearEnd || false, mechanicalError: status.mechanicalError || false, cutterError: status.cutterError || false, unrecoverableError: status.unrecoverableError || false, error: status.error || false, }; if (debug) logPrinterStatus(p, status); enriched.push(printerData); } catch (e) { console.error("Failed to enrich printer:", p.ip, e); } } res.json(enriched); }); module.exports = router; 6. Starting the ServiceFile: server.js require('dotenv').config(); const express = require('express'); const http = require('http'); const cors = require('cors'); const { discoverPrintersPeriodic } = require('./printers/discovery'); const printersRoute = require('./routes/printers'); const paymentRoute = require('./routes/payment'); const printRoute = require('./routes/print'); const { startWebSocket, startMonitoring } = require('./printers/monitor'); const app = express(); const PORT = 3001; const server = http.createServer(app); app.use(cors()); app.use(express.json()); app.use('/api/printers', printersRoute); // Start periodic network discovery (removes offline printers automatically) discoverPrintersPeriodic(process.env.PRINTER_INTERVAL); // Start WebSocket server startWebSocket(server); // Start real-time monitoring startMonitoring(5000); server.listen(PORT, () => console.log(`Server running at http://localhost:${PORT}`)); Run it:node server.jsVisit: http://localhost:3000/printers 7. Example Output: [ { "id": "192.168.10.148:9100", "ip": "192.168.10.148", "protocol": "SNMP", "name": "EPSON_TM_T88VI", "model": "EPSON TM-T88VI Receipt Printer", "firmware": "1.02", "serialNumber": "AB12345678", "kioskId": "Kiosk-001", "online": true, "coverOpen": false, "paperOut": false, "paperNearEnd": false, "mechanicalError": false, "cutterError": false, "unrecoverableError": false, "error": false } ] Printer Status insights for real-time kiosk monitoringCheck NowThe Way ForwardIntegrating Apple Pay and Google Pay using Stripe in React Native is a powerful way to deliver seamless and secure payment experiences to users worldwide. With a few lines of configuration and careful setup, you can enable one-tap payments and boost conversion rates.This guide covered the end-to-end process from SDK setup and backend creation to testing React Native apps online and deployment, giving you a solid foundation for handling mobile payments confidently.Next step: Explore advanced flows like saving payment methods, handling subscriptions, or integrating 3D Secure authentication for maximum protection.Free Consultation Node js Service ProvidersNode.jsHire Dedicated Node js DeveloperNode.js DevelopersNode.js ApplicationHire Node.js DeveloperChandra RaoNov 18 2025You may also like Network Discovery for JCC Terminals in Node.js – Best Practices & Code Samples Read More Nov 18 2025 Next JS Development Services Driving Innovation in Modern Web Architecture Read More Sep 11 2025 Scaling SaaS Platforms Using SSR Strategies with Hire Next.js Developers Read More Aug 12 2025 Implementing Microservices Architecture with Node.js and MongoDB Read More Jun 13 2025 How to Use TypeORM in Node.js: A Step-by-Step Guide with Employee CRUD Example Read More Jun 02 2025 Leveraging Node.js Service Providers to Rebuild and Optimize Your Web Applications Read More Mar 05 2025