Serial Peripheral Test Guide

A reference for the DeskTest.net Serial Peripheral Test. The browser cannot scan your machine for COM ports: the Web Serial API only opens the one port you explicitly pick in a native chooser. This guide covers what the tool opens, which baud rate to choose, how to read every verdict, and why a receipt printer that never answers is still a pass.

Open the Serial Peripheral Test →

What does the Serial Peripheral Test check?

The tool exercises the Web Serial API (navigator.serial) - the web platform's way to talk to a serial port straight from a browser tab. Three steps run in order:

  1. Support. Feature-detects navigator.serial and confirms the page is a secure context. If either is missing, the run stops here.
  2. Connect. You click Select a serial port. The browser calls navigator.serial.requestPort() and shows its native picker. You choose your COM or USB-serial port; the tool calls port.open({ baudRate }) at the baud rate you set, then reads the USB-serial vendorId / productId back from port.getInfo().
  3. Probe. The tool acquires the port's writable stream to confirm bytes can be sent. If you left the box checked, it also writes a three-byte ESC/POS status request (DLE EOT) and reads for a moment to see whether the device answers.

The verdict centers on three things: the port opens, the baud rate negotiates, and the port is writable. A status reply is a bonus. Nothing leaves the workstation.

Why "writable" is the real test. Most receipt printers, cash drawers, and pole displays are one-way devices: the workstation sends, the device acts, and nothing comes back. So the tool proves the workstation can drive the device (the port opens and accepts bytes) rather than demanding a reply. A device that stays silent still passes.

Serial vs the USB Device Test

DeskTest.net has two device tools that sound similar but use completely different transports. Pick by how the device presents itself:

Use the Serial Peripheral Test when...Use the USB Device Test when...
The device shows up as a COM port (Windows) or /dev/ttyUSB* / /dev/ttyACM* (Linux).The device is a raw USB or HID device (barcode scanner as a keyboard, payment terminal, signature pad).
Receipt printers in serial mode, cash drawers driven over serial, pole / customer displays, serial scales.Devices with no COM port that a vendor app claims through WebUSB or WebHID.
API: Web Serial (navigator.serial).API: WebUSB / WebHID (navigator.usb / navigator.hid).

A USB-serial cable (FTDI, Prolific, CP210x, CH340) creates a COM port, so it belongs here - even though it is physically a USB device. If you are not sure, check Windows Device Manager: anything under Ports (COM & LPT) is a serial device and this is the right tool.

When should I run this?

Choosing a baud rate

Serial devices only communicate if both ends agree on the baud rate. The dropdown offers the four rates you will meet at a front desk:

BaudTypical device
9600The most common default for receipt printers, pole displays, and older serial gear. Start here.
19200Many Epson TM and Star TSP receipt printers when moved off 9600.
38400Some scales and mid-range printers.
115200Faster modern printers and many USB-serial dev boards.

If you do not know the rate, the device usually prints it on a self-test slip: power a receipt printer on while holding the FEED button and it prints its current serial settings. If the port opens but a status query never replies, try the next baud rate - a wrong rate still opens the port but produces garbage on the wire.

Web Serial always uses 8 data bits, no parity, 1 stop bit (8N1) unless configured otherwise, which matches the overwhelming majority of receipt-printer and pole-display defaults. This tool opens with those defaults and only varies the baud rate.

Reading the results

Each step renders a row with a status badge: Pending (gray), Running (yellow), Pass (green), Warn (yellow), or Fail (red). The connect step shows a card with what the port reported:

The probe step tells you one of three good outcomes: writable, device replied (bytes flow both ways - the strongest result); writable, no reply (normal for a write-only device); or writable, query skipped (you unchecked the box). All three are a pass. Only a port that opens but cannot be written is a fail.

The verdict panel at the top summarizes the run with a likely cause and a recommended next step. Copy Diagnostic Report puts a plain-text report (user-agent, secure-context status, VID/PID, baud, per-step results, any reply bytes) on the clipboard for a ticket.

Common failures and fixes

Every failure path in the tool has a named diagnosis. Here they are in the order steps run.

not-supported: navigator.serial is missing

The page asked for navigator.serial and got nothing. This browser does not ship Web Serial.

  1. You are on Firefox, Safari, or a mobile browser. None implement Web Serial and there are no plans on the Firefox or Safari roadmap as of 2026.
  2. Switch to desktop Chrome, Edge, Opera, or another Chromium-based desktop browser and re-run. Web Serial is desktop-only; it is absent on Chrome for Android and iOS.

insecure-context: not a secure context

Web Serial is only exposed over HTTPS or localhost. If you self-host this tool over plain HTTP, navigator.serial will not appear. Open https://desktest.net/serial-test/ directly, or serve your copy over HTTPS.

user-cancel: no port selected

