ESP8266: Setting a simple HTTP web server

The objective of this post is to explain how to set a HTTP web server on a ESP8266 and how to make some requests to it using a web browser.


The objective of this post is to explain how to set an HTTP web server on a ESP8266 and how to make some requests to it using a web browser.

We assume the use of the ESP8266 libraries for the Arduino IDE. You can check here how to configure the Arduino IDE to support the ESP8266.

The tests were performed using a NodeMCU board, a very cheap and easy to use ESP8266 board. The board can be bought at eBay here.

The code

First of all, we include the ESP8266WiFi library, which will make available the functionality needed for the ESP8266 to connect to a WiFi network. You can check a more detailed explanation on how to connect to a WiFi network from the ESP8266 on this previous post.

Then, we include the ESP8266WebServer library, which will make available the class ESP8266WebServer that we will use during this post. Naturally, this class has some methods available that will help us setting up a server and handle incoming HTTP requests without needing to worry about low level implementation details. You can check the implementation of the library here.

#include "ESP8266WiFi.h"
#include "ESP8266WebServer.h"

Next, we declare a global object variable from the previously mentioned class, so we will be able to access it in our functions.

As argument for the constructor of this class, we will pass the port where the server will be listening to. Since 80 is the default port for HTTP [1], we will use this value, so we will not need to specify it in the URL when accessing to our ESP8266 server using a browser.

ESP8266WebServer server(80);

Since we need to pre-configure our HTTP server before actually running it, we will do most of the coding in the setup function.

First of all, we open a serial connection for debugging.


Then, we will need to connect to the WiFi network, as shown with the code below. If you need a detailed explanation on how to connect to a WiFi network with the ESP8266, check here.

WiFi.begin("Network name", "Password");

