Make a Web Server with ESP8266

July 05, 2017 by Mohammad Amin Karami

In this project, we first examine how to install an ESP8266 add-on on Arduino IDE and then we make a configurable web server with an ESP8266 and show the simplicity of this process.

In this project, we first examine how to install an ESP8266 add-on in the Arduino IDE and then make a configurable web server with an ESP8266.

The ESP8266 is popular largely because it has an excellent performance-to-cost ratio. It can also bring the internet via Wi-Fi to a microprocessor.

Its main considerable drawback is its power consumption. The ESP8266 is not a very power efficient chip because it is designed to obey the IEEE 802.1 protocol (which we know as Wi-Fi) which is available in most homes and businesses. This protocol agenda guarantees good speed and robustness for creating wireless local networks. Higher speed leads to a higher power consumption which makes the ESP8266 inefficient for low-power designs.

However, an ESP8266 is very beneficial in cases where power consumption is not important such as devices which are constantly fed power and do not require a battery. An ESP8266 can connect to any Wi-Fi network and send or receive data through various protocols such as TCP and UDP. In addition, it can construct a Wi-Fi hotspot and manage other devices, as well.


Circuit Design Considerations

An ESP8266 may need a 250mA current for data transferring. Therefore, we may need at least 500mA for powering the ESP8266 if we want to have a good margin. Powering an ESP8266 with USB cables that get their power from a computer can lead to instability.

In this project, we use a 5V power supply that guarantees a 1A current and an LM1086-3.3V as a regulator for powering the ESP8266. In Figure 1, the pin configuration for using an ESP8266 in both bootloader and usage mode is shown.


Figure 1. Using an ESP8266 in bootloader and usage mode. Image source:

Arduino Add-On

Installing the ESP8266 add-on is described in many articles on the internet but, for clarity, we will cover installation briefly here. To install the ESP8266 add-on, we need to update the board manager in the Arduino IDE. An additional board manager URL can be added from File->Preferences->Additional Boards Manager URLs. In the URL section, the below URL should be entered like Figure 2.


Figure 2. Additional boards manager URLs


By updating the URLs, the ESP8266 add-on can be accessed by navigating to Tools->Boards->Boards Manager. The ESP8266 board is available and should be installed. After the installation, in the boards section, ESP8266 modules will be available. Different kinds of modules are selectable and, for the purposes of this project (because we built the board we are using), we will use a generic ESP8266 module.

Uploading a Sketch to the ESP8266

To program an ESP8266, we use the UART bootloader the ESP8266 already contains. In this project, I made a simple development board fo ESP8266 with the schematic like Figure 3 and the following part list:

1. ESP8266-12(E or F doesn’t matter in footprint and the only difference is memory)
2. 3.3K resistor x 2
3. 470R resistor for the power demonstrator LED
4. One LED that determines whether the board is powered or not
5. AMS1117-3.3: Voltage regulator
6. 10uF-25v electrolyte capacitor
7. 22uF-25v electrolyte capacitor
8. 100nF capacitor
9. One 3 pin connector for  serial communication
10. One 2 pin connector for entering into the bootloader

For entering the boot mode, GPIO0 should be grounded for the startup of the ESP8266. Then by setting the appropriate COM port in the Arduino IDE, the sketch can be uploaded by hitting the upload button. After programming, GPIO0 should be floating because ESP8266 should start in normal mode and run the program.


Figure 3. ESP8266-12E development board schematic

Connecting to an Access Point

The ESP8266 has a built-in EEPROM that can be used for applications such as storing data in order to build a secure login page. Using EEPROM is much like other Arduino boards with some small differences.

For one thing, you need to call EEPROM.begin(size) before you start reading or writing. Size is the number of bytes you want to use, anywhere between 4 and 4096 bytes. Note that EEPROM.write() does not write to flash immediately. You must call EEPROM.commit() anytime you wish to save changes to flash.

In this project, we want to make a configurable web server that can be placed in every network (i.e., in a new network that doesn’t have the SSID and the password for connection to the access point) to connect with the previous settings. When it fails to connect, the ESP8266 will go to the access point mode and wait to receive the configuration settings (SSID and password).

In the beginning, we get 512 bytes of the EEPROM and check whether a username or password is available or not. We can also choose a specific IP address for our device and set it manually, which needs to be stored in the EEPROM. Setting the device IP manually is useful when we need to create a database of our devices to know their location and definition.

In the following snippet of the complete code, we reserve 512 bytes from the EEPROM and then, after gathering the information, we try to connect to the access point. In the complete code, the code will bypass the connecting stage if the EEPROM is empty.

IPAddress ipad(192, 168, 1, eip.toInt());
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
WiFi.begin(esid.c_str(), epass.c_str());
WiFi.config(ipad, gateway, subnet);

The above code tries to connect to the network with a specific IP address that is stored in the EEPROM. One thing to remember when using a specific IP address is that we need to know the gateway IP address and also the network subnet mask. On the other hand, the mentioned items are not necessary for automatic IP addressing, which requires a DHCP server.

