ESP32 Arduino: Asynchronous HTTP web server

The objective of this post is to explain how to configure an asynchronous HTTP web server on the Arduino core running on the ESP32. The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.


The objective of this post is to explain how to configure an Asynchronous HTTP web server on the Arduino core running on the ESP32.

As example, we will develop a very simple “hello world” application that will return a message to the clients that connect to it. As client, we will use a web browser.

The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.

If you prefer a video tutorial, please check the video below from my YouTube channel:

The libraries

In order to setup the web server, we will need two libraries. The first one is the ESPAsyncWebServer, which we will use in our code.

This library allows setting an asynchronous HTTP (and Websocket) server, meaning that it can handle more than one connection at the same time [1].

Furthermore, as we will see in the code, once we set the server callback functions, we don’t need to periodically call any  client handling function on the main loop, like we had to do on the ESP8266 HTTP web server original implementation.

The second library needed is the AsyncTCP, which is a dependency for the previous one. Thus, we will not directly interact with it in our code.

This library is an asynchronous TCP library for the ESP32 and it is the base for the ESPAsyncWebServer library implementation [2]. Naturally, this is a lower level library which is more complex to use.

At the time of writing the libraries were not available on the Arduino IDE libraries manager, so we have to download them from the GitHub pages and place them on our Arduino libraries folder.

To download both of the libraries, simply click the “Clone or download” button on the top of the GitHub page, as highlighted in figure 1.

ESP32 Async Arduino HTTP webserver.png

Figure 1 – Downloading the libraries code from GitHub.

Then, select the “Download ZIP” option and the file should be downloaded to your computer. Just open the .zip file and extract the folder to your Arduino libraries folder.

Usually, the libraries folder for the Arduino installation is located on the C:\Users\UserName\Documents\Arduino\libraries folder.

Note that the extracted folder has a -master at the end of its name. Just delete this appended -master and keep the remaining name.

After that, the libraries should be available for use on the Arduino environment. This procedure applies to installing both libraries.

The code

For this example we will need to include two libraries. First of all, we will need to include the WiFi.h library, which is needed for connecting the ESP32 to a Wireless network.

Finally, we will include the previously installed asynchronous HTTP web server library, namely the ESPAsyncWebServer.h.

#include "WiFi.h"
#include "ESPAsyncWebServer.h"

After these includes, we will declare two global variables to hold our WiFi network credentials, so we can later use them to perform the connection.

const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPassword";

To finalize, we will declare a variable of class AsyncWebServer, which we will use to set up our asynchronous ESP32 HTTP server.

As input of the constructor, we will pass the port where the server will be listening. We will use port 80, which is the default HTTP port.

AsyncWebServer server(80);

Moving on to the setup function, we will start by opening a serial connection. Then, we will connect the ESP32 to the WiFi network using the previously declared credentials. If you need a detailed explanation on how to connect the ESP32 to a WiFi network, please refer to this previous article.


WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
    Serial.println("Connecting to WiFi..");


Note that, after the connection finishes, we are printing the local IP assigned to the ESP32, so we can later use it to make a request to our server.

Now we are going to configure the route where server will be listening for incoming HTTP requests and a function that will be executed when a request is received on that route.

We specify this by calling the on method on the server object. As first input, this method receives a string with the path where it will be listening. We are going to set it to listen for requests on the “/hello” route.

As second parameter, it receives an enum of type WebRequestMethod (defined here), which allows to specify which type of HTTP request is allowed on that route. We will specify that we only want to receive HTTP GET requests, and thus we use the value HTTP_GET.

As third argument, it receives a function to which the signature is defined by the ArRequestHandlerFunction type, which can be seen here.

So, this handling function we will specify has to return void and receives as parameter a pointer to an object of type AsyncWebServerRequest. Each incoming client will be wrapped in an object of this class and both live together until disconnection [3].

In order to keep the syntax compact, we will declare this handling function as a C++ lambda function. Thus, we can specify a locally declared unnamed function. For servers with many routes, this is much cleaner and compact than having to declare a named function for each route. You can read more about lambdas here.

We will use the following lambda syntax:


In our case, we will not use any captures, so we simply use empty square brackets []. For the params, we will need to respect the signature of the previously mentioned definition of the handling function, which is specified by the ArRequestHandlerFunction type. Thus, our lambda will receive a parameter which is a pointer to an object of type AsyncWebServerRequest.

server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
// Lambda body implementation

For our handling function implementation, we want to return to the client a simple “hello world” message. As said before, each client is associated with a AsyncWebServerRequest object, which has a method called send that allows us to specify the HTTP response to be returned.

This method receives as first input the HTTP response code, which will be 200 in our case. This is the HTTP response code for “OK”.

As second input, the send method receives the answer content-type of the response. We will use the value “text/plain“, since we simply want to return a “hello world” message.

Finally, as third argument, we will pass the actual content, which will be our “hello world” message.

Note that since we are working with a pointer to an object rather than the object itself we will need to use the arrow operator to call the send method on the AsyncWebServerRequest object.

server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "Hello World");

To finalize the setup function, we will need to call the begin method on our server object. This method call will start the server.


Since our server is asynchronous, we will not need to call any client handling function on the main loop, as stated before. So, the route handling function we just defined will be asynchronously called and executed upon receiving requests from clients. The final code can be seen below.

#include "WiFi.h"
#include "ESPAsyncWebServer.h"

const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";

AsyncWebServer server(80);

void setup(){

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("Connecting to WiFi..");


  server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "Hello World");


void loop(){}

Testing the code

To test the code, simply compile it and upload it to the ESP32 with your Arduino IDE. After the procedure finishes, open the serial monitor and copy the IP that gets printed once the ESP32 connects to the WiFi network.

Then, open a web browser and type the following on the address bar, changing #yourEspIp# by the IP you have just copied.


You should get an output similar to figure 2, which shows the “hello world” message we have defined on the code being printed.

ESP32 Arduino Async HTTP webserver hello world.png

Figure 2 – ESP32 HTTP web server hello world.





68 thoughts on “ESP32 Arduino: Asynchronous HTTP web server”

  1. Hi,

    I am a newbie in programming and I really like your tutorials, they are well explained and there are a lot of topics.

    I have a question for you. I tried to do the “ESP32 Arduino: Asynchronus HTTP web server” with an Sparkfun ESP32 Thing plus (WRL-15663) but everytime I run the code in the Arduino IDE, I opened the serial monitor and I am stuck in “Connecting to Wifi…”
    I really don’t know what’s wrong since I install all the libraries that are used in the project and the compilation seems to work.

    Thank you in advance for your help ! 🙂

  2. ESPAsyncWebServer.h:210:5: error: ‘AsyncClient’ does not name a type

    and other error in this library

  3. Hello, thanks a lot for this amazing tutorial.
    I just have a small question, what should I do if I want to have more than one requesting method? e.g: if I want to use the HTTP_GET and the HTTP_POST methods, what should I write in the second parameter in the server.on() function?

  4. I think your explanation is the best I have seen.. I appreciate that you assume nothing but give a proper explanation for what you are doing.

  5. Pasquale Castelli

    Great tutorial. If I want to make the two esp8266 cards work under a home router? Do I have to use a specific library?

Leave a Reply

%d bloggers like this: