This sketch demonstrates WebUSB sending text from the browser to a microcontroller which in turn sends the text back to the browser.

Load the Example Code to Your Microcontroller

Click Download in the code window below and save the Arduino sketch in your Arduino sketches folder. Open the code with the Arduino IDE File -> Open command.

 Adafruit invests time and resources providing this open source code,
 please support Adafruit and open-source hardware by purchasing
 products from Adafruit!

 MIT license, check LICENSE for more information
 Copyright (c) 2019 Ha Thach for Adafruit Industries
 All text above, and the splash screen below must be included in
 any redistribution

/* This sketch demonstrates WebUSB as web serial with browser with WebUSB support (e.g Chrome).
 * After enumerated successfully, Browser will pop-up notification
 * with URL to landing page, click on it to test
 *  - Click "Connect" and select device, When connected the on-board LED will litted up.
 *  - Any charters received from either webusb/Serial will be echo back to webusb and Serial
 * Note: 
 * - The WebUSB landing page notification is currently disabled in Chrome 
 * on Windows due to Chromium issue 656702 ( You have to 
 * go to landing page (below) to test
 * - On Windows 7 and prior: You need to use Zadig tool to manually bind the 
 * WebUSB interface with the WinUSB driver for Chrome to access. From windows 8 and 10, this
 * is done automatically by firmware.

#include "Adafruit_TinyUSB.h"

// USB WebUSB object
Adafruit_USBD_WebUSB usb_web;

// Landing Page: scheme (0: http, 1: https), url
// Page source can be found at
WEBUSB_URL_DEF(landingPage, 1 /*https*/, "");

int led_pin = LED_BUILTIN;

// the setup function runs once when you press reset or power the board
void setup()
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
  // Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040

  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, LOW);
  //usb_web.setStringDescriptor("TinyUSB WebUSB");


  // wait until device mounted
  while( !TinyUSBDevice.mounted() ) delay(1);

  Serial.println("TinyUSB WebUSB Serial example");

// function to echo to both Serial and WebUSB
void echo_all(uint8_t buf[], uint32_t count)
  if (usb_web.connected())
    usb_web.write(buf, count);

  if ( Serial )
    for(uint32_t i=0; i<count; i++)
      if ( buf[i] == '\r' ) Serial.write('\n');

void loop()
  uint8_t buf[64];
  uint32_t count;

  // From Serial to both Serial & webUSB
  if (Serial.available())
    count =, 64);
    echo_all(buf, count);

  // from WebUSB to both Serial & webUSB
  if (usb_web.available())
    count =, 64);
    echo_all(buf, count);

void line_state_callback(bool connected)
  digitalWrite(led_pin, connected);

  if ( connected )
    usb_web.println("WebUSB interface connected !!");

Ensure you have set up the IDE per the previous instructions for the board type, correct library, and use of TinyUSB.

Connect the microcontroller to your computer/device via the USB cabling discussed previously.

Place your Circuit Playground Express in bootloader mode by pressing the tiny onboard reset button once or twice (depending on how it was programmed earlier). The board should flash red briefly and then display a green circle of lights. Select the correct port for the board in the IDE by going to Tools -> Port in the menus and you should see the Circuit Playground Express listed as a possible selection.

Use Sketch -> Upload (or the circle with the right arrow button) to load the Arduino code onto the Circuit Playground Express. If you get any compile errors, look on the previous page for library requirements, the correct board definition file, and selecting TinyUSB.

After upload, the ring of NeoPixel LEDs on the CPX will turn off. The board is now ready to test.


There is a known bug that when a WebUSB board is connected to an Android device, this example sends text but does not receive it back correctly. This is being looked into. All other devices (PC, mac, Linux, Chromebook, etc) work as expected.

After enumerating successfully, Chrome will pop-up a notification with a URL to a landing page, click on it to test. On Windows there is a known bug, you'll have to click on the button below to go to the test web page.

Click "Connect" and select your microcontroller. For example: Circuit Playground Express.

When connected, the right Receiver window will display the text "TinyUSB WebUSB Serial example" - this is the board sending its first text message to the browser via WebUSB.

Click inside the left Sender window with your mouse or cursor. 

Type something such as "Adabot is my friend"

As you type, the characters are echoed in the receiver window. 

The last line shows that I used a backspace to correct a typo. The echo routine in the Arduino example code doesn't recognize backspace as going back one character so the mistyped character is echoed in the Receiver window.

Behind the Scenes

The computer/mobile device sends character data from the browser Sender window to the microcontroller via the USB serial connection. The microcontroller looks for text and immediately sends the text back via WebUSB to the browser where it appears in the Receiver window.

When connected, this process may continue indefinitely, the board will continuing echoing typed text. The microcontroller does not recognize extended keyboard input at present (as shown with backspace).

This demonstrates two way communications from the browser to the microcontroller. The Arduino program can be changed to do any manner of serial communication, unidirectional or bidirectional.

When done, you can click the Disconnect button to stop communications.

This guide was first published on Aug 27, 2019. It was last updated on Aug 27, 2019.

This page (Serial Communications Example) was last updated on Aug 27, 2019.

Text editor powered by tinymce.