Virtual Receipt Printer for Dev and Testing

Options for a virtual thermal printer: print-to-image drivers, GitHub emulators, and a network digital twin your app can't tell from real hardware.

Published 2026-07-24 · Updated 2026-08-02 · For developers

A virtual receipt printer is software that stands in for a thermal printer: your app "prints," and instead of paper you get an image, a PDF, a browser preview, or a fully simulated device on the network. Which kind you need depends entirely on the question you're trying to answer — "does this receipt look right?" needs a renderer, while "does my point-of-sale handle a paper jam?" needs something that can fake the jam.

This guide covers the whole range, from print-to-PDF drivers to a network digital twin, and ends with a decision table so you can pick in thirty seconds.

The four jobs people hire a virtual printer for

"Virtual receipt printer" means at least four different things depending on who's searching:

  1. Proofing a design. A designer or product manager wants to see a receipt — logo, spacing, totals — without owning a printer.
  2. Developing print code. A developer is generating ESC/POS commands and wants fast visual feedback while iterating.
  3. QA and troubleshooting. A tester wants to reproduce what happens when the printer misbehaves: out of paper, cover open, unplugged.
  4. Automated testing (CI). A team wants the build to fail if printing breaks — with no printer within a mile of the build server.

Each job has a different right answer. Working through them simplest-first:

If your application prints through the operating system's normal print dialog (a browser page, a desktop POS using OS drivers), the built-in Microsoft Print to PDF on Windows or Save as PDF on macOS is a perfectly good virtual printer. Commercial virtual printer drivers go further — capturing output as PNG/JPEG, watermarking, auto-saving to a folder — and you can usually configure a custom paper size around 80 mm wide to approximate receipt stock.

  • Good for: design proofs, archiving what would have printed, demoing receipt layouts in documents.
  • The catch: real receipt printing in POS systems mostly doesn't go through OS print drivers. It sends raw ESC/POS bytes straight to the printer over TCP or USB. A PDF driver never sees those bytes, so this route tests nothing about an actual POS integration. There are also iPad and Android apps that render sample receipts — same category, same limitation.

If your print path is raw ESC/POS, keep reading.

Online receipt renderers

virtual-printer.online is a hosted page where you send ESC/POS data and see the rendered receipt. Zero install, so it's the fastest possible answer to "what do these bytes draw?" The related receiptline project takes the opposite approach — a markdown-like receipt language with an open-source renderer — which is pleasant if you control both ends.

  • Good for: one-off checks, sharing a rendered receipt with a teammate, learning ESC/POS.
  • The catch: your application can't connect to a web page as if it were a printer. Nothing about your transport, timeouts, or error handling is exercised.

Developer-grade ESC/POS emulators

The next step up: open-source emulators that listen on TCP port 9100 — the port real network receipt printers use — and render whatever your app sends. Point your POS at your laptop's IP and print.

  • EscPosEmulator (roydejong): desktop app, receipt appears in a window. The standard choice for interactive development.
  • escpos-netprinter: runs in Docker, renders jobs to HTML — the most automatable renderer.
  • escpresso: renders received jobs in a browser preview.

Now your app's real network code path runs, and that's genuine progress over a PDF driver. What these still can't do: talk back. Real printers answer status queries (DLE EOTexplained here) telling the POS about paper, cover, and errors, and real printers fail in ways your software must handle. The renderers accept bytes and stay silent. The full comparison — including exactly which emulator does what — is in the ESC/POS emulator guide.

  • Good for: iterating on receipt layout against your real print path.
  • The catch: one-directional. No status, no faults, mostly GUI apps that don't fit CI.

A network digital twin

The top of the range is a digital twin: a service that doesn't just render receipts but behaves like the device — same ports, same discovery, same status replies, same failure modes — so your application genuinely cannot tell it from hardware.

The Proxy Nodes twin is free and starts with one command:

pnpm sim   # HTTP API on :8080, raw ESC/POS on :9100, mDNS announce, fault console

From another terminal, it answers like a physical node:

curl -s localhost:8080/status          # printer, drawer, scanner state as JSON
printf '\x10\x04\x01' | nc localhost 9100   # DLE EOT status query — one byte back

