Web Serial API
Published Updated
Web Serial API — The Web Serial API lets a web app request access to a serial port via navigator.serial.requestPort() and read from or write to it using the port’s readable and writable streams.
Browser & ecosystem support
Section titled “Browser & ecosystem support”- Legend
- Yes
- Partial
- Flag
- No
- Unknown
| Browser / Platform | Support | Versions | Confidence | Source | Notes |
|---|---|---|---|---|---|
| Chrome (Desktop) | Yes | 89 | high | source | — |
| Chrome (Android) | Yes | 148 | high | source | — |
| Edge (Desktop) | Yes | 89 | high | source | 1 |
| Firefox (Desktop) | Yes | 151 | high | source | — |
| Firefox (Android) | No | — | high | source | 2 |
| Safari (macOS) | No | — | high | source | 3 |
| Safari (iOS) | No | — | high | source | 45 |
| Samsung Internet | Partial | 30.0 | high | source | 67 |
| WebView (Android) | No | — | high | source | 8 |
- Derived by browser-compat-data mirroring from Chrome.
- No Firefox for Android support is recorded in browser-compat-data.
- No Safari support is recorded in browser-compat-data.
- No Safari on iOS support is recorded in browser-compat-data.
- Derived by browser-compat-data mirroring from Safari.
- Serial ports are only available if they're provided by Bluetooth RFCOMM serial port emulation.
- Derived by browser-compat-data mirroring from Chrome Android.
- Implementation tracking: https://crbug.com/40740509.
How to use it
Section titled “How to use it”Requesting a port must happen inside a user gesture, and filters narrows the picker to
ports matching a USB vendor ID. Once the user selects a port, open it with a baud rate
before reading or writing:
async function connectSerialPort() { const port = await navigator.serial.requestPort({ filters: [{ usbVendorId: 0x2341 }], }); await port.open({ baudRate: 9600 }); return port;}How to detect it at runtime
Section titled “How to detect it at runtime”Check for navigator.serial before offering the feature, and give the reader a fallback
path when it is absent:
if ('serial' in navigator) { connectButton.hidden = false;} else { connectButton.hidden = true; fallbackNotice.textContent = 'This browser cannot access serial ports from the page.';}Practical checklist
Section titled “Practical checklist”- Requires a secure context — plain HTTP origins other than potentially trustworthy ones like
localhostcannot use it. requestPort()needs transient user activation (a click or keydown handler); without it, the returned promise rejects with aSecurityErrorDOMException.port.readableandport.writablearenulluntil you callport.open({ baudRate }); get the reader/writer from those streams only afteropen()resolves.- The picker only lists ports matching the
filtersyou pass, so a request with no matching device leaves the user with nothing to select, which rejects the returned promise. - Support is not uniform across browsers or platforms: per MDN browser-compat-data, Chrome for Android has full support from version 148; in Chrome 138-146 it only exposed serial ports provided through Bluetooth RFCOMM serial port emulation, not a wired connection — check the support table above before relying on the feature for a given target.
Where to go next
Section titled “Where to go next”See WebUSB API for raw access to USB devices not claimed by an OS driver — a related but distinct low-level device access API.
See also WebHID API for input/output device access via HID reports.
← Back to the Compatibility explorer.