Zbotic Logo Zbotic Logo
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

  • Shop
  • About Us
  • Contact Us
  • Reseller
  • Blogs
020 69134444
1800 209 0998
[email protected]
Help Desk
Facebook Twitter Instagram Linkedin YouTube
Zbotic Logo Zbotic Logo
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

All departments
  • 3D Print Service
  • 3D Printer
  • Batteries & Chargers
  • Development Boards
  • Drone Parts
  • EBike parts
  • Sensor Modules
  • Electronic Components
  • Electronic Modules
  • IoT and Wireless
  • Mechanical Parts and Workbench Tools
  • Motors & Drivers & Pumps & Actuators
  • DIY and Robot Kits
  • Show more
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
Return to previous page
Home IoT & Smart Home

ESP32 HTTP Web Server: Control GPIO from Browser Page

ESP32 HTTP Web Server: Control GPIO from Browser Page

March 11, 2026 /Posted byJayesh Jain / 0

One of the most satisfying beginner-to-intermediate ESP32 projects is building an ESP32 HTTP web server GPIO control browser application — turning on an LED, relay, or motor by clicking a button on a webpage hosted directly on the chip. No cloud service, no app, no internet required. Your ESP32 serves a webpage over your local Wi-Fi, and any device on the same network — phone, laptop, tablet — can control it just by opening a browser. In this comprehensive guide, we’ll build a fully-featured GPIO control web server from scratch, progressively adding features from a simple LED toggle to a multi-channel relay controller with real-time feedback.

Table of Contents

  1. How ESP32 HTTP Web Server Works
  2. Project 1: Simple LED Toggle Server
  3. Project 2: ESPAsyncWebServer for Better Performance
  4. Project 3: Multi-GPIO Control with Status Display
  5. Project 4: Sensor Dashboard with Auto-Refresh
  6. Adding Basic Security: Password Protection
  7. mDNS: Access Your ESP32 by Name
  8. Frequently Asked Questions

How ESP32 HTTP Web Server Works

The ESP32 HTTP web server GPIO control browser concept is simple: the ESP32 connects to your Wi-Fi router as a station (client), gets an IP address (e.g., 192.168.1.45), and runs an HTTP server on port 80. When you type that IP address into your browser, the browser sends an HTTP GET request to the ESP32. The ESP32’s web server handles the request, generates an HTML response, and sends it back — just like any web server, but running on a microcontroller.

GPIO control happens via URL paths. For example:

  • http://192.168.1.45/ — Serves the main control page
  • http://192.168.1.45/gpio/2/on — Turns GPIO 2 HIGH
  • http://192.168.1.45/gpio/2/off — Turns GPIO 2 LOW
  • http://192.168.1.45/status — Returns JSON with current pin states

This URL-based control makes it trivial to automate from scripts, integrate with home automation platforms like Home Assistant, or trigger from Telegram bot webhooks.

30Pin ESP32 Expansion Board

30Pin ESP32 Expansion Board with Type-C USB and Micro USB

This expansion board breaks out all ESP32 GPIO pins with labelled headers, making it easy to connect LEDs, relays, and sensors for your HTTP web server control project.

View on Zbotic

Project 1: Simple LED Toggle Server

Let’s start with the simplest possible implementation using the built-in WebServer library included with the ESP32 Arduino core:

#include <WiFi.h>
#include <WebServer.h>

const char* ssid = "YourWiFi";
const char* password = "YourPassword";

#define LED_PIN 2
WebServer server(80);
bool ledState = false;

