Web-based POS systems are easy to deploy and update, but they hit a wall at the receipt printer. A browser on an Android tablet can't simply open a Bluetooth connection to a 58 mm thermal printer and send it ESC/POS commands. That gap is why so many web POS systems depend on a small background app to do the printing, and why the quality of that app decides whether the checkout feels instant or fragile.
Why the browser can't print receipts on its own
- Most receipt printers use Bluetooth Classic. Web Bluetooth only supports Bluetooth Low Energy devices, so the classic serial (SPP) connection that most portable receipt printers use is out of reach.
- WebUSB needs extra work. Chrome on Android can reach some USB devices, but each site needs the user's permission, and you have to write your own ESC/POS driver code.
window.print()is built for paper sheets. The system print dialog adds taps, A4 margins and scaling, and gives you little control over paper cutting, cash drawers or print speed.
The practical answer is a printing engine: an Android app that runs in the background, keeps the printer connected, and accepts print jobs from your web page through a link.
How link-based printing works
Your POS builds the receipt, then navigates to a custom link. Android hands the link to the printing engine, which turns it into printer commands and sends them, with no print dialog. With Raw Print, for example:
// Raw ESC/POS bytes (e.g. from an ESC/POS encoder library) location.href = "rawprint:base64," + base64Bytes; // Plain text, encoded with the printer's character table or as an image location.href = "rawprint:" + encodeURIComponent(receiptText); // A PDF or picture as a data URI location.href = "rawprint:data:application/pdf;base64," + pdfBase64; // Let the engine download and print a receipt page location.href = "rawprint:https://pos.example.com/receipt/42";
Raw Print also accepts the older rawbt: link format, so POS systems built for an older utility can switch without code changes.
Old background utilities vs. a modern engine
Older print utilities were built when "send some bytes over Bluetooth" was enough. Shops now run POS all day on cheap phones, with Android's strict battery management and receipts in many languages. Here's what's changed:
| Area | What a modern engine should do |
|---|---|
| Staying connected | Run as a foreground service, reconnect automatically when the printer sleeps or the phone restarts, and keep printers that support it awake with harmless status checks. |
| Connections | Support Bluetooth Classic, Bluetooth Low Energy and USB OTG, because shops mix portable and countertop printers. |
| Input formats | Accept raw ESC/POS bytes, base64, plain text, HTML, pictures and PDFs, from links, intents, the share menu and the Android Print menu. |
| Job queue | Print one job at a time in order, so two receipts arriving at once never interleave on paper. |
| Languages | Print scripts the printer doesn't have (Arabic, Hindi, Thai, Chinese) as images with correct shaping and right-to-left order, instead of question marks. |
| Setup | Detect paper width and printer features automatically, and fix wrong settings from a test receipt instead of making staff edit code pages. |
| Reliability on cheap printers | Offer a slower sending mode, because small printer buffers drop data when it arrives too fast. |
| Clean output | Never add promo text or watermarks to a merchant's receipts. |
| Privacy | Keep receipt contents on the device. Receipts contain customer data. |
Integration checklist for POS developers
- Send ESC/POS when layout matters. Build receipts with an ESC/POS encoder for exact control of fonts, cuts and the cash drawer. Send text or HTML when convenience matters more.
- Plan for any language. If your customers write in non-Latin scripts, send text or HTML and let the engine render it, rather than encoding bytes yourself.
- Avoid package-locked intent links. An
intent://…;package=…;endlink only opens that exact app. A plain custom-scheme link lets the shop choose the engine. - Handle "app not installed". If the link does nothing, show a message with an install link instead of failing silently.
- Test a full day. Leave the tablet on battery for a shift and print every 10 minutes. That's when reconnection and battery-optimisation problems show up.
The bottom line
The printing engine is the least visible part of a web POS, but it's the part customers notice when a receipt doesn't come out. A modern drop-in engine keeps the printer connected, accepts whatever your POS already sends, prints any language and stays out of the merchant's way. Raw Print was built to be exactly that, and it's free.