What you get:

  • Raw ESC/POS on TCP :9100 like any network printer — including DLE EOT status replies that stay consistent with the simulated state. Inject a paper-out and the status byte changes exactly as the spec says it should.
  • The full Proxy Nodes HTTP API: POST /print, GET /status, a live SSE stream at GET /events, GET/PUT /config, POST /drawer/kick, POST /raw, GET /peers, and GET /scans — the same endpoints, validated by the same schema, that firmware 1.0.24 serves on a physical node.
  • mDNS announcement (_proxynodes._tcp), so printer-discovery code runs for real.
  • The peripherals around the printer, not just the printer: a cash drawer, a barcode scanner whose reads land in /scans with a verdict per read — rejects are kept with the reason, and each read's symbology is labeled as scanner-transmitted (aim) or inferred — and a scale (scale support on physical nodes is in development).
  • A fault-injection console: type paper out, cover open, or offline and the virtual hardware breaks on command. Type weight 1.25 or scan 0123456789 and the scale and scanner produce data.

That last item is the piece nothing else on this page offers. QA can script the ugly scenarios — "printer dies halfway through the dinner rush" — instead of physically yanking cables, and CI can run them nightly. And because the twin is byte-compatible with the device, the results transfer: 123 conformance specs run identically against the twin or against real hardware, so behavior verified in simulation is re-verified on a physical node — such as the Station Hub — with the same assertions. The protocol is documented and "implements the protocol" is checkable with the same free suite; source publication is on the engineering docket. Details on the simulator page.

Which do you need?

You are...Your questionUse
Designer / PM proofing a receipt"Does this layout look right?"Print-to-PDF/image driver, or virtual-printer.online if you have raw bytes
Developer writing ESC/POS"What do my bytes draw?"EscPosEmulator or escpresso for interactive work; escpos-netprinter in Docker
Developer building a POS integration"Does my app talk to a printer correctly — including status?"A digital twin on your LAN; verify DLE EOT handling against it
QA engineer"What happens on paper-out / cover-open / network loss?"A twin with fault injection — scripted, repeatable, no cable-yanking
Team lead who wants CI coverage"Will the build fail if printing breaks?"Byte-level golden tests + a twin running as a CI service — full recipes in testing receipt printing in CI

Two rules of thumb fall out of the table:

  • If the output is for human eyes, a renderer is enough. Don't stand up a network service to check a logo.
  • If the output is for a machine — your POS, your error handler, your retry logic — you need a virtual printer that can answer back and misbehave. A test double that never fails only proves your code works on days when nothing goes wrong.

The trap in the middle

The common failure mode is stopping at level two: the team eyeballs receipts against a renderer, ships, and discovers in production that nobody ever tested what the app does when the printer stops answering. Status handling and fault paths are where "printer offline" support tickets come from — test them with a tool that can produce those states on command.

For the wider context of how apps drive receipt printers in the first place — raw TCP, vendor SDKs, local HTTP APIs — see the receipt printer API guide, and browse the rest of the developer guides.

Frequently asked questions

Is there a free virtual receipt printer?
Yes, several. Print-to-PDF drivers are built into Windows and macOS; virtual-printer.online renders ESC/POS in the browser; EscPosEmulator, escpos-netprinter, and escpresso are open source; and the Proxy Nodes digital twin is free — pnpm sim starts it with the HTTP API on :8080 and raw ESC/POS on :9100.
Can I use a print-to-PDF driver to test POS receipt printing?
Only if your app prints through the OS print system. Most POS software sends raw ESC/POS bytes over TCP or USB, which never touches the OS driver stack — so a PDF driver tests nothing about that path. Use a port-9100 emulator or a digital twin instead.
What's the difference between a virtual printer and a printer emulator?
Usage overlaps, but 'virtual printer' usually means anything that captures print output (including PDF drivers), while 'emulator' implies imitating a specific printer protocol like ESC/POS. A digital twin goes furthest: it imitates the device's network behavior, status replies, and failure modes, so the same tests run against software and hardware.
How do I test what happens when the printer runs out of paper?
You need fault injection. The Proxy Nodes twin has a console command — paper out — that makes prints fail and changes DLE EOT status replies exactly as a real paper-out would, so you can verify your app alerts staff instead of dropping the order silently.
Can a virtual receipt printer run in CI?
Renderers like escpos-netprinter can run headless for visual checks. For integration tests, run a digital twin as a service in the pipeline, point your app at it, and assert on behavior — including injected faults. Proxy Nodes ships 123 conformance specs that run identically against the twin and real hardware; the CI guide has working recipes.
Does the twin behave exactly like the hardware?
That is the design contract, and it is tested rather than asserted: the twin and the physical node share one schema, and 123 conformance specs run unchanged against either target. Where physical hardware differs — USB enumeration timing, real paper — you re-run the same suite against a node to confirm.

Related reading