const char* htmlPage = R"(
<!DOCTYPE html>
<html>
<head>
  <meta charset='UTF-8'>
  <meta name='viewport' content='width=device-width,initial-scale=1'>
  <title>ESP32 GPIO Control</title>
  <style>
    body { font-family: Arial, sans-serif; text-align: center; margin: 50px; }
    .btn { padding: 20px 40px; font-size: 20px; border: none; border-radius: 8px;
           cursor: pointer; margin: 10px; }
    .on  { background: #4CAF50; color: white; }
    .off { background: #f44336; color: white; }
  </style>
</head>
<body>
  <h1>ESP32 LED Control</h1>
  <p>LED is: <strong id='state'>...</strong></p>
  <button class='btn on'  onclick="fetch('/on') .then(()=>document.getElementById('state').innerText='ON')">Turn ON</button>
  <button class='btn off' onclick="fetch('/off').then(()=>document.getElementById('state').innerText='OFF')">Turn OFF</button>
  <script>
    fetch('/status').then(r=>r.json()).then(d=>document.getElementById('state').innerText=d.led?'ON':'OFF');
  </script>
</body>
</html>
)";

void handleRoot() {
  server.send(200, "text/html", htmlPage);
}

void handleOn() {
  ledState = true;
  digitalWrite(LED_PIN, HIGH);
  server.send(200, "text/plain", "LED ON");
}

void handleOff() {
  ledState = false;
  digitalWrite(LED_PIN, LOW);
  server.send(200, "text/plain", "LED OFF");
}

void handleStatus() {
  String json = "{"led":" + String(ledState ? "true" : "false") + "}";
  server.send(200, "application/json", json);
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  Serial.println("IP: " + WiFi.localIP().toString());
  
  server.on("/", handleRoot);
  server.on("/on", handleOn);
  server.on("/off", handleOff);
  server.on("/status", handleStatus);
  server.begin();
}

void loop() {
  server.handleClient();
}

Flash this to your ESP32, open the Serial Monitor to see the IP address, and type that IP into any browser on the same Wi-Fi network. You’ll see a clean web page with ON and OFF buttons that control the built-in LED in real time.

Project 2: ESPAsyncWebServer for Better Performance

The blocking WebServer library handles one request at a time in the main loop. For production-quality applications — especially when multiple users might access the device simultaneously, or when you’re running other time-sensitive tasks — use ESPAsyncWebServer:

Install from Arduino Library Manager: search for “ESP Async WebServer” by me-no-dev. Also install “AsyncTCP” as a dependency.

#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

AsyncWebServer server(80);

void setup() {
  WiFi.begin("SSID", "Password");
  while (WiFi.status() != WL_CONNECTED) delay(500);
  
  // URL parameter-based GPIO control
  // Usage: /gpio?pin=2&state=1
  server.on("/gpio", HTTP_GET, [](AsyncWebServerRequest* req) {
    if (req->hasParam("pin") && req->hasParam("state")) {
      int pin = req->getParam("pin")->value().toInt();
      int state = req->getParam("state")->value().toInt();
      // Whitelist allowed pins for security
      if (pin == 2 || pin == 4 || pin == 16 || pin == 17) {
        pinMode(pin, OUTPUT);
        digitalWrite(pin, state ? HIGH : LOW);
        req->send(200, "application/json",
          "{"pin":" + String(pin) + ","state":" + String(state) + "}");
      } else {
        req->send(403, "text/plain", "Pin not allowed");
      }
    } else {
      req->send(400, "text/plain", "Missing parameters");
    }
  });
  
  server.begin();
}

void loop() {
  // loop() is free for other tasks!
  // ESPAsyncWebServer runs on a separate task
}

The key advantage of ESPAsyncWebServer is that it runs entirely on FreeRTOS tasks in the background. Your loop() function is completely free for other work — reading sensors, controlling actuators, running state machines.

Ai Thinker ESP32 CAM Development Board

Ai Thinker ESP32 CAM Development Board WiFi+Bluetooth with AF2569 Camera Module

Extend your web server project with live camera streaming. Serve a live MJPEG stream alongside GPIO control from the same ESP32-CAM HTTP server.

View on Zbotic

Project 3: Multi-GPIO Control with Status Display

Here’s a more complete web interface for controlling multiple GPIO pins, styled to look professional on a mobile browser:

// Relay/GPIO definitions
struct GPIOPin {
  int pin;
  const char* name;
  bool state;
};

GPIOPin pins[] = {
  {2,  "Bedroom Light",  false},
  {4,  "Fan",            false},
  {16, "Water Pump",     false},
  {17, "Gate Lock",      false}
};
const int numPins = 4;

String buildDashboard() {
  String html = "<!DOCTYPE html><html><head><meta charset='UTF-8'>";
  html += "<meta name='viewport' content='width=device-width,initial-scale=1'>";
  html += "<title>Home Control</title><style>";
  html += "body{font-family:Arial,sans-serif;max-width:500px;margin:20px auto;padding:15px}";
  html += ".card{border:1px solid #ddd;border-radius:10px;padding:15px;margin:10px 0;";
  html += "display:flex;justify-content:space-between;align-items:center;box-shadow:0 2px 4px rgba(0,0,0,.1)}";
  html += ".switch{position:relative;width:60px;height:30px}";
  html += ".switch input{opacity:0;width:0;height:0}";
  html += ".slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;";
  html += "background:#ccc;border-radius:30px;transition:.4s}";
  html += ".slider:before{content:"";position:absolute;height:22px;width:22px;left:4px;";
  html += "bottom:4px;background:white;border-radius:50%;transition:.4s}";
  html += "input:checked+.slider{background:#ff6b00}";
  html += "input:checked+.slider:before{transform:translateX(30px)}</style></head><body>";
  html += "<h2 style='text-align:center;color:#ff6b00'>Home Control Panel</h2>";
  
  for (int i = 0; i < numPins; i++) {
    html += "<div class='card'><span>" + String(pins[i].name) + "</span>";
    html += "<label class='switch'><input type='checkbox' ";
    if (pins[i].state) html += "checked ";
    html += "onchange="fetch('/gpio?pin=" + String(pins[i].pin) + "&state='+(this.checked?1:0))">";
    html += "<span class='slider'></span></label></div>";
  }
  html += "</body></html>";
  return html;
}

Project 4: Sensor Dashboard with Auto-Refresh

Combine GPIO control with sensor reading for a full home monitoring dashboard. This example reads DHT11 temperature/humidity and displays it alongside GPIO controls:

// Add sensor data endpoint
server.on("/data", HTTP_GET, [](AsyncWebServerRequest* req) {
  float temp = dht.readTemperature();
  float hum = dht.readHumidity();
  String json = "{"temperature":" + String(temp, 1) +
                ","humidity":" + String(hum, 1) + "}";
  req->send(200, "application/json", json);
});

// In the HTML, add auto-refresh every 5 seconds:
// <script>
// setInterval(() => {
//   fetch('/data').then(r => r.json()).then(d => {
//     document.getElementById('temp').innerText = d.temperature + '°C';
//     document.getElementById('hum').innerText = d.humidity + '%';
//   });
// }, 5000);
// </script>
DHT11 Temperature And Humidity Sensor Module with LED

DHT11 Temperature And Humidity Sensor Module with LED

Add environmental monitoring to your ESP32 web server dashboard. Read temperature and humidity data and display it in real-time on the browser control page.

View on Zbotic

Adding Basic Security: Password Protection

An open ESP32 web server on your local network means anyone on your Wi-Fi can control your GPIO pins. Add HTTP Basic Authentication to protect it:

// ESPAsyncWebServer basic auth
server.on("/", HTTP_GET, [](AsyncWebServerRequest* req) {
  if (!req->authenticate("admin", "zbotic123")) {
    return req->requestAuthentication();
  }
  req->send(200, "text/html", buildDashboard());
});

// For API endpoints, check a token in the header or URL:
server.on("/gpio", HTTP_GET, [](AsyncWebServerRequest* req) {
  String token = req->header("X-API-Token");
  if (token != "my-secret-token-2026") {
    req->send(401, "text/plain", "Unauthorized");
    return;
  }
  // ... handle GPIO control
});

For devices exposed to the internet (via port forwarding or VPN), always use HTTPS. The ESP32 supports TLS with WiFiClientSecure, though memory constraints mean you should use elliptic curve certificates (smaller key sizes) for embedded use.

mDNS: Access Your ESP32 by Name

Instead of memorizing the IP address (which can change if your router reassigns it), set up mDNS so you can access your ESP32 at http://esp32control.local:

#include <ESPmDNS.h>

void setup() {
  // ... WiFi setup ...
  if (MDNS.begin("esp32control")) {
    Serial.println("mDNS responder started: http://esp32control.local");
    MDNS.addService("http", "tcp", 80);
  }
  // ... server setup ...
}

mDNS works on Windows, macOS, iOS, and Android (Android requires Bonjour/mDNS support, which is built into modern Android versions). On Windows, you may need to install Apple Bonjour Print Services if mDNS doesn’t resolve.

D1 Mini V2 NodeMCU ESP8266

D1 Mini V2 NodeMCU 4M Bytes Lua Wi-Fi Internet Of Things Development Board Based ESP8266

The ESP8266 D1 Mini supports the same HTTP web server concept at a lower cost. Perfect for simple single-channel GPIO control projects where ESP32’s extra power isn’t needed.

View on Zbotic

Frequently Asked Questions

Can I access the ESP32 web server from outside my home network?

Yes, but it requires port forwarding on your router (risky) or a VPN/tunnel solution. Better options include using a free service like Ngrok for temporary remote access, or setting up a WireGuard VPN server on a Raspberry Pi for permanent secure remote access. Never expose an unprotected ESP32 web server directly to the internet.

How many simultaneous connections can the ESP32 web server handle?

The blocking WebServer library handles 1 request at a time. ESPAsyncWebServer can handle 4–8 simultaneous connections (limited by ESP32 TCP/IP stack configuration). For typical home automation use with a handful of users, either approach is fine. For higher concurrency, use an MQTT-based architecture instead.

Why does my ESP32 web page load slowly or time out?

Common causes: (1) The ESP32 is busy in loop() and not calling server.handleClient() often enough — switch to ESPAsyncWebServer. (2) The HTML response is too large — keep pages under 50KB. (3) Wi-Fi signal is weak — try moving the router closer or use an ESP32 with external antenna. (4) PSRAM is not available and the string is fragmenting heap — split large HTML into chunks using chunked transfer encoding.

Can I serve files from SPIFFS/LittleFS instead of hardcoding HTML?

Yes! Storing HTML, CSS, and JavaScript in SPIFFS or LittleFS flash file system is much better for complex UIs. Use ESPAsyncWebServer’s server.serveStatic("/", SPIFFS, "/www/") to automatically serve files. This allows updating the UI without recompiling firmware — just upload new HTML files via a file upload endpoint.

What GPIO pins are safe to use for output on ESP32?

Safe output GPIO pins: 2, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 32, 33. Avoid: GPIO 0 (boot mode), GPIO 1 (TX), GPIO 3 (RX), GPIO 6–11 (connected to flash SPI), GPIO 34–39 (input-only, no pullup). Always check your specific board’s pinout diagram as some pins may be used by on-board components.

Get Your ESP32 Web Server Project Started

Shop for ESP32 development boards, sensors, relay modules, and expansion boards at Zbotic. Quality components, competitive Indian prices, and fast delivery nationwide.

Shop ESP32 Components at Zbotic

Tags: ESP32 Arduino, ESP32 Web Server, ESPAsyncWebServer, GPIO control, home automation, HTTP server ESP32, IoT browser control
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
ESP8266 Power Consumption: Red...
blog esp8266 power consumption reducing current in sleep mode 595555
blog esp32 interrupt handling gpio interrupt tutorial and code 595558
ESP32 Interrupt Handling: GPIO...

Related posts

Svg%3E
Read more

IoT Home Insurance Sensor Kit: Leak, Smoke, and Motion

April 1, 2026 0
Table of Contents IoT and Home Insurance Water Leak Detection Smoke and Fire Detection Motion and Intrusion Sensing Building the... Continue reading
Svg%3E
Read more

IoT Pet Tracker: GPS Collar with Geofencing Alerts

April 1, 2026 0
Table of Contents Introduction and Overview Hardware Components Required GPS Module Integration with ESP32 Cloud Platform Setup Real-Time Tracking Dashboard... Continue reading
Svg%3E
Read more

IoT Aquaponics Controller: Fish and Plant Automation

April 1, 2026 0
Table of Contents The Water Monitoring Challenge in India Sensor Technologies for Water Building the Sensor Node Data Transmission and... Continue reading
Svg%3E
Read more

IoT Composting Monitor: Temperature and Moisture Tracking

April 1, 2026 0
Table of Contents Why Temperature Monitoring Matters Sensor Selection Guide Hardware Assembly and Wiring Firmware Development Cloud Data Logging Alert... Continue reading
Svg%3E
Read more

IoT Beehive Monitor: Weight, Temperature, and Humidity

April 1, 2026 0
Table of Contents Why Monitor Beehives Weight Measurement System Temperature and Humidity Sensing Building the Monitor Data Analysis for Bee... Continue reading

Add comment Cancel reply

Your email address will not be published. Required fields are marked

Facebook Twitter Instagram Pinterest Linkedin Youtube

Get the latest deals and more.

Download on Google Play Download on the App Store

Call us: 020 69134444 / 1800 209 0998

Monday - Saturday 09:30 AM - 06:00 PM
For Technical Supports Email: [email protected]
For Sales / Enquiries Email: [email protected]

  • My Account

    • Cart

    • Wishlist

    • Checkout

    • My Orders

    • Track Order

    • My Account

  • Information

    • FAQs

    • Blogs

    • Career

    • About Us

    • Contact Us

    • Payment Options

  • Policies

    • Privacy Policy

    • Terms & Conditions

    • GST Input Tax Credit

    • Shipping Return Policy

    • E-Waste Collection Points

    • Our Sitemap

© Zbotic.in is registered trademark of Moxie Supply Pvt Ltd – All Rights Reserved
Login
Use Phone Number
Use Email Address
Not a member yet? Register Now
Reset Password
Use Phone Number
Use Email Address
Register
Already a member? Login Now