while (WiFi.status() != WL_CONNECTED) {   //Wait for connection

   Serial.println("Waiting to connect...");


Since we are not going to do any domain name resolution, we need to know the IP where the ESP8266 is listening to incoming requests, which will be the local IP assigned in the WiFi network.

To get this value, we just call the localIP method on the WiFi global variable and then print it to the serial port, so we will know which URL to call on our web browser.


Then, we will start to specify which code to execute when an HTTP request is performed to each path. To do so, we call the on method on our previously declared server global object.

The more elegant method consists on defining a handling function somewhere in our code and passing it to the on function, alongside the URL that will trigger the execution of that function. This is exemplified below.

server.on("/", handleRootPath);

So, the code mentioned bellow indicates that when an HTTP request is received on the root (“/”) path, it will trigger the execution of the handleRootPath function. Note that we don’t specify the IP or port where the ESP8266 is listening, but only the path of the URL from that point onward.

For the sake of simplicity, let’s assume that our handleRootPath only answers with the text “Hello World” to the incoming HTTP request. So, to define an answer to a request, we call the send method on our server object.

Although the method can be called with a different set of arguments, its simplest form consists on receiving the HTTP response code, the content type and the content. Check the code below.

void handleRootPath() {

   server.send(200, "text/plain", "Hello world");


In this case, we are sending the code 200, which corresponds to the “OK” response [2]. Then, we are specifying the content type as “text/plain“, since we are only responding with a simple “Hello world”, and finally the actual response text.

Naturally, this function needs to be declared outside the setup function.

We can also specify the handling function when calling the on method. In this case, we don’t need to declare a separate function and we can do everything in the setup function, as demonstrated bellow.

server.on("/other", [](){

   server.send(200, "text/plain", "Other URL");


In this case, if we receive an HTTP request in the path “/other”, we will answer with a “Other URL” sentence.

Now, to start our server, we call the begin method on the server object. This is the last line of code we need to include in our setup function.


Finally, to handle the actual incoming of HTTP requests, we need to call the handleClient method on the server object, on the main loop function.

void loop() {



The complete code can be seen bellow.

#include "ESP8266WiFi.h"
#include "ESP8266WebServer.h"

ESP8266WebServer server(80);

void setup() {

  WiFi.begin("Network name", "Password");  //Connect to the WiFi network

  while (WiFi.status() != WL_CONNECTED) {  //Wait for connection

    Serial.println("Waiting to connect…");


  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //Print the local IP

  server.on("/other", []() {   //Define the handling function for the path

    server.send(200, "text / plain", "Other URL");


  server.on("/", handleRootPath);    //Associate the handler function to the path
  server.begin();                    //Start the server
  Serial.println("Server listening");


void loop() {

  server.handleClient();         //Handling of incoming requests


void handleRootPath() {            //Handler for the rooth path

  server.send(200, "text/plain", "Hello world");


Testing the code

To test the code we just need to open our browser and make an HTTP request to the IP of the ESP8266, on a path we defined early. The format is shown bellow:


Since, as stated before, we are listening on the 80 port, the browser will assume it by default, so we don’t need to specify it:


So, we substitute the serverIP by the IP printed on the serial console, and we make a request as shown in figure 1.


Figure 1 – HTTP request via browser on the root path (Google Chrome).

In this case, only the IP is shown because the browser removed the “/” from the root path. Also, the http:// was removed by the browser. Although some browsers perform the request when we only specify the IP, others assume that we want to search something in a search engine. So, the safest way is to always specify the http:// before the IP.

The example from figure 2 shows a request on the path “/other” that we also defined.


Figure 2 – HTTP request via browser on the “/other” path (Firefox).

Finally, note that if we specify a path not defined, the ESP will return a message indicating that the resource was not found, as we can see in figure 3, where we sent an HTTP request to the path “/notdefined”.


Figure 3 – HTTP request via browser on a path not defined.

Important: The IP that will be printed by the ESP8266 will be its private IP on the network. It won’t be possible for a client outside the network to contact it on that IP (and thus, the URL will not work). In order for a client to be able to contact the ESP8266 from outside its network, it would need to use the external IP of the network and the router would need to be configured to forward the requests on its public IP for that port to the private IP of the ESP8266. Since port forwarding depends on the router used, explaining how to do it is outside of the scope of this post.

Related posts




Technical details

ESP8266 libraries: v2.3.0


39 Replies to “ESP8266: Setting a simple HTTP web server”

  1. Have you considered the Watchdog on the Esp8266? I have several of these things but they always seem to halt. (Daily) I wonder if you’ve figured out how to employ the watchdog so they reboot themselves. Thanks for the content!

    Liked by 2 people

    1. Hi again! I’ve been playing a little bit with the watchdogs of the ESP8266 and shared the results here:

      As it seems, the ESP has 2 watchdogs: a software one and a hardware one. The ESP libraries for the Arduino IDE give us some control on the software watchdog. For the hardware watchdog, I haven’t found any way to control it.

      Nevertheless, both the hardware and software watchdogs are enabled by default, so it’s strange that they don’t reset your devices when they halt. Do you have any error log that you can share in the github page of the libraries? It’s probably the best way to try to find the root cause and solve it.

      Liked by 1 person

      1. Thanks for looking! That’s funny, it definitely locks up on me for hours, until I reset the device. I’ll see about posting it somewhere. The device I built simply lets my kids see their BTC balance, on an oled, all running on a esp8266 feather. So it’s just making http calls… and it locks up daily.

        Liked by 2 people

        1. You’re welcome 🙂 It sounds a very cool project!

          Well, I remember that once I had some problems while doing socket communication with a Java program. My program seemed to hang but in reality the sockets were being left half opened, so I wasn’t able to do any more connections after a certain point. Is that a possible case for your program or is it really crashing/locking at a deeper level?

          I also have once experienced problems when doing many HTTP requests in a row, without a delay between them. It also caused some malfunctions.

          Other things that you can try to solve the problem:
          – Making sure you have the latest version of the ESP libraries.
          – Changing the type of ESP board if you only tested in the same model. The problem you are experiencing may be a hardware issue. You have some different models at eBay, from the NodeMCU to the ESP01.

          Hope it helps, if you are able to solve the issue please share with us.

          Liked by 2 people

      1. You can check here how to configure the Arduino IDE to support the ESP8266:

        Think as Arduino not only as an hardware platform but also as a software platform. The Arduino IDE already supports multiple Arduino boards, which are implemented with different microcontrollers.

        So, the question is being able to translate the Arduino language to the language that a specific microcontroller knows, being it integrated in an Arduino board or not. This project achieves that for the ESP8266:


  2. I encountered a strange phenomenon. When I started this described program; my ESP8266 first connected to the IP-address: 192-168.4.2 which is NOT the default range of my WiFiNetwork ( And when I reset this chip then it founds a good adres:
    And I found in my Wifi Networklist that this chip pronounce itsself as “ESP_863074”. And in LookatLAN (a Windowsprogram thats pinning the arrea) I found this chip on this 2 IP-adresses. Also it is accessible on this both addresses.

    Liked by 1 person

    1. Hi! That’s really a strange behavior, never happened to me yet, or at least I haven’t noticed. Does it happen to any other devices on your network or just the ESP8266?

      I think it may be related to the router, since its the router that assigns the IP to the device on the network. But is just a guess.

      Let us know if you discover the cause 🙂


  3. To associate an IP to a domain, download the library DNSServer.h. Then,

    dnsServer.start(DNS_PORT, “”, my_IP);

    See more,
    sketches/examples —- DNSServer —– DNSServer (sketch)

    Liked by 1 person

  4. Hello, thanks for your excelent post.

    I have a dubt… you say
    “Naturally, this function needs to be declared outside the setup function.”

    ¿Why? i dont understand why must be declared outside the setuo function.

    Liked by 1 person

    1. Hi! Thanks for the feedback 🙂

      You can’t declare a function inside another function. If you do this:

      void setup() {

      void newfunc(){

      You will get an error like “a function definition is not allowed here”.

      And that’s why I mentioned that.

      Best regards,
      Nuno Santos


    1. Hi! In this post we are using the ESP8266 standalone, meaning that there is no Arduino board to connect to.

      We are only using the Arduino environment for developing the program that will run on the ESP8266.

      So, in short, you can think of the ESP8266 as an Arduino with Wifi.

      Hope this clarifies.

      Best regards,
      Nuno Santos


      1. Currently I don’t have USB to serial converter. So do you know how can I configure my ESP8266-01 with arduino uno in my hands. I have checked loads of tutorials but I am not getting any response on sending ESP AT commands.

        Liked by 1 person

        1. Hi!

          Unfortunately I have never used the arduino uno to program the ESP8266.

          I’ve used an Arduino in the past to send some AT commands to the ESP8266, but it was a couple of years back and I suspect that things have changed since that time.

          But basically I was getting very unreliable results and thus I’ve moved to directly programming the ESP8266.

          Some reasons that may be causing the lack of response from the module that you are experiencing:
          – The ESP8266 you are using was not flashed with the AT commands firmware
          – You are using an incorrect baud rate for the serial connection

          Besides that, the ESP866 works at 3.3 V and the Arduino uno at 5V (at least the older versions). Are you using a voltage level converter between 3.3 and 5 v? if not, you may have fried your ESP8266 pins.

          My recommendation is that you get one of those easy to program boards, such as the esp8266 NodeMCU, which allow you to program the ESP8266 without the need for any external hardware, just a usb cable is enough.

          Hope this helps.

          Best regards,
          Nuno Santos


  5. hello, thanks for awesome tutorial

    I have very strange problem in the code, when modem is turned off and then turned on, I cannot send request to esp anymore it says site cant be reached but I am sure that ESP reconnects to modem because in modem Dashboard I can see connected devices.

    Is the problem reason handleCLient might be still waiting for clients for old server ?
    I am calling server.begin again when reconnects can it be reason, and what should i do???

    Please help

    Liked by 1 person

    1. Hi! Thanks for the feedback 🙂

      At the time I played with the HTTP server, I never tested it for those disconnect / reconnect conditions, so I’m not sure what may be causing the problem.

      Maybe it is something related with binding the server with the network interface when the device reconnects.

      Nonetheless, my recommendation is that you share the issue in the GitHub page of the Arduino core for the ESP8266, since somebody may already have found the same issue and found a solution:

      Just as an additional note, there’s a new async HTTP server library for the ESP32 / ESP8266 that may be more reliable than the original one. I haven’t tested it yet for the ESP8266, but it works pretty well for the ESP32:

      Best regards,
      Nuno Santos


  6. I’m facing the same issue as mamacker ie my 2 tested esp-01 halt daily and no more respond to the requests till i reset the device manually. Don’t know if it’s a software or hardware issue.
    Note : a lot of people over internet are facing the same issue of web server halting and no more responding after some hours without any solution . Strange…

    Liked by 1 person

    1. Hi! Unfortunately I haven’t yet came across any solution, but it is indeed a strange problem, specially in a feature that should be used a lot, such as setting a HTTP server.

      Nonetheless, there’s a new implementation of a HTTP server for the ESP8266 / ESP32 that you may give a try to check if works more reliably.

      The implementation of this solution is asynchronous and thus should be more flexible, at least in terms of software development.

      I haven’t had the change to test it on the ESP8266 yet, but it works pretty well on the ESP32.

      GitHub Page:

      Let me know if this helps.

      Best regards,
      Nuno Santos


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s