ESC/POS Emulator: Print Without a Printer

Compare ESC/POS emulators and receipt printer simulators for development — and how to emulate paper-out, cover-open, and DLE EOT status in software.

Published 2026-07-24 · For developers

An ESC/POS emulator is software that accepts the same bytes a thermal receipt printer would — over TCP port 9100, a serial port, or a library call — and does something useful with them: renders the receipt, logs the commands, or answers status queries. A handful of open-source projects cover the rendering part well. Almost nothing emulates the part that actually breaks POS systems in production: real-time status (DLE EOT), paper-out and cover-open behavior, and network failure modes.

This guide surveys the emulators that exist, what each one does and doesn't do, and where a network-level digital twin fits when rendering alone isn't enough.

What "emulating ESC/POS" actually means

ESC/POS looks like one protocol but an emulator can imitate it at four distinct layers, and most tools only cover the first one or two:

  1. Parsing and rendering. Decode the escape sequences (ESC @, GS V, ESC a and friends — see the ESC/POS command reference) and produce a picture or text version of the receipt. This answers "does my receipt look right?"
  2. Network transport. Listen on TCP :9100 like a real network printer, so your application connects to an IP address instead of calling a library. This answers "does my app actually reach a printer?"
  3. Status emulation. Answer DLE EOT real-time status queries on the same socket — paper present, cover closed, online — the way real hardware does. This answers "does my app notice when the printer has a problem?" (DLE EOT explained byte by byte.)
  4. Fault behavior. Let you cause problems on demand — paper out, cover open, device offline — and observe what your software does. This answers the support-ticket questions: what does the cashier see, does the job retry, does the order silently vanish?

Layer 1 is a solved problem. Layers 3 and 4 are, as of mid-2026, nearly empty.

The emulators that exist today

These are the projects you'll find searching for "escpos emulator" — all open source, all useful within their scope, all built by people scratching a real itch:

ProjectFormRenders receiptsListens on :9100DLE EOT statusFault injectionBuilt for CI
EscPosEmulator (roydejong)Desktop appYes — visual receipt windowYesNoNoNo
escpos-netprinterDocker containerYes — HTML outputYesNoNoPartly (headless)
escpressoLocal web appYes — browser previewYesNoNoNo
virtual-printer.onlineHosted web pageYes — paste/send bytes, see receiptNo (hosted)NoNoNo
python-escpos DummyLibrary classNo — captures raw bytesNoNoNoYes (byte assertions)
ProxyNodes digital twinLAN serviceYes — text render + logYesYesYes — REPL + control planeYes

A fair reading of each:

  • EscPosEmulator is the classic. Point your POS at your workstation's IP, print, and a receipt appears in a window. Excellent for eyeballing layout during development. It's a GUI desktop app, so it doesn't fit headless pipelines, and it doesn't answer status queries.
  • escpos-netprinter wraps a :9100 listener and an ESC/POS-to-HTML converter in a Docker container. That makes it the most automatable of the renderers — you can run it in a pipeline and diff the HTML. Still receive-only: your app can send jobs but learns nothing back.
  • escpresso parses jobs and shows the receipt in a browser. Nice feedback loop for layout work.
  • virtual-printer.online is a hosted receipt renderer — handy for a quick "what do these bytes draw" check with zero install, but your application can't treat it as a printer on the LAN.
  • python-escpos's Dummy printer isn't a network emulator at all: it's an in-memory printer object that accumulates the exact bytes your code generated. For unit-testing an encoder it's the right tool — assert on d.output and you're done. It tells you nothing about transport or status.

None of this is a knock on these projects. They each do the rendering job they set out to do. But notice the two columns that are almost entirely "No."

The gap: status and faults

Rendering bugs are the cheap bugs. You catch them by looking at a receipt. The expensive bugs — the ones that become "printer offline" support tickets — live in the status path:

  • Your app sends DLE EOT 4 (10 04 04) to check the paper sensor. Does it parse the reply byte correctly? Does it handle no reply?
  • The cover opens mid-shift. Does your UI tell the cashier, or does the print queue back up silently?
  • The printer drops off the network between jobs. Does your code time out sanely, retry, reroute to a backup printer, or hang a POS thread?

You cannot test any of that against an emulator that only renders. And you can't conveniently test it against real hardware either — nobody's CI job opens a printer cover at the right millisecond, and taping over a paper sensor is not a repeatable test fixture. This is why the status path is chronically undertested across the industry: the tooling to exercise it hasn't existed.

