ESC/POS Emulator: Print Without a Printer
ESC/POS emulators compared: which render receipts, which listen on port 9100, and the one that answers DLE EOT status and fakes paper-out on demand.
Published 2026-07-24 · Updated 2026-09-21 · For developers →
An ESC/POS emulator accepts printer commands and renders, logs or responds to them in software. This guide compares receipt-rendering tools with a network test target that models status and peripheral faults. The Proxy Nodes twin requires developer-workspace evaluation access; it is not a public download, and its modeled faults do not reproduce every physical or network failure.
This guide surveys the emulators that exist, what each one does and doesn't do, and how to pick the right layer of emulation for the problem in front of you.
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:
- Parsing and rendering. Decode the escape sequences (
ESC @,GS V,ESC aand friends — see the ESC/POS command reference) and produce a picture or text version of the receipt. This answers "does my receipt look right?" - Network transport. Listen on TCP
:9100like 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?" - Status emulation. Answer
DLE EOTreal-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.) - 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, with several good options below. Layers 3 and 4 went almost entirely uncovered for years — which is exactly why the status path is the least-tested code in most POS integrations. That is the layer the digital-twin category exists to close.
The emulators that exist today
These are the projects you'll find searching for "escpos emulator" — all useful within their scope, all built by people scratching a real itch:
| Project | Form | Renders receipts | Listens on :9100 | DLE EOT status | Fault injection | Built for CI |
|---|---|---|---|---|---|---|
| EscPosEmulator (roydejong) | Desktop app | Yes — visual receipt window | Yes | No | No | No |
| escpos-netprinter | Docker container | Yes — HTML output | Yes | No | No | Partly (headless) |
| escpresso | Local web app | Yes — browser preview | Yes | No | No | No |
| virtual-printer.online | Hosted web page | Yes — paste/send bytes, see receipt | No (hosted) | No | No | No |
python-escpos Dummy | Library class | No — captures raw bytes | No | No | No | Yes (byte assertions) |
| Proxy Nodes digital twin | LAN service | Yes — text render + log | Yes | Yes | Yes — REPL + control plane | Yes |
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
:9100listener 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
Dummyprinter 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 ond.outputand 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. The two right-hand columns are where the categories split.
The expensive bugs live in the status path
Rendering bugs are the easy 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 real hardware doesn't make it convenient 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. To exercise this layer you need an emulator that answers status and misbehaves on command.
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 that models selected device requests, replies and faults. Point your client at its test address to exercise the network code. Results apply to the simulated behavior, not every physical fault.
The Proxy Nodes twin requires a developer-workspace checkout.
Request evaluation access before planning a trial or CI dependency;
there is no standalone public download or published npm package. With the workspace
and its dependencies installed, pnpm sim starts the process. The default binds
to all interfaces and announces discovery; for an isolated local test use
pnpm sim --host 127.0.0.1 --no-mdns --no-beacon.
It exposes these modeled behaviors:
- The HTTP/JSON API —
POST /print,GET /status,POST /drawer/kick,POST /raw,GET/PUT /config, SSEGET /eventsfor live telemetry,GET /peers,GET/DELETE /scans,GET /scaleandGET /devices/unknown. Some node routes are not served —/bootlog,/network,/composeand/restartamong them — and the twin does not enforceapiMode. - Raw TCP on
:9100— accepts ESC/POS like any network receipt printer, and answersDLE EOTstatus queries that always agree with whatGET /statusreports. - mDNS discovery — advertises
_proxynodes._tcp, so your discovery code paths get exercised too. - Virtual peripherals — printer, cash drawer, scale, and barcode scanner, depending on the variant you launch, driven from the console below.
- A fault-injection REPL — type
paper out,cover open,offline,drawer,weight 1.25, orscan 0123456789at the console and the virtual hardware misbehaves on command. Prints start failing, status bytes change, telemetry events fire.
proxynodes> paper out # prints now fail; DLE EOT 4 reports paper end
proxynodes> cover open # cover bit flips in status replies
proxynodes> offline # the node drops off the network
proxynodes> status # snapshot of what your app should be seeing
Alongside it runs the conformance suite: conformance specs that execute against the twin or against a physical node, so selected behaviors can be checked with the same assertions. You must run the hardware checks separately; a simulator pass does not establish physical compatibility. The firmware those specs are run against on a Proxy Node Raw board — Nodeware 1.2.55 as of this writing — is the contract the twin is held to. The twin does not enforce API authentication or deliver configured webhooks, and its offline toggle leaves the network listeners running. Use hardware or a separate fixture for those tests. One detail worth calling out: when a node genuinely can't take a reading, the status layer models the value as unknown instead of guessing. Test doubles that are more optimistic than reality are how integrations pass QA and fail in kitchens.
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
:9100andDLE EOTand can fail on command — that's the digital-twin category, and simulator evaluation access must be arranged before adding it to your pipeline. The broader virtual receipt printer guide covers the decision from the non-emulator end (PDF drivers, preview apps) if your need is less technical.
Where the code lives
The twin and conformance suite currently live in the developer workspace. Request access on the simulator page; these instructions are not a public package installation path. We have not announced an open-source release of the firmware; the firmware page says what is published and on what terms.
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 Proxy Nodes digital twin answers DLE EOT on port 9100 with status bytes that always match its HTTP GET /status endpoint.
- How do I simulate a printer running out of paper?
- With a fault-injecting emulator. The Proxy Nodes twin has a REPL where typing 'paper out' makes prints fail and flips the paper bit in DLE EOT replies, so you watch exactly how your application reacts. Pure renderers can't simulate faults.
- Which ESC/POS emulator shows me the rendered receipt?
- EscPosEmulator opens the receipt in a desktop window, escpresso previews it in a browser, and escpos-netprinter writes it out as HTML. The Proxy Nodes twin renders to readable text and a log — its strength is status replies and faults, not a pretty picture.
- 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.
- Does the digital twin cost anything?
- Access currently requires an authorized developer-workspace checkout. Ask about evaluation access at /simulator before planning a trial; this page does not promise a public download, account-free access or commercial terms.
Related reading
- Virtual Receipt Printer for Dev and TestingPick a virtual thermal printer by job: print-to-PDF for proofing, online renderers, port-9100 emulators, or a network digital twin for integration work.
- Test Receipt Printing in CI — No HardwareHow to put receipt printing under CI: golden-file byte tests, decoded snapshots, a printer service in the pipeline, injected faults, and conformance runs.
- ESC/POS Printer Status: DLE EOT ExplainedThe DLE EOT real-time status commands byte by byte — paper, cover, drawer, errors — plus why many printers lie or stay silent, and what to do about it.
- ESC/POS Commands: a Practical ReferenceThe ESC/POS commands that matter in production — init, text style, feed, cut, drawer kick, status — with raw bytes and the quirks between brands.