Introduction: ESP8266 Building Blocks: Basic Web Server

About: IoT - Internet of Things. Iota - small thing. Thingamajig - An object whose name can't be recalled. Iotamajig - A little unnamed internet connected gizmo!

This instructable is part of my series on introducing people to the ESP8266-01 WiFi transceiver. The goal of this series is to act as a basic code repository for easy reuse, as well as to provide some foundational building blocks for people new to the ESP. The "building blocks" series will contain just the basic code needed to complete the object of the instructable, with a (hopefully) thorough explanation of what's going on and why.

In this building block, we are going to leverage our ESP as a web server. We're not going to do anything fancy with it, but just give you the basics on how to start the server, how to pass HTML, and a basic way to pass parameters.

Step 1: The Code

The following code block is missing the part where you connect to the internet. The attached .ino contains the code to do that, or if you haven't explored that yet, check out this Instructable. I've removed it from this snippet to focus on the important parts of being a web server.

PLEASE NOTE: I had to add spaces to the opening and closing <html> tags to get them to display properly here. Remove those spaces before using the code.

#include <ESP8266WebServer.h>

ESP8266WebServer server(80);

String htmlServe() {
  String htmStr;
  htmStr += "<h t m l>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0,\">\n";

  htmStr += "<body>\n<center>\n<h1>Server has been running for \n";

  htmStr += millis()/1000;

  htmStr += " seconds</h1>\n";
  htmStr += "<br><br><br><a href=\"/\"><button>Refresh</button></a>";
  htmStr += "</center>\n</body>\n</h t m l>\n";

  return htmStr;

void setup() {


   server.on("/", [](){
      server.send(200, "text/html", htmlServe());



void loop() {


Step 2: Upload Your Code

You'll need to add the WiFiCon() function from here (or something similar) and update the SSID and password for the router.

Open the serial monitor in the Arduino IDE. This is so once your code uploads, we can see the messages coming over serial from the ESP.

Use a setup like the one laid out here to upload your code. Once the code is done uploading, you should immediately start to see some messages in the serial monitor. If you don't, power down the ESP, turn the switch off of flash mode, and repower the ESP.

After the code is uploaded, a simple wiring like the one at the top of this Instructable is all you need to actually run the ESP.

Step 3: Get the IP Address

Once the code has uploaded, the ESP is going to try connecting to your router. If it's successful, it will display the IP address of the ESP in the serial monitor.

Take that IP and put it in the address bar of your browser, and let's see what we get.

Step 4: Explanation

Ok, so it's nothing fancy. A simple page that tells you how long the server has been up, and a refresh button.

But with the code that builds this, you can customize it to read data from GPIOs, or add other buttons or links to get input from the end user on the web page.

The htmlServe() function is building the HTML string that will be sent back to the client. If you have some HTML skills, you can make it as fancy as you want. The ESP projects I typically build will be accessed from my phone's web browser. This line:

<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0,\">

Makes it show nicely on the smaller scale of a phone.

As to the code that makes it a server, there are just 5 important blocks.

The include:
#include <ESP8266WebServer.h>
The port setting:
ESP8266WebServer server(80);

80 is the typical port for HTTP. If you change this, you would have to specify the new number when calling the devices address.

The response information:
   server.on("/", [](){
      server.send(200, "text/html", htmlServe());

This is what we will send to the client when a request is received. In this case, the "/" specifies root. We could have said: server.on("/newpage" , which would be called from the browser's address bar like:

(assuming that was your IP for the device).

You can have multiple blocks like this, each specifying different pages to handle different actions to take.

Starting the server:
Handling the client:

This just sits in the loop section waiting for a client to call in.

Step 5: Simple Parameters

As you may have guessed by now, a simple way for the user to pass us a command, is to give them different addresses to hit with the server.on("/" code.

Let's say instead of one button, we had two. And the target of one was "/on", and the target of the second was "/off".

We could then have three sections of code to handle these pages:

   server.on("/", [](){
      server.send(200, "text/html", htmlServe());

   server.on("/on", [](){
      server.send(200, "text/html", htmlOn());

   server.on("/off", [](){
      server.send(200, "text/html", htmlOff());

Notice for on and off, I have it call different functions than the original htmlServe(). You could have these extra functions serve back the same exact text as htmlServe(), but with additional code to take specific action, like maybe triggering a relay attached to a GPIO pin. Have one function to turn it on, the other to turn it off.

This of course could be handled in one function, and just pass a parameter to take action on, but hopefully this basic example has helped you understand how to serve web pages from your ESP as well as retrieve feedback from the end user.

Thanks for reading!