In this guide, you’ll learn how to create and use a web-based “Serial Monitor” for your ESP32 projects using the WebSerial library. This creates a web-based interface to output debugging messages, as you would do with a regular serial monitor. You can also send messages from the web-based serial monitor to the ESP32.
We have a similar tutorial for the ESP8266 board: ESP8266 NodeMCU WebSerial Web-based Remote Serial Monitor
Web-based Serial Monitor
In most of your ESP32 projects, you use the serial monitor to output debugging messages that help you better understand what’s happening with the microcontroller.
You create a Serial communication between your board and your computer, and then you can visualize the messages using the serial monitor. However, when your board is not connected to your computer, you can’t see the debugging messages.
A workaround for this issue is to use a web-based serial monitor—the ESP32 hosts a web server that serves a page to visualize the messages as you would with the “regular” serial monitor. The WebSerial web page also allows you to send data from the web page to your board.
For this tutorial, we’ll use the WebSerial library.
If you like this library and you’ll use it in your projects, consider supporting the developer’s work.
WebSerial Features
List of WebSerial features:
- Works on WebSockets;
- Realtime logging;
- Any number of serial monitors can be opened on the browser;
- Uses AsyncWebserver for better performance.
WebSerial Functions
Using WebSerial is similar to use the serial monitor. Its main functions are print() and println():
- print(): prints the data on the web-based serial monitor without newline character (on the same line);
- println(): prints the data on the web-based serial monitor with a newline character (on the next line);
Installing the WebSerial Library
For this project, we’ll use the WebSerial.h library. To install the library:
- In your Arduino IDE, go to Sketch > Include Library > Manage Libraries…
- Search for webserial.
- Install the WebSerial library by Ayush Sharma.
You also need to install the ESPAsyncWebServer and the AsyncTCP libraries. Click the following links to download the libraries’ files.
To install these libraries, click on the previous links to download the libraries’ files. Then, in your Arduino IDE, go to Sketch > Include Library > Add .ZIP Library…
If you’re using VS Code with the PlatformIO extension, copy the following to the platformio.ini file to include the libraries.
lib_deps = ESP Async WebServer
ayushsharma82/WebSerial @ ^1.1.0
ESP32 WebSerial Example
The library provides a simple example about creating the Web Serial Monitor to output and receive messages. We’ve modified the example a bit to make it more interactive.
This example prints Hello! to the web-based serial monitor every two seconds. Additionally, you can send messages from the web-based serial monitor to the board. You can send the message ON to light up the board’s built-in LED or the message OFF to turn it off.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp32-webserial-library/
This sketch is based on the WebSerial library example: ESP32_Demo
https://github.com/ayushsharma82/WebSerial
*/
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <WebSerial.h>
#define LED 2
AsyncWebServer server(80);
const char* ssid = "REPLACE_WITH_YOUR_SSID"; // Your WiFi SSID
const char* password = "REPLACE_WITH_YOUR_PASSWORD"; // Your WiFi Password
void recvMsg(uint8_t *data, size_t len){
WebSerial.println("Received Data...");
String d = "";
for(int i=0; i < len; i++){
d += char(data[i]);
}
WebSerial.println(d);
if (d == "ON"){
digitalWrite(LED, HIGH);
}
if (d=="OFF"){
digitalWrite(LED, LOW);
}
}
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.printf("WiFi Failed!\n");
return;
}
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// WebSerial is accessible at "<IP Address>/webserial" in browser
WebSerial.begin(&server);
WebSerial.msgCallback(recvMsg);
server.begin();
}
void loop() {
WebSerial.println("Hello!");
delay(2000);
}
Before uploading the code to your board, don’t forget to insert your network credentials.
In this example, the ESP32 is in station mode. This example also works in access point mode. To learn how to set up your ESP32 as an access point, read:
How the Code Works
Continue reading to learn how the code works or skip to the demonstration section.
First, you need to include the required libraries for WebSerial. The WiFi.h library is needed to connect the ESP32 to a Wi-Fi network.
#include <WiFi.h>
The WebSerial library uses the AsyncTCP and the ESPAsyncWebServer libraries to create the web-based serial monitor.
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
Finally, the WebSerial library provides easy methods to build the web-based serial monitor.
#include <WebSerial.h>
Create a variable called LED for the built-in LED on GPIO 2.
#define LED 2
Initialize an AsyncWebServer object on port 80 to set up the web server.
AsyncWebServer server(80);
Insert your network credentials in the following variables:
const char* ssid = "REPLACE_WITH_YOUR_SSID"; // Your WiFi SSID
const char* password = "REPLACE_WITH_YOUR_PASSWORD"; // Your WiFi Password
Handling Received Messages
The following function receives incoming messages sent from the web-based serial monitor. The message is saved on the d variable. Then, it is printed on the web serial monitor using WebSerial.println(d).
void recvMsg(uint8_t *data, size_t len){
WebSerial.println("Received Data...");
String d = "";
for(int i=0; i < len; i++){
d += char(data[i]);
}
WebSerial.println(d);
Next, we check if the content of the d variable is ON or OFF and light up the LED accordingly.
if (d == "ON"){
digitalWrite(LED, HIGH);
}
if (d=="OFF"){
digitalWrite(LED, LOW);
}
setup()
In the setup(), set the LED as an OUTPUT.
pinMode(LED, OUTPUT);
Connect your board to your local network:
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.printf("WiFi Failed!\n");
return;
}
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Initialize the web-based serial monitor with the begin() method on the WebSerial object. This function accepts as an argument an AsyncWebServer object.
WebSerial.begin(&server);
Register the recvMsg() as a callback function using the msgCallback() method on the WebSerial object. The recvMsg() function will run whenever you send a message from the monitor to the board.
WebSerial.msgCallback(recvMsg);
Finally, initialize the server.
server.begin();
It is just after calling this line that the web-based serial monitor will start working.
loop()
In the loop(), print the Hello! message every 2000 milliseconds (2 seconds) using the println() function on the WebSerial object.
void loop() {
WebSerial.println("Hello!");
delay(2000);
}
Demonstration
After inserting your network credentials, you can upload the code to your board.
After uploading, open the “regular” serial monitor at a baud rate of 115200. The board’s IP address will be printed.
Now, open a browser on your local network and type the ESP IP address followed by /webserial. For example, in my case:
192.168.1.85/webserial
The WebSerial page should load.
As you can see, it is printing Hello! every two seconds. Additionally, you can send commands to the ESP32. All the commands that you send are printed back on the web serial monitor. You can send the ON and OFF commands to control the built-in LED.
This was just a simple example showing how you can use the WebSerial library to create a web-based serial monitor to send and receive data.
Now, you can easily add a web-based serial monitor to any of your projects using the WebSerial library.
Wrapping Up
In this quick tutorial, you learned how to create a web-based serial monitor. This is especially useful if your project is not connected to your computer via Serial communication and you still want to visualize debugging messages. The communication between the web-based serial monitor and the ESP32 uses WebSocket protocol.
We hope you find this tutorial useful. We have other web server tutorials you may like:
- ESP32 Web Server using Server-Sent Events (Update Sensor Readings Automatically)
- ESP32 WebSocket Server: Control Outputs (Arduino IDE)
- ESP32 OTA (Over-the-Air) Updates – AsyncElegantOTA using Arduino IDE
Learn more about the ESP32 with our resources:
- Build Web Servers with ESP32 and ESP8266 eBook
- Learn ESP32 with Arduino IDE (eBook + video course)
- More ESP32 tutorials and projects…
Thank you for reading.
Hi there, nice feature!
Is it possible to send plotter data?
Hi Daniel, did you get any response? Or found any answer?
Data on how to include WiFi.h incomplete as far as i see using VS platform. I copied the
lib_deps = ESP Async WebServer as instructed to platform.ino
ayushsharma82/WebSerial @ ^1.1.0
but all the following includes
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <WebSerial.h>
resulted in errors. Files not found!
Hi.
Those two lines are all you need.
The WiFi library is included by default.
The AsyncTCP is called by the ESPAsyncWebServer that is included in the lib_deps.
The WebSerial is also included in the lib_deps.
What is exactly the error that you get?
Regards,
Sara
I moved the code to the Arduino esp 8266 IDE and it compiled with no error, but when I use the displayed IP on both an Android and PC browser I get refuse to connect. My router sees the devices IP. I will cut and paste the example again and see what happens. Where is the HTML of image located in library?
I will go load back to VS and get the exact error later today.
I think your IP is not public, so you need an Public IP.
does it also support for esp8266?
Hi.
Yes.
Check the ESP8266 tutorial: https://randomnerdtutorials.com/esp8266-nodemcu-webserial-library/
Regards,
Sara
Froehlich again. My fault on failure to connect, I forgot the /webserial after ip. Now if I can get VS to work.
Great!
I’m glad you found the issue.
You guys are great, thanks for this tutorial
Second that, You guys are great!
Todos os seus Tutoriais são excelentes, parabéns!
Carlos Bruni
Salvador Bahia Brasil
good job, as usual!
Small question: how to modify the server page?
Good evening Sara,
Sorry to bother you but as this topic interests me a lot, I would love to put this great tutorial into practice.
I just copy / paste the source code into my Arduino IDE, I installed the WebSerial then ESPAsyncWebServer and AsyncTCP libraries there as shown in the tutorial. I find them in the list of original and contributory libraries.
I documented my username and password, restarted my computer but nothing helped. The response is always “Compilation error for ESP32 Dev Module board”.
What is my problem?
Hi Claude.
Can you provide more details about the error?
Regards,
Sara
My ESP32 boards (I have tried 4 from 2 different vendors) really struggle to connect to my network, though sometimes they will manage.
In contrast, my ESP8266 boards connect easily. Both boards see the network with similar strength when I run a scan. I got the ESP8266 version of this project working immediately.
I’m using Arduino, and I feel there’s a configuration problem somewhere. I think the hardware is ok (because of the scan) and the software sometimes (but rarely) works, so it’s not grossly wrong.
Any ideas?
Hi Doug.
What are the models of your ESP32 boards?
Regards,
Sara
Not sure why just yet, but adding the WebSerial.h library into a dual-core sketch using the xTaskCreatePinnedToCore option (yes, I am using core0 for all my wifi related stuff) is throwing declaration issues when trying to compile. Deleting WebSerial.h restores the sketch. Again, not sure what’s going on yet…
FYI.
Thanks Sara for your interest in my problem.
Following is the full message received from the Arduino IDE.
The part about using one of the two WiFi libraries usually doesn’t bother me.
= = = = = = = = =
C:\Users\Claude\Documents\Arduino\libraries\AsyncTCP-master\src\AsyncTCP.cpp: In function ‘bool _start_async_task()’:
C:\Users\Claude\Documents\Arduino\libraries\AsyncTCP-master\src\AsyncTCP.cpp:221:141: error: ‘xTaskCreateUniversal’ was not declared in this scope
xTaskCreateUniversal(_async_service_task, “async_tcp”, 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
^
Plusieurs bibliothèque trouvées pour “WiFi.h”
Utilisé : C:\Users\Claude\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.1\libraries\WiFi
Non utilisé : C:\Program Files (x86)\Arduino\libraries\WiFi
exit status 1
Erreur de compilation pour la carte ESP32 Dev Module
I finally solved my problem by upgrading the ESP32 board manager of my Arduino IDE :
1.0.1 -> 1.0.6
Good day to everyone
Great! I would suggest that.
I’m glad you solved the issue.
Regards,
Sara
hi
i was wondering if the code works with the esp32 feather?
I tried but it wrote in the serial: wifi failed
do you have any advice?
Hi.
Yes, it should work with any ESP32 board.
What is exactly the error that you get?
Regards,
Sara
Hello! I bought the book, and learned quite a lot.
Would it be possible to show us how to do something like this serial monitor library in more of a home-made style so that we can modify it and add to it?
The library works fine but I’d like to do more on the web page than just this one function.
Rhanks
Doug
Hi.
To do that, you would have to create your own WebSerial.
You can do that using WebSocket protocol with the ESP32.
You would need to set up an input field where the user enters messages to send to the ESP32, and some HTML text that would be replaced with the messages sent from the ESP32.
I don’t think you can modify the web page using the library. But, you can ask here: https://github.com/ayushsharma82/WebSerial/issues
Regards,
Sara
Hi,
Yes, I looked at the webserial library with the hope of learning more about its implementation. Unfortunately, it is pretty much obscured, which is not what I’m used to for Arduino-style libraries. Perhaps it is because there is a commercial cousin of the library available?
I will review the websocket section of the book and have a go. Any more hints about generating the html output would be much appreciated!
Doug
Hi again.
If you need further help and since you’ve bought our eBook, please post your questions on the forum: https://rntlab.com/forum/
It is easier to follow and answer your questions there.
Regards,
Sara
Hello there,
It’s amazing what I’ve learned the last few weeks, thanks to your tutorials!
Thanks again!
Thanks for mentioning how to implement this Webserial library.
I tried combining it with a static IP adress, but that didn’t work.
Probably something went wrong on my side, but if other people have the same problem let me know. Or even better a solution:)
Kind Regards,
Michiel
Hi.
Thanks for following our work.
To set a static IP address, you can follow this tutorial: https://randomnerdtutorials.com/esp32-static-fixed-ip-address-arduino-ide/
Regards,
Sara
Why this problem occurs
exit status 1
An error occurred when compiling for the development board NodeMCU-32S.
Hi.
What is exactly the error that you get?
Can you provide more details?
Regards,
Sara
In file included from E:\Arduino\libraries\AsyncTCP\src\AsyncTCP.cpp:24:0:
E:\Arduino\libraries\AsyncTCP\src\AsyncTCP.h:53:8: note: forward declaration of ‘struct ip_addr’
struct ip_addr;
^
E:\Arduino\libraries\AsyncTCP\src\AsyncTCP.cpp:982:33: error: invalid use of incomplete type ‘struct ip_addr’
connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port);
^
In file included from E:\Arduino\libraries\AsyncTCP\src\AsyncTCP.cpp:24:0:
E:\Arduino\libraries\AsyncTCP\src\AsyncTCP.h:53:8: note: forward declaration of ‘struct ip_addr’
struct ip_addr;
exit status 1
An error occurred when compiling for the development board NodeMCU-32S.
Hi.
I never faced that issue.
I suggest updating your ESP32 board’s installation as well as installing all the libraries again.
Regards,
Sara
Thanks for this tutorial.
It works well and most important thing, you make it easy to understand.
One thing, if you do send a message every 2 seconds is it normal the ESP32 to get warm? I think because to use a lot the WiFi communications. Or is it normal?
Thank you :-).
Hi.
it is normal to get a little warm, but not “too hot”. 😀
Regards,
Sara
Hi Sara,
I want to display messages the ESP32 recieves on the Serial2 port via wifi on my browser. Can you help me realise that? I used the webserial library with the ESP32 in AP mode and already put
while(Serial.available()){
webserial.print(char(Serial2.read());
}
in loop(). This transmits something but not the data im really recieving.
I´m really new to programming and I would really appreciate your help!
Thank you!
Easy to setup and works great!
I’m trying to develop a set of tools to allow me to remotely manage an ESP. I’d like to be able to OTA SW update (another good tutorial, thanks), watch debug output and change settings.
I’m concerned that there is no security (login) required to access this stream. There is a login option for AsyncElegantOTA, but I don’t see one for WebSerial. Any thoughts on how to secure this stream or another approach to securely monitor this output?
Some libraries write to Serial directly. I would like to duplicate these writes to both Serial and WebSerial. Any suggestion on how to achieve that?
Just what I needed!
I was going to ask in the tutorial section how to do this, when I ran into this. Thanks!
How to save the data from webserial as a .txt file?
Hi Rookie, have you found out the answer to this? Thank you
How is Web Serial different from the usual client.print() command?
Thanks,
Bernie
Hi,
did you see that recently, it cannot be compile anymore with the same error:
ESPAsyncWebServer-master\src/WebAuthentication.cpp:73: undefined reference to `mbedtls_md5_starts’
Even the example of the library have this issue.
Weird because before was great
LAurent
Hi.
Check your ESP32 boards version in Tools > Boards > Boards Manager > ESP32.
Check if downgrading solves the issue.
Regards,
Sara
Thanks Sara for your answer. Always well appreciated.
However, still same after upgrade last status of ESP32
Tried to downgrade all the relating libraries, same result. Several undefined starting by:
undefined reference to `SHA1Init’
I use the demo sketch from webserial. Few weeks ago, all was working well.
Still ok on your side this tutorials ?
Laurent
What is the ESP32 boards version you have installed?
Downgrade to an older version and check if that solves the issue.
Regards,
Sara
I was in 2.0.2 and I upgrade to 2.03 and NOK
Tried to downgrade to 2.0.1, still NOK
2.0.0 NOK too
Laurent
If the issue persists, better to take a look at the library issues page: https://github.com/ayushsharma82/WebSerial/issues
Regards,
Sara
If esp32 lost wifi connection , I can use webserial? TKS you
Excellent tutorial, Sara. Used webserial monitor to avoid hardware complication. My case: Pixel6 has adaptive charging. OnePlus6 does not. Using an IR controlled plug, a NodeMCU ESP8266 and one IR led, a sketch which reads time from the internet (NTP) starts my plug every morning to charge the OnePlus6. Hardcoding the start time is ugly. Adding hardware (LCD display and buttons) is possible but not desirable. Using Webserial Monitor to change the start time of phone charging was an elegant solution. Thank you for this and many other tutorials. Regards, Adrian from Romania.
P.S. Book on Node-RED was a pleasure to read and instructive.
That’s great!
I’m glad our tutorials are useful.
Thank you so much for supporting our work.
Regards,
Sara
Can I use both webserial and webota in single webpage? If yes how?
Your sample program works fine, but whenever i try to build upon it I have problems. Any subroutine I try to define gives me the error “mysubroutine” was not declared in this scope.
The program will run just fine if I comment out the #include <WebSerial.h> line.
I did not see anyone else having this problem, but I have gone all the way down to the minimum “blink” program and have the same error when I try to add a subroutine.
using Arduino 1.8.6, with doit esp32 devkit v1
#include <WebSerial.h>
int t = 3; //a test number
String s = “”; // string representation of number
void setup() {
// initialize digital pin LED_BUILTIN as an output.
Serial.begin(115200);
}
void loop() {
delay(1000); // wait for a second
Serial.println(t);
s = PadString(t);
Serial.println(s);
}
String PadString(int Ins){
String s = String(Ins);
int len = s.length();
if(len==1){s = “00”+s;}
if(len==2){s = “0”+s;}
return s;
}
Hi.
Move your subroutine to a place in the code before the loop() and setup().
Regards,
Sara
I think I had tried that to no avail. But I have resolved the issue. In desperation i upgraded to arduino IDE 2.03. So I now have both 1.86 and 2.03 on my machine which so far seem to coexist without incident. While installing it asked me to update my libraries, which I allowed. It then forced me to get rid of some duplicate libraries to do the update. (took me a couple days to recover from updating the libraries, forgot where I had changed some of them to work with most of my programs) The code now compiled with subroutines , placed anywhere, and I am on my way. Interestingly the code now complies on my 1.86, so apparently updating one of the libraries resolved it. Don’t know why that should have made any difference, especially in my minimal program above, but that seems to have resolved my issue.
Hi Sara and Rui,
Great tutorials and very well explained. You guys are doing a fantastic job.
With your guidance I have been able to apply Web Serial in one of my projects and control various inputs without any hassle on a ESP32.
But know I found that I would like to clear at some point programmatically the Web Serial screen. However, none of the clear print statements I know have worked.
Do you have by any chance, a solution to clear the Web Serial display, with a particular command or print statement, without restarting the ESP32?
Thank you very much for any recommendations or help.
Greetings,
Heinz
Hi.
I’m not sure how to do that.
Maybe you can try asking the library developer.
Let me know if you find an answer.
Regards,
Sara
Hi Sara
Loving this!
2 questions:
1) Is there a way to secure the page with username and password similar to https://github.com/ayushsharma82/ElegantOTA?
2) Im cant seem to get webserial.print from the void setup() function to display in webserial. Is this expected? I am trying to generate them after WebSerial.begin(&server); in void setup()
Hi, I seems that every one is quite satisfied, but for me it’s not working here are the compile errors :
undefined reference to
SHA1Init'
SHA1Update’undefined reference to
undefined reference to `SHA1Final’
I did exactly what is described…
Can someone help me?
Thank you.
Hi, is there any possibillity to combine OTA and WEBserial? After all, we can put OTA on port 8080 and WEBSerial on port 80.
…C:\Users\syamala\Documents\Arduino\LCD_display_Server\LCD_display_server\LCD_display_server.ino: In function ‘void setup()’:
LCD_display_server:43:13: error: ‘class WebSerialClass’ has no member named ‘msgCallback’
43 | WebSerial.msgCallback(recvMsg);
| ^~~~~~~~~~~
exit status 1
‘class WebSerialClass’ has no member named ‘msgCallback’….
Hi It is showing msgCallback is not a member in the webserialclass. Why??
Please help…
Try replacing WebSerial.msgCallback(recvMsg) with WebSerial. onMessage(recvMsg). I think this is one of the changes in the latest version
Hi
Just noticed that all my ESP32 programs for home equipment no longer compile, and neither does the code above. Updated libraries to latest version and board the 3.0.2 but still not working
Compilation error: ‘class WebSerialClass’ has no member named ‘msgCallback’
Is there a quick fix to this
It seems that is you are using Webserial 2.0.4 then you need to change WebSerial.msgCallback(recvMsg) to become WebSerial.onMessage(recvMsg)
The ESP32 board was version 3.0.2
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1448
load:0x40078000,len:14828
ho 0 tail 12 room 4
load:0x40080400,len:4
load:0x40080404,len:3356
entry 0x4008059c
ets Jun 8 2016 00:22:57
‘IP’ is not getting printed here and the above message is getting printed manytimes…. in serial monitor
This tutorial is great! I have used these concepts in my code to allow a user of the hardware to change EEPROM settings with a cell phone. I am using v1.4.0 . The new version is not usable and really its not clear how to make use of it. The gitHUB info and examples are totally useless. Apparently the various server libs used here don’t work with the v 2.0.8 version. It would be a great service if you guys would update the tutortial to use v 2.0.8 of WebSerial so we can get an idea of what is going on. Thanks for this and all the other great tutorials.