Sign In
Products
ZPL ViewerBarcode GeneratorImage → ZPLZPL cheat sheetLabel DesignerTemplate Gallery
Developers
API QuickstartAPI ReferenceMCP ServerBulk GenerationWebhooksSDKs & ExamplesLimitsDirectPrint agent NewGitHub ActionVS Code extensionOn-Premise
Solutions
Logistics & ShippingE-CommerceERP & WMSManufacturingRetailHealthcare & LaboratoryAll solutions
Tools
ZPL Diagnostics HubZPL DebuggerSize & DPI AnalyzerDPI ConverterBarcode fit calculatorShipping Label AnalyzerFont InspectorOrientation DebuggerCalibration AssistantPrinter Compatibility CheckerBarcode Readability CheckerPrinter Language DetectorThermal Printer Test PackZPL ToolsEPL ToolsTSPL ToolsCPCL ToolsPrinter Language ConverterAll ToolsGuidesPricing
Language
EnglishTürkçeDeutsch
Home›Guides›Printing TSPL to a Bluetooth Label Printer from a Phone or Browser

Printing TSPL to a Bluetooth Label Printer from a Phone or Browser

Published:

Many low-cost 4×6 and small label printers speak TSPL and come with a Bluetooth radio. Printing to one from a web app or a phone works — people do it from Android Chrome with a few dozen lines of JavaScript — but only if you first know which Bluetooth the printer speaks, and only on browsers that implement Web Bluetooth.

Two kinds of Bluetooth

Bluetooth Low Energy (BLE) devices expose data through GATT: services that contain characteristics you read, write or subscribe to. A BLE label printer typically has one characteristic that accepts the print data. Bluetooth Classic printers usually offer a serial port profile (SPP) instead: a byte stream, like a cable. The printer's spec sheet or pairing behaviour tells you which one you have; some printers offer both.

That distinction decides what a web page can do. The Web Bluetooth API connects to BLE peripherals over GATT. For Classic devices, Chrome's own documentation points to the Web Serial API, which supports RFCOMM services such as SPP on paired devices in Chrome 117 on desktop.

Which browsers can do it

Web Bluetooth is marked experimental and is not Baseline. It is available in Chrome (desktop and Android), Edge, Opera and Samsung Internet. Safari on macOS and iOS and Firefox do not support it. On iPhone and iPad there is no supported path in Safari; third-party browsers that add their own Bluetooth bridge exist, and one of the reports below used one, but that is not part of WebKit. The API only works on HTTPS (a secure context), and requestDevice() must be called from a user gesture such as a button tap — so you need a "Connect printer" button.

The generic approach

1. Ask the user to pick the printer and declare the service you will use. 2. Connect and find a characteristic whose properties allow writing. 3. Send the TSPL job in small pieces.

// SERVICE_UUID: from your printer's documentation or a BLE scanner app
const device = await navigator.bluetooth.requestDevice({
  acceptAllDevices: true,
  optionalServices: [SERVICE_UUID],
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService(SERVICE_UUID);
const chars = await service.getCharacteristics();
const out = chars.find(
  (c) => c.properties.writeWithoutResponse || c.properties.write);

const bytes = new TextEncoder().encode(tsplJob);
const CHUNK = 180;
for (let i = 0; i < bytes.length; i += CHUNK) {
  const part = bytes.slice(i, i + CHUNK);
  if (out.properties.writeWithoutResponse) {
    await out.writeValueWithoutResponse(part);
  } else {
    await out.writeValueWithResponse(part);
  }
}

Why chunks. The Web Bluetooth specification rejects any single write longer than 512 bytes, and the usable size per write is set by the connection's negotiated MTU, which the browser negotiates and the page does not see. A label job — especially one with a BITMAP — is far longer, so it goes out in pieces. One report on a 4×6 BLE printer sent 179-byte chunks with writeValueWithoutResponse and an 8 ms gap between them without losses; treat numbers like that as a starting point for your device, not a constant.

The UUIDs are the printer's, not ours. Service and characteristic IDs differ between vendors and even models — the reports below show different short IDs on different printers — and we do not list them here. Read them from the vendor's documentation or with a BLE scanner app. One reporter found that optionalServices only worked with the full 128-bit UUID form.

A minimal TSPL job

A 50 × 30 mm label with a line of text and a Code 128 barcode, for a 203 dpi printer (8 dots per mm):

SIZE 50 mm, 30 mm
GAP 2 mm, 0 mm
CLS
TEXT 40,24,"3",0,1,1,"BOX 42"
BARCODE 40,80,"128",80,1,0,2,2,"12345678"
PRINT 1

SIZE and GAP describe the label stock in real units, CLS clears the image buffer, TEXT and BARCODE place content in dots from the top-left corner, and PRINT 1 prints one copy. This job passes the TSPL validator with no findings and fits the label in the TSPL viewer; paste your own job there before you send it over the air — a wrong SIZE or a coordinate past the edge shows up on screen instead of on a strip of labels. Command details are in the TSPL command reference, and the wider preview workflow in TSPL preview and debugging.

When it connects but nothing prints

Check that you wrote to the characteristic that accepts print data, not one used for notifications. Check the job ends with PRINT. If some printers in a family answer to their own pocket-printer commands as well, do not assume TSPL is the default: one report found TSPL on the same characteristic gave a clean, edge-aligned print where the vendor's raster commands came out cropped. A logo that prints as a black rectangle is a TSPL bit-polarity issue — see TSPL BITMAP prints a black box. For Zebra printers and ZPL from phones, the routes are different; see printing ZPL from iPhone, iPad or Android.

Sources

Frequently asked questions

Can I print to a Bluetooth label printer from a web page?

Yes, if the printer uses Bluetooth Low Energy and the browser implements Web Bluetooth: Chrome on desktop and Android, Edge, Opera and Samsung Internet. Safari on iPhone, iPad and macOS and Firefox do not support it.

Does Web Bluetooth work with Bluetooth Classic (SPP) printers?

No. Web Bluetooth talks to BLE devices over GATT. For Classic serial-port printers Chrome points to the Web Serial API, which supports RFCOMM services such as SPP on paired devices in Chrome 117 on desktop.

Why do I have to send the TSPL job in chunks?

The Web Bluetooth specification rejects a single write longer than 512 bytes, and the usable size per write depends on the connection's MTU. One report sent 179-byte chunks with an 8 ms gap without losses; tune the size for your printer.

Related guides

Printing ZPL to a USB Zebra printer from the cloud

A USB label printer has no port 9100. How the operating system's print queue carries raw ZPL, and how the Labelixa agent connects that queue to a cloud API.

Label Prints Too Large, Cropped or Blank After a CUPS Update

After a Linux update the label is enlarged, cropped, blank or the barcode is a black block. Why driver queues do this, and the raw-queue fix.

Why did my label print on the wrong printer?

Labels landing on the wrong printer are an identity problem, not bad luck: queue names, DHCP leases and shared drivers. How to diagnose and stop it.

Printing ZPL on macOS and Linux with a CUPS Raw Queue

Set up a raw CUPS queue with lpadmin, send ZPL with lp, and avoid the classic trap: a filtering queue that prints your ZPL code as plain text.

Try your own ZPL code →