Desktop bridge · Windows, macOS, Linux

Your web app, printing real paper.

Printol sits on the counter PC and turns a browser into something that can drive a thermal printer and an A4 tray directly. Your app sends an invoice object over loopback; a receipt comes out of the printer. No print dialog, no PDF download, no “please press Ctrl+P”.

Printol is not running here
That is the expected answer if you have not installed it yet.
ANAND TRADERS 14 Nehru Road, Coimbatore 641001 GSTIN 33ABCDE1234F1Z5 +91 98400 11223 ------------------------------------------------ Bill INV-2043 22-08-2026 18:41 Cust Ravi Kumar +91 90000 55555 ------------------------------------------------ Item Qty Rate Amount ------------------------------------------------ Masala Dosa 2 90.00 180.00 Filter Coffee 3 40.00 120.00 Curd Rice 1 110.00 110.00 ------------------------------------------------ Subtotal 410.00 incl. CGST 2.5% 9.76 incl. SGST 2.5% 9.76 TOTAL 410.00 ------------------------------------------------ Paid by UPI YBL2209 [ QR: upi://pay?pa=anandtraders@ybl ] Thank you. Visit again. - - - - - - - - - - - - - - - - - - - - - - - -
48 columns · exactly what the printer receives

Three lines in your web app

The SDK is one ES module with no dependencies. It discovers the bridge, handles pairing, and gives you a client. You never construct an ESC/POS byte, never pick a font, never count characters to make a column line up.

  • Works from any framework, or from none — it is a plain module off a URL.
  • Pairing is remembered, so the shopkeeper approves once and never again.
  • Prefer no SDK? It is a plain JSON API — every endpoint is documented.
SDK reference →
billing.js
import { connect } from 'https://printol.crawlink.com/sdk/printol.js';

// Finds the bridge on this machine, reuses a stored token, or asks the
// person at the counter to approve this browser once.
const printol = await connect({ appName: 'Anand Traders Billing' });

await printol.print({
  templateId: 'pos.receipt.retail',
  data: bill                       // your invoice object, not ESC/POS bytes
});

How it actually works

Nothing leaves the machine. The web page talks to 127.0.0.1, the bridge talks to the printer, and the shop's data sits in a SQLite file under the user's own profile directory.

  1. 1

    Discover

    Your page probes ports 47600–47619 in parallel and keeps whichever answers with the Printol marker.

  2. 2

    Pair

    The desktop app raises a dialog naming your site and showing six digits. Somebody at the counter clicks Allow. You get a token bound to your origin.

  3. 3

    Send data

    POST an invoice object and a template id. Not HTML, not bytes — the same payload prints on 58mm and on A4.

  4. 4

    Paper

    The bridge renders, spools and reports back. Poll the job, or subscribe to the event stream.

Why a desktop bridge at all

Because a browser cannot reach a printer, and the print dialog it offers instead is wrong for a counter: it is modal, it adds margins and headers, it cannot cut paper, and it certainly cannot kick a cash drawer.

A4 and 80mm from the same call

You send the bill. The bridge renders it for whatever paper the chosen printer is loaded with — a 32-column thermal roll, an 80mm roll, or a full GST invoice on A4 — and your code does not branch.

One payload. Four papers.

No print dialog, ever

The browser is not involved in printing. The bridge talks to the OS spooler, to a network printer on port 9100, or straight to a USB thermal head. Nothing pops up, nothing needs a click, nothing prints the page header on the receipt.

Silent by design, not by hack.

Discoverable on a port range

The bridge binds the first free port between 47600 and 47619. Your web app probes all twenty at once, keeps the one that answers, and remembers it. No configuration screen asking a shopkeeper for a port number.

Found in one round trip.

It is also a working till

Catalog with stock, invoices, payments, day-end totals and CSV export — usable on its own, on a counter with no internet at all. The API is a second way into the same local database, not a bolt-on.

Works with the web app, or without one.

10 templates, ready on install

Retail receipts, restaurant bills, kitchen tickets, token slips, shelf labels, GST invoices, quotations, delivery challans. Each is a block tree you can copy and change — there is no template language to learn beyond {{ }}.

See them all →
ANAND TRADERS 14 Nehru Road, Coimbatore 641001 GSTIN 33ABCDE1234F1Z5 +91 98400 11223 ------------------------------------------------ Bill INV-2043 22-08-2026 18:41 Cust Ravi Kumar +91 90000 55555 ------------------------------------------------ Item Qty Rate Amount ------------------------------------------------ Masala Dosa 2 90.00 180.00 Filter Coffee 3 40.00 120.00 Curd Rice 1 110.00 110.00 ------------------------------------------------ Subtotal 410.00 incl. CGST 2.5% 9.76 incl. SGST 2.5% 9.76 TOTAL 410.00 ------------------------------------------------ Paid by UPI YBL2209 [ QR: upi://pay?pa=anandtraders@ybl ] Thank you. Visit again. - - - - - - - - - - - - - - - - - - - - - - - -
Retail receipt
pos.receipt.retail

The default counter receipt: items, tax summary, payment mode, QR.

THE FILTER ROOM Race Course, Coimbatore GSTIN 33ABCDE1234F1Z5 ------------------------------------------------ Table 7 Covers 4 Bill R-1189 22-08-2026 21:07 Steward Suresh ------------------------------------------------ Item Qty Rate Amount ------------------------------------------------ Paneer Tikka 1 320.00 320.00 Butter Naan 4 55.00 220.00 Dal Makhani 1 280.00 280.00 Gulab Jamun (2) 2 90.00 180.00 ------------------------------------------------ Subtotal 1,000.00 Service charge 50.00 incl. CGST 2.5% 23.81 incl. SGST 2.5% 23.81 TOTAL 1,050.00 ------------------------------------------------ Service charge is optional. Ask to remove. Thank you. - - - - - - - - - - - - - - - - - - - - - - - -
Restaurant bill
pos.receipt.restaurant

Table, server, covers, and a service-charge line above tax.

================================================ TABLE 7 KOT 4412 Steward Suresh 21:07 Course: MAIN ================================================ 2 PANEER TIKKA - less spicy 4 BUTTER NAAN 1 DAL MAKHANI ================================================ *** NEW ORDER *** - - - - - - - - - - - - - - - - - - - - - - - -
Kitchen order ticket
pos.kot.kitchen

Double-height items, no prices, one ticket per course.

THE FILTER ROOM TOKEN A-47 Counter 2 21:09 Please wait for your number to be called - - - - - - - - - - - - - - - -
Token slip
pos.token.queue

One enormous number, and nothing else that matters.

MASALA DOSA MIX 500G SKU DOSA-MSL MRP 145.00 99.00 per pack [|||| |||| ||| ||||||] 8901234567890 - - - - - - - - - - - - - - - -
Shelf / price label
pos.label.price

Name, MRP, your price and a barcode, sized for a shelf edge.

Not just a bridge — a small till

A shop that has no web app yet can still use Printol on day one: build a catalog, track stock, raise an invoice, print it, and export the day's billing as CSV. When a web app does arrive, it reads and writes that same local database through the API, so nothing has to be migrated or entered twice.

Catalog

Items, categories, units, tax rates, MRP and your rate. Import from CSV.

Stock

A ledger, not a number: every movement carries a reason and a reference.

Sale

Fast keyboard billing, split payments, held bills, reprint and duplicate.

Printers

System spooler, network 9100 or a file. A default per paper size.

Templates

Ten built-in layouts, editable, plus any your web app pushes in.

Reports

Day book, item-wise and payment-wise totals, and a CSV of the lot.

Printol · Sale
ItemQtyAmount
Masala Dosa2180.00
Filter Coffee3120.00
Curd Rice1110.00
F9 saves and prints ₹419.76

A local server, taken seriously

Software that opens a port on a shop's computer has to justify itself. Printol's answer is that the port is useless to anybody the shopkeeper has not personally approved.

Loopback only

The listener binds 127.0.0.1, not 0.0.0.0. Another machine on the shop wifi cannot reach it at all, and no firewall rule is needed.

A human approves each origin

Pairing shows your site name and origin on the counter screen with a six-digit code. No approval, no token. A page cannot pair itself.

Scoped, revocable tokens

A token is bound to the origin that asked for it and carries only the scopes granted. The shop can see every paired app and revoke any of them.

The full threat model →

Free. Not free-for-now.

Every feature, every template, as many printers and as many paired web apps as you want. There is no paid tier waiting behind a wall, and nothing in the app will ever ask you for money or for card details.

No account

Nothing to sign up for. The app has no login screen, because it has nobody to log in to.

No licence key

Nothing to activate, nothing to lose, and no licence server that could ever switch a counter off.

No meter

Print ten bills a day or ten thousand. Nothing counts them, here or anywhere else.

Bundling it with your own software is free too, and needs no permission — the FAQ covers the details.

Install it, then print from this page

The playground runs the real SDK against the real bridge on your machine. If a receipt comes out of your printer there, your integration will work.