WebUSB says "Access denied" to your receipt printer on Windows. Here is who has it.
If you have tried to print to a USB receipt or label printer straight from the browser on Windows, you have probably met this: DOMException: Failed to execute 'open' on 'USBDevice': Access denied. It is not a pe
If you have tried to print to a USB receipt or label printer straight from the browser on Windows, you have probably met this:
DOMException: Failed to execute 'open' on 'USBDevice': Access denied.
It is not a permission you forgot to grant. The user picked the device in Chrome's chooser, and it still fails.
People keep getting stuck on this. A developer with a Zebra ZD621 posted it on Zebra's own forum: fine on macOS, "Access denied" on Windows 10 and 11, reinstalling the driver did nothing, and nobody from Zebra answered. Back in 2021 someone raised the same thing with a label printer on the WebUSB spec repo.
So I looked at my own machine to see what is actually holding the printer.
Who has the printer
My receipt printer is a BIXOLON SRP-352plusIII on USB. This asks Windows which driver service owns its USB device:
Get-PnpDevice | Where-Object { $_.FriendlyName -match 'BIXOLON' } |
Select-Object Class, FriendlyName,
@{n='Service';e={(Get-PnpDeviceProperty -InstanceId $_.InstanceId `
-KeyName DEVPKEY_Device_Service -ErrorAction SilentlyContinue).Data}},
InstanceId | Format-List
The line that matters:
Class : USB
FriendlyName : BIXOLON SRP-352plusIII
Service : usbprint
InstanceId : USB\VID_1504&PID_003F\00000001
usbprint is usbprint.sys, Microsoft's USB printing driver. It is what gives you the USB004 port and lets the Windows spooler talk to the printer. It also owns the printer's USB interface, and Windows gives an interface to one driver at a time.
Chrome's WebUSB on Windows can only open an interface that is bound to WinUSB. So open() is refused. That is the whole error.
The WebUSB editor said as much on that 2021 issue: "I don't think there is a good solution for this problem, particularly on Windows."
What you can do about it
1. Swap the driver with Zadig. This is the fix people in both threads ended up with: replace usbprint with WinUSB for that device, and WebUSB can open it. The cost is that the printer stops being a Windows printer. Nothing else can print to it until you put the old driver back, and every customer machine needs the same manual step. The Zebra poster rejected it for exactly that reason. I have not done this to my own printer, because I still need it to print normally.
2. Use a different door. If the printer has a serial or virtual COM mode, Web Serial may work where WebUSB does not. Network printers are no help here: a web page cannot open a raw TCP socket to port 9100.
3. Leave the driver alone and go through the spooler. The spooler will accept raw bytes for a print queue and pass them to the printer untouched. A web page cannot call the spooler, so this needs a small program on the PC that listens on localhost and hands the bytes over. QZ Tray works this way. So does the one I wrote, Thermalink, which is how the BIXOLON above prints from my web app with its normal driver still installed.
Which one
If you control the machine and the printer is used by one web app only, Zadig is free and it works. Write down how to undo it.
If the printer also has to work for anything else on that PC, or you are shipping to customers who will not run a driver tool, option 3 is the one that survives.
What I did not test
I did not reproduce the open() failure on my own printer; the error text and the Zadig result come from the two threads linked above. What I checked myself is the driver binding shown here, and that raw printing through the spooler works on this printer. Everything in this post is about Windows. Both threads say macOS works.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.