Tap a button on your phone and watch an LED light up across the room. This External LED via Wi-Fi turns an ESP32 into a tiny web server that hosts a page with ON/OFF buttons. Open the page on any device on your Wi-Fi, tap a button, and a 5 mm LED wired to the board flips instantly.
You only need three parts for the prototype: an ESP32, a 5 mm LED, and a 2200 Ω resistor. The LED sits on GPIO 23 so it stays free from the default serial pins, and the resistor limits current for a long, safe demo. Drop everything into a small 3D-printed case if you want a clean, hand-held gadget.
Setup is straightforward: flash the sketch, change the ssid/password, and connect the LED (anode → resistor → GPIO23, cathode → GND). When the Serial Monitor prints the IP address, type it into your phone’s browser. The page loads with big buttons and a live status label so you always know whether the LED is on or off.
Once you’re comfortable with this concept, you can explore more advanced boards like the ESP32-CAM. Instead of just switching an LED, the ESP32-CAM lets you capture images, stream video, and store files on an SD card—perfect for smart cameras and visual IoT projects. If you want to try that next, check out the ESP32-CAM Image Capture and SD Storagetutorial on Circuitrocks Learn.
Circuit Diagram

LED connection
- GPIO23 → Resistor (220Ω/330Ω) → LED Anode (long leg +)
- LED Cathode (short leg -) → GND (ESP32)
Sample Code
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";
WebServer server(80);
// External 5mm LED pin (recommended)
const int LED_PIN = 23; // GPIO23
bool ledOn = false;
String page() { String s = R"(
<!doctype html>
<html>
<head> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>ESP32 LED Control</title> <style> body{font-family:Arial;margin:20px}.card{max-width:420px;margin:auto;padding:16px;border:1px solid #ddd;border-radius:12px}.btn{padding:12px 16px;border:none;border-radius:10px;cursor:pointer;margin-right:8px}.on{background:#1f9d55;color:#fff}.off{background:#e53e3e;color:#fff}.state{font-weight:bold} </style>
</head>
<body> <div class="card"> <h2>ESP32 - External LED (GPIO23)</h2> <p>Status: <span class="state">)"; s += (ledOn? "ON": "OFF"); s += R"(</span></p> <p> <a href="/on"><button class="btn on">ON</button></a> <a href="/off"><button class="btn off">OFF</button></a> </p> </div>
</body>
</html>
)"; return s;
}
void handleRoot() { server.send(200, "text/html", page()); }
void handleOn() { ledOn = true; digitalWrite(LED_PIN, HIGH); server.sendHeader("Location", "/"); server.send(303);
}
void handleOff() { ledOn = false; digitalWrite(LED_PIN, LOW); server.sendHeader("Location", "/"); server.send(303);
}
void setup() { Serial.begin(115200); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW); WiFi.begin(ssid, password); Serial.print("Connecting"); while (WiFi.status()!= WL_CONNECTED) { delay(400); Serial.print("."); } Serial.println("nConnected!"); Serial.print("Open website: http://"); Serial.println(WiFi.localIP()); server.on("/", handleRoot); server.on("/on", handleOn); server.on("/off", handleOff); server.begin(); Serial.println("Web server started.");
}
void loop() { server.handleClient();
}
How It Works
When the ESP32 boots, it joins your Wi-Fi with WiFi.begin(ssid, password) and waits until WL_CONNECTED. It then prints its local IP address so you know what to open in a browser. The sketch also configures GPIO23 as an output and starts a tiny HTTP server on port 80.
Three routes power the experience. The root path / serves a small HTML page with an ON and OFF button and a visible status label. The /on and /off routes flip the ledOn flag, write HIGH or LOW to GPIO23, and then send an HTTP 303 redirect back to / so the page refreshes with the updated state without you pressing back.
Inside loop(), server.handleClient() processes incoming requests. Because the page is static and the handlers are tiny, the response feels instant even on a phone. The result is a predictable interaction loop: connect → tap → LED reacts → page reflects the new state
Applications & Extensions
Start with the desktop LED in a small 3D-printed case—great for task reminders, meeting indicators, or a silent “ping” light for teammates. Since it’s just a web page, anyone on the same network can toggle it from a browser without installing anything.
Grow it into multi-output control. Add more pins and buttons for a lamp, fan, or relay board, or swap the LED for a MOSFET-driven LED strip. You can also add a slider UI for brightness or animation speed and map it to PWM on another pin.
Harden it for the real world. Add a simple login form, mDNS (http://esp32.local/) so you don’t memorize IPs, or move to AsyncWebServer for heavier pages. If you need control outside your LAN, pair it with a VPN, a reverse proxy, or a cloud dashboard—same hardware, same wiring, bigger reach.
Watch the Full Demo Video
Frequently Asked Questions
What does this External LED via Wi-Fi | ESP32 Mini Guide tutorial cover?
Tap a button on your phone and watch an LED light up across the room.
Why does my ESP32 reset randomly during the External LED via Wi-Fi | ESP32 Mini Guide sketch?
Usually brownout from a weak USB supply. Use a 5V/2A wall adapter or add a 470uF cap across VIN/GND. Second cause: WDT timeout — sprinkle yield() or vTaskDelay() in long loops.
Can I run ESP8266 code on an ESP32?
Mostly yes. ESP32 is API-compatible with most ESP8266 Arduino libraries plus dual core, BLE, and more I/O. Watch for analogRead range (ESP32 is 0-4095, 12-bit) and pin numbering.