Checking the Wi-Fi status is possible using WiFi.status() function. According to the Arduino website, this function returns the following:

  • WL_CONNECTED: assigned when connected to a Wi-Fi network
  • WL_NO_SHIELD: assigned when no Wi-Fi shield is present
  • WL_IDLE_STATUS: a temporary status assigned when WiFi.begin() is called and remains active until the number of attempts expires (resulting in WL_CONNECT_FAILED) or a connection is established (resulting in WL_CONNECTED)
  • WL_NO_SSID_AVAIL: assigned when no SSID are available
  • WL_SCAN_COMPLETED: assigned when the scan networks is completed
  • WL_CONNECT_FAILED: assigned when the connection fails for all the attempts
  • WL_CONNECTION_LOST: assigned when the connection is lost
  • WL_DISCONNECTED: assigned when disconnected from a network

By using the WiFi.status() function we can check the connectivity status and, if it’s not there, the ESP8266 should turn to an access point.

Turning to the access point configuration can be done with WiFi.mode(WIFI_AP), which will require a username and password. Setting a username and password can be done with the WiFi.softAP function. Describing every Wi-Fi function would make this article incredibly long and is out of the scope of this project. However, an eager person can find very comprehensive documentation about the Wi-Fi functions and other libraries for the ESP6288 on GitHub and the Arduino website.

In this project, we want to connect our device to an existing network. At first, when our device doesn’t have the SSID and password for connecting to the network, it will go into access point mode and then we can configure it. After the configuration, the device can get connected to the desired network. On the other hand, someone may want to use the ESP8266 only in the access point mode. In this case, we need to connect to the device whenever we want to transfer data.

Therefore, in the access point mode, the ESP8266 will wait for a new set of configurations. Scanning available wireless access points in the area can be done with WiFi.scanNetworks that returns integer numbers, determining the existing access points. After gathering the number of available networks, the following functions can get you all the information you need:

  • WiFi.SSID: gets the SSID of the current network
  • WiFi.RSSI: gets the signal strength of the connection to the router
  • WiFi.encryptionType: gets the encryption type of the current network

In Figure 4, the outputs of WiFi.scanNetworks is shown. The data is captured via RS232 communication and a program called TeraTerm.


Figure 4. Scanned networks


Creating a web server on an ESP8266 is easy using pre-built libraries. In addition, creating a simple multicast Domain Name System (mDNS) which links a name to our server IP in the network is possible using the ESP8266mDNS library. The mDNS resolves host names to IP addresses in small networks that lack a local name server. It uses the same programming interfaces, packet formats, and operating semantics as unicast DNS.

Next, “mdns.begin(‘esp8266’)” causes an mDNS server to be defined with the name of ESP8266. If everything works fine, the mdns.begin function returns true and we can start the server by server.begin().


Reading a GET Request

We can update mDNS queries by mdns.update() and then read requests as a client. The below code first updates mDNS queries and then, if a packet is available, reads it.

  WiFiClient client = server.available();
  if (!client) {
  String req = client.readStringUntil('\r');
  // Wait for data from client to become available
  if(client.connected() && !client.available()){

In the above code, the ESP8266 checks whether any client is available or not. If a client is available, it will read its data until it receives ‘\r’ which means the end of the packet. From that point on, our web server can receive GET requests but cannot interpret them or send an answer.

Sending the answer of the client can be done by using the client.print() function. For the client, in order to see it as a web content (i.e., see the answer in a browser such as Firefox), the answer should be in HTML format. In this way, we can create a graphical HTML web server with our ESP8266.

In the above code, we read the client GET request and stored it in the ‘req’ variable. The ‘req’ variable now has the GET data and we can interpret it simply. According to the client GET request, we should create a String and by using the client.print() function, the client answer can be generated. The below snippet generates a simple HTML page for the answer to the client.

s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n\r\n


"; s += "\r\n\r\n"; client.print(s);

In the snippet, a ‘200’ command has been sent to the client.


In this project, the ESP8266 libraries for creating a simple web server were examined. Then, a configurable web server that takes SSID and the password of the desired wireless network was created. Finally, after connecting to the local network, GET requests were transferred between the device and a client.

Give this project a try for yourself! Get the BOM.

  • J
    jimallison57 December 15, 2017

    The YouTube video no longer matches the way the sketch runs.  Has the sketch been modified?  I can’t seem to get it to work with my network.  Router Gateway:   Router Subnet:  Can you re-test the sketch and upload a new version if needed?

    Like. Reply
    • M
      monosys January 13, 2018
      Router Gateway IP should be the IP from which you access your routers admin page. And no router will give you class A IP address(as per my knowledge) all router are configured for class C IP Address
      Like. Reply
  • J
    jimallison57 January 17, 2018

    Okay.  Thanks for the response on the router question.  Can you review the code again?  The YouTube video doesn’t match the way the code runs when I download it.  I just want to make sure it’s not something on my end and that the code works the way it is supposed to.  Other than that, I think this code really satisfies a need that many of us can use in our projects.  Thanks for any help you can provide!

    Like. Reply