Documentation
Print receipts instantly from any web POS โ no dialog, no delay.
A desktop bridge app that connects your web-based POS directly to a local printer
(dot matrix LPT or thermal POS) over a local HTTP server at http://localhost:3535.
Your web app sends a single fetch POST and the receipt prints immediately โ
no browser print dialog, no driver pop-ups. The app minimizes to the system tray when closed โ
the HTTP server keeps running in the background.
3535 with open CORS (callable from any origin)lp -o raw), or direct device path (/dev/usb/lp0)LPT1/COM3 for parallel dot matrix without a drivercut), cash drawer (drawer), form feed
Menu bar interface โ endpoint, printer selector, and live print log
Check if the app is running.
{
"status": "ok",
"app": "printer-bridge",
"version": "0.1.0"
}
List available printers and the current default.
{
"printers": ["EPSON_LX310", "POS58"],
"default": "POS58"
}
Send a JSON body with Content-Type: application/json. A non-JSON body (text/plain / application/octet-stream) is sent as-is to the default printer.
| Field | Type | Description |
|---|---|---|
printer |
string | Printer name. Omit to use the default printer. |
data |
string | Text to print (alias: text). |
base64 |
string | Raw bytes encoded as base64 (logos, barcodes, binary ESC/POS commands). |
feed |
number | Number of extra line feeds appended at the end. |
cut |
boolean | Cut paper (ESC/POS GS V) โ for thermal POS printers. |
drawer |
boolean | Open cash drawer (ESC/POS ESC p). |
formfeed |
boolean | Send form feed 0x0C โ for dot matrix continuous form. |
qr |
string | Text/URL printed as an ESC/POS QR code (center-aligned). |
qr_size |
number | QR module size 1โ16 (default 6, โ3 cm on 80 mm paper). |
logo |
string | PNG/JPEG image URL โ downloaded and printed as a bitmap at the top. |
logo_width |
number | Logo print width in pixels (default 300, max 576 for 80 mm paper). |
logo_text |
string | Text to the right of the logo (use \n for line breaks). When set, the logo is scaled small and layout becomes [logo โ text]. |
logo_size |
number | Logo box size when displayed beside text, in pixels (default 88). |
http://localhost โ browsers treat localhost as a secure context, so there is no mixed-content block.
Safari is not supported โ it blocks these local requests. Use Chrome, Firefox, Edge, or another Chromium-based browser.
await fetch("http://localhost:3535/print", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
data: "receipt text...\n",
cut: true,
drawer: true,
}),
});
await fetch("http://localhost:3535/print", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
logo: "https://example.com/logo.png",
logo_text: "Example Company\nExample Subtitle",
logo_size: 88,
data: "================================\n"
+ " EXAMPLE COMPANY\n"
+ " 123 Example Street\n"
+ "================================\n"
+ "No : INV/2026/06/00001\n"
+ "Date: 15-06-2026 10:32:45\n"
+ "--------------------------------\n"
+ "Name : JOHN DOE\n"
+ "--------------------------------\n"
+ "Service Charge: 45,000\n"
+ "TOTAL DUE : 47,500\n"
+ "================================\n"
+ " Thank you for your payment.\n",
qr: "https://example.com",
qr_size: 6,
feed: 3,
cut: true,
drawer: true,
}),
});
await fetch("http://localhost:3535/print", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
data: "receipt text...\n",
feed: 4,
cut: true,
}),
});
LX-310 is typically 5โ7 lines from print head to tear bar.
await fetch("http://localhost:3535/print", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
printer: "LPT1",
data: "receipt text...\n",
feed: 6,
}),
});
await fetch("http://localhost:3535/print", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
printer: "LPT1",
data: "receipt text...",
formfeed: true,
}),
});
Questions? Contact the developer at [email protected]