That's the specific hole a digital twin fills.

Parsing library vs. network-level digital twin

The distinction that matters when choosing a tool:

A parsing library (or a renderer built on one) sits inside your test process. You hand it bytes, it hands you a picture or a decoded structure. Fast, deterministic, great for unit tests — but your production code path to the printer (socket connect, write, status poll, timeout handling) is never executed.

A network-level digital twin is a separate process on your LAN (or in your CI job) that behaves like the device: same ports, same discovery, same replies, same failure modes. Your application connects to it exactly the way it connects to production hardware — same code, different IP. When the twin says "paper out," your app experiences a paper-out the way it would on a Friday night.

The ProxyNodes twin is the second kind. It's a plain LAN service (started with pnpm sim) that exposes what the physical ProxyNode device exposes:

  • HTTP on :8080POST /print, GET /status, POST /drawer/kick, GET /events for server-sent telemetry, and an identity endpoint.
  • Raw TCP on :9100 — accepts ESC/POS like any network receipt printer, and answers DLE EOT status queries that always agree with what GET /status reports.
  • mDNS discovery — advertises _proxynode._tcp, so discovery code paths get exercised too.
  • Virtual peripherals — printer, cash drawer, scale, and barcode scanner, depending on the variant you launch.
  • A fault-injection REPL — type paper out, cover open, offline, drawer, weight 1.25, or scan 0123456789 at the console and the virtual hardware misbehaves on command. Prints start failing, status bytes change, telemetry events fire.
proxynode> paper out        # prints now fail; DLE EOT 4 reports paper end
proxynode> cover open       # cover bit flips in status replies
proxynode> offline          # the node drops off the network
proxynode> status           # snapshot of what your app should be seeing

Alongside it runs a protocol conformance suite — the same test suite executes against the twin or against real hardware on the bench, so "works in simulation" and "works on the device" are verified by identical assertions rather than hope. One detail worth calling out for honesty's sake: when the node genuinely can't take a reading, the status API says known: false instead of guessing. Test doubles that are more optimistic than reality are how integrations pass QA and fail in kitchens.

Where the code lives

The twin and conformance suite will be published under an open license at launch — the repository isn't public yet. The simulator page has current details.

Which should you use?

  • Checking receipt layout while you build? Any renderer works. EscPosEmulator if you like a desktop window, escpresso for a browser preview, virtual-printer.online for zero-install one-offs.
  • Unit-testing your encoder? python-escpos Dummy (or plain byte assertions in any language). See testing receipt printing in CI for patterns.
  • Automated rendering checks in a pipeline? escpos-netprinter's Docker form factor is the most practical of the pure renderers.
  • Testing the status path, failure handling, discovery, or the full integration in CI? You need something that speaks :9100 and DLE EOT and can fail on command — that's the digital-twin category. The broader virtual receipt printer guide covers the decision from the non-emulator end (PDF drivers, preview apps) if your need is less technical.

More developer guides live on the developers hub.

Frequently asked questions

What is an ESC/POS emulator?
Software that accepts ESC/POS printer commands — usually over TCP port 9100 — and renders, logs, or responds to them instead of printing on paper. Developers use emulators to build and test receipt printing without physical hardware.
Can an emulator answer DLE EOT status queries?
Most can't. The well-known open-source emulators (EscPosEmulator, escpos-netprinter, escpresso) render receipts but don't reply to DLE EOT real-time status requests. The ProxyNodes digital twin answers DLE EOT on port 9100 with status bytes that match its HTTP status endpoint.
How do I simulate a printer running out of paper?
With a fault-injecting emulator. The ProxyNodes twin has a REPL where typing 'paper out' makes prints fail and flips the paper bit in DLE EOT replies, so you can watch exactly how your application reacts. Pure renderers can't simulate faults.
Is there an ESC/POS emulator I can run in CI?
escpos-netprinter runs headless in Docker for rendering checks. For full integration tests — network transport, status queries, fault scenarios — run a digital twin as a service in the pipeline and point your app at it, then assert on behavior.
What's the difference between an ESC/POS parser and a printer simulator?
A parser decodes bytes inside your test process; a simulator is a separate service your app connects to over the network, exercising your real socket, timeout, and status-handling code. Parsers test formatting; simulators test integration.

Related reading