This tutorial shows how to control the ESP32 or ESP8266 outputs using a web server and a physical button simultaneously. The output state is updated on the web page whether it is changed via physical button or web server.

Let’s take a quick look at how the project works.

ESP32 ESP8266 NodeMCU Web Server With Physical Button Project Overview

In summary, this project allows you to control the same output using a web server and a push button simultaneously. Whenever the output state changes, the web server is updated.

Schematic Diagram

Before proceeding, you need to assemble a circuit with an LED and a pushbutton. We’ll connect the LED to GPIO 2 and the pushbutton to GPIO 4.

Parts Required

You can use the preceding links or go directly to to find all the parts for your projects at the best price!

ESP8266 NodeMCU Schematic

Installing Libraries – Async Web Server

To build the web server you need to install the following libraries:

These libraries aren’t available to install through the Arduino Library Manager, so you need to copy the library files to the Arduino Installation Libraries folder. Alternatively, in your Arduino IDE, you can go to Sketch Include Library > Add .zip Library and select the libraries you’ve just downloaded.

ESP Web Server Code

Copy the following code to your Arduino IDE.

You just need to enter your network credentials (SSID and password) and the web server will work straight away. The code is compatible with both the ESP32 and ESP8266 boards and controls GPIO 2 – you can change the code to control any other GPIO.

How the Code Works

We’ve already explained in great details how web servers like this work in previous tutorials (DHT Temperature Web Server), so we’ll just take a look at the relevant parts for this project.

Network Credentials

As said previously, you need to insert your network credentials in the following lines:

Button State and Output State

The ledState variable holds the LED output state. For default, when the web server starts, it is LOW.

The buttonState and lastButtonState are used to detect whether the pushbutton was pressed or not.

Button (web server)

We didn’t include the HTML to create the button on the the index_html variable. That’s because we want to be able to change it depending on the current LED state that can also be changed with the pushbutton.

So, we’ve create a placeholder for the button %BUTTONPLACEHOLDER% that will be replaced with HTML text to create the button later on the code (this is done in the processor() function).


The processor() function replaces any placeholders on the HTML text with actual values. First, it checks whether the HTML texts contains any placeholders %BUTTONPLACEHOLDER%.

Then, call the outputState() function that returns the current output state. We save it in the outputStateValue variable.

After that, use that value to create the HTML text to display the button with the right state:

HTTP GET Request to Change Output State (JavaScript)

When you press the button, the toggleCheckbox() function is called. This function will make a request on different URLs to turn the LED on or off.

To turn on the LED, it makes a request on the /update?state=1 URL:

Otherwise, it makes a request on the /update?state=0 URL.

HTTP GET Request to Update State (JavaScript)

To keep the output state updated on the web server, we call the following function that makes a new request on the /state URL every second.

Handle Requests

Then, we need to handle what happens when the ESP32 or ESP8266 receives requests on those URLs.

When a request is received on the root / URL, we send the HTML page as well as the processor.

The following lines check whether you received a request on the /update?state=1 or /update?state=0 URL and changes the ledState accordingly.

When a request is received on the /state URL, we send the current output state:


In the loop(), we debounce the pushbutton and turn the LED on or off depending on the value of the ledState variable.

Upload the code to your ESP32 or ESP8266 board.

Then, open the Serial Monitor at a baud rate of 115200. Press the on-board EN/RST button to get is IP address.

Open a browser on your local network, and type the ESP IP address. You should have access to the web server as shown below.

You can toggle the button on the web server to turn the LED on.

You can also control the same LED with the physical pushbutton. Its state will always be updated automatically on the web server.

Watch the next quick video for a live demonstration:

Wrapping Up

In this tutorial you’ve learned how to control ESP32/ESP8266 outputs with a web server and a physical button at the same time. The output state is always updated whether it is changed via web server or with the physical button.

Thanks for reading.

This content was originally published here.