Web Serial API: How It Works, Who Uses It & Open Source Projects

Web Serial API
📡

Web Serial API — Deep Dive

Talk to Microcontrollers, 3D Printers & More — Directly from Your Browser

Chrome / Edge (Desktop) Launched Chrome 89 USB & Bluetooth Serial Streams API

The Web Serial API allows websites to communicate with serial devices — microcontrollers, 3D printers, GPS receivers, oscilloscopes — connected via physical serial ports, USB-to-serial adapters, or Bluetooth serial emulation. Launched in Chrome 89, it is the successor to workarounds involving native helper apps or WebUSB serial emulation.

📌 What Is the Web Serial API?

Serial communication is one of the oldest and most widely-used protocols in computing. Almost every microcontroller (Arduino, ESP32, Raspberry Pi Pico, STM32, etc.) has a UART interface. The Web Serial API wraps the native OS serial port API and exposes it to JavaScript through the Streams API — making reads and writes asynchronous and composable.

Key distinction: Web Serial works with devices that expose a serial port to the OS (via CDC-ACM USB class or Bluetooth SPP) — not with raw USB endpoints. For raw USB access, use WebUSB. For HID devices, use WebHID.

🌐 Browser Support

BrowserSupportNotes
Chrome 89+ (Desktop)✅ Full supportWindows, Mac, Linux, ChromeOS. Not Android (OS limitation).
Edge 89+ (Desktop)✅ Full supportChromium-based Edge, same as Chrome.
Firefox❌ Not supportedNot on Firefox roadmap. Position: not harmful but not prioritised.
Safari❌ Not supportedApple has not shipped Web Serial API.

⚙️ How It Works — The API

// Feature detection
if ('serial' in navigator) { /* supported */ }

// 1. Request a port — requires user gesture
const port = await navigator.serial.requestPort({
  filters: [{ usbVendorId: 0x2341 }]  // Arduino
});

// 2. Open at 9600 baud
await port.open({ baudRate: 9600 });

// 3. Read data using Streams API
const reader = port.readable.getReader();
while (true) {
  const { value, done } = await reader.read();
  if (done) { reader.releaseLock(); break; }
  console.log(new TextDecoder().decode(value));
}

// 4. Write data
const writer = port.writable.getWriter();
await writer.write(new TextEncoder().encode('hello
'));
writer.releaseLock();

// 5. Close the port
await port.close();

🔀 Reading with Transform Streams

Serial data arrives in arbitrary chunks. Transform streams let you parse it into meaningful units:

// Parse incoming serial data line-by-line
const textDecoder = new TextDecoderStream();
port.readable.pipeTo(textDecoder.writable);
const reader = textDecoder.readable
  .pipeThrough(new TransformStream(new LineBreakTransformer()))
  .getReader();

class LineBreakTransformer {
  constructor() { this.chunks = ''; }
  transform(chunk, controller) {
    this.chunks += chunk;
    const lines = this.chunks.split('\r\n');
    this.chunks = lines.pop();
    lines.forEach(l => controller.enqueue(l));
  }
  flush(controller) { controller.enqueue(this.chunks); }
}

🏢 Who Uses Web Serial?

ProjectUse CaseURL
Arduino Create / CloudSerial monitor for Arduino boards in browsercreate.arduino.cc
Betaflight ConfiguratorConfigure drone flight controllers over serialgithub.com/betaflight
Espruino Web IDEREPL and code upload to Espruino boardsespruino.com/ide
Microsoft MakeCodeSerial console for BBC micro:bit in browsermakecode.com
Octoprint (via WebSerial)3D printer control — send G-code, monitor tempsoctoprint.org
Serial Terminal (Chrome Demo)Reference implementation — full terminal emulatorgooglechromelabs.github.io/serial-terminal

📦 Open Source Tooling

WICG/serial

Official W3C WICG spec repository for the Web Serial API. Issue tracker and living specification.

Serial API polyfill

On Android, WebUSB + the Serial API polyfill provides USB-based serial port support as a fallback.

googlechromelabs/serial-terminal

Full-featured browser serial terminal — ANSI colors, line ending options, hex view. Great reference app.

nickvdyck/webserial-polyfill

WebUSB-based polyfill for Web Serial API — provides the navigator.serial interface on top of WebUSB.

🔒 Security Model

  • User gesture requirednavigator.serial.requestPort() only callable from user interaction
  • Picker dialog — browser shows OS-level port list; site can filter by USB vendor/product ID
  • HTTPS required — only secure contexts (or localhost for development)
  • Permissions Policy — restrict serial access in iframes: <iframe allow="serial">
  • Revocable access — via port.forget() (Chrome 103+) or chrome://settings/content/serialPorts
  • One port at a time — each requestPort() grants access to one port only

Written by Alex R. | Coding with Alex | Tags: Web Serial, Browser APIs, Arduino, 3D Printers, Chrome, Serial Communication

Post a Comment

Previous Post Next Post