You clicked Select a serial port, the picker appeared, and you closed it without choosing - or you clicked Skip. This is inconclusive, not a device failure.

  1. Click Reset, run again, and pick your port before the dialog closes.
  2. If the picker is empty, the browser sees no serial ports. On Windows, open Device Manager and look under Ports (COM & LPT). No entry means the USB-serial driver (FTDI, Prolific, CP210x, CH340) is not installed - install it and replug.
  3. On Linux, add your user to the dialout group (sudo usermod -aG dialout $USER) and log back in, so the browser can open /dev/ttyUSB* and /dev/ttyACM*.

open-failed: port picked but would not open

You selected a port and port.open() threw. The port exists but the OS would not hand it over.

  1. Another app holds it. Windows gives one COM port to one application at a time. Close the POS software, the vendor print utility (Epson TM Utility, StarPRNT, Bixolon), and any serial terminal (PuTTY, Tera Term), then run again.
  2. Wrong baud rate. A mismatched rate can still fail on some adapters. Try the next rate in the dropdown.
  3. Stale port. Unplug and replug the USB-serial cable so the OS re-enumerates it, then re-run. On Windows the COM number can change after a reconnect - re-pick it in the chooser.

blocked: serial access blocked by policy

The browser threw a SecurityError or NotAllowedError when asked for a port. An enterprise policy or a site setting is blocking serial access.

  1. Chrome and Edge honor DefaultSerialGuardSetting. If IT set it to block, no port opens. Ask whoever manages the GPO to allow this origin (see For IT admins).
  2. Check chrome://settings/content/serialPorts is not set to block.
  3. If this page is embedded in an iframe, the framing page must send Permissions-Policy: serial=(self) and allow it on that frame.

not-writable: opened but not writable

The port opened but its writable stream was missing or already locked, so no bytes could be sent.

  1. Click Reset (which closes any handle this page still holds) and run again.
  2. Unplug and replug the device to force a clean port, then re-run.
  3. If it keeps failing, suspect the cable or adapter - swap in a known-good USB-serial cable.

For IT admins

You can pre-authorize serial ports for a fleet so users never see the chooser. This is the right answer for a fixed receipt printer on a known workstation and origin.

Chrome and Edge support the policy SerialAllowUsbDevicesForUrls, which grants named USB-serial devices (by vendor and product ID) to a list of origins without a per-user click:

[
  {
    "devices": [{ "vendor_id": 1027, "product_id": 24577 }],
    "urls": ["https://desktest.net", "https://pos.internal.example.com"]
  }
]

The example pre-authorizes an FTDI adapter (vid 0x0403 = 1027, pid 0x6001 = 24577). Push it as a GPO under Computer Configuration, Administrative Templates, Google Chrome (or Microsoft Edge). Note that this policy covers USB-serial devices with a VID/PID; native motherboard COM ports have no USB identity and cannot be pre-authorized this way.

The default for everything else is set by DefaultSerialGuardSetting: 2 blocks all sites, 3 asks (the browser default). Setting it to 2 plus an allowlist is a workable lockdown stance for kiosks.

Safari and Firefox have no equivalent. Neither ships Web Serial and neither has a policy to enable it. If Safari or Firefox is your standard browser, this page fails step 1 with not-supported on every workstation - and a browser-based POS that needs Web Serial will not work there either.

Behind the scenes

The serial port chooser is drawn by the browser, not the page. The page calls navigator.serial.requestPort() and the browser renders the list; a page cannot read it, style it, or pre-select an entry. That user-gesture-and-consent boundary is what lets the API exist at all - the tool never opens a port without your click.

Once you pick a port, port.open({ baudRate }) configures the line and exposes two Web Streams: port.readable and port.writable. The tool acquires a writer to prove bytes can be sent, and (optionally) a reader to catch a reply. Both stream locks are released and port.close() is called when the test finishes or you click Reset, so the port is never left held.

The optional status query is ESC/POS DLE EOT n (bytes 10 04 01), the real-time status request defined by Epson's ESC/POS command set. It asks the printer to transmit one status byte; it does not print and does not open a cash drawer (a drawer kick is a different command, ESC p / DLE DC4, which this tool never sends). A printer in bidirectional mode answers with a status byte encoding drawer, feed, and error state; a write-only device ignores it, which is why the tool never treats silence as failure. Uncheck the box to skip the query entirely and only verify writability.

port.getInfo() returns { usbVendorId, usbProductId } for a USB-serial adapter and an empty object for a native COM port - the tool handles both. Authorized ports persist per-origin: a port you granted on desktest.net is not visible to your internal POS site without a separate grant, and users revoke grants at chrome://settings/content/serialPorts.

No vendor IDs, baud rates, or reply bytes leave the browser. Copy Diagnostic Report puts the data on your clipboard for you to paste into a ticket.

Elsewhere on the web: