BysMax

ESP32 WiFi Tutorial — Connect to WiFi, Web Server & HTTP Requests

14 min

The ESP32 has dual-mode WiFi (2.4 GHz 802.11 b/g/n) built in. Unlike Arduino Uno or Nano which need an external WiFi shield, the ESP32 connects to your router with a few lines of code. This guide covers everything from basic connection to building a web server.

Prerequisite: Install ESP32 board support in Arduino IDE. Go to File → Preferences → Additional Board Manager URLs and add:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Then: Tools → Board → Boards Manager → search "esp32" → Install.

ESP32 WiFi Modes

ModeDescriptionUse case
Station (STA)ESP32 connects to existing WiFi routerMost IoT projects
Access Point (AP)ESP32 creates its own WiFi networkConfig portal, direct device connection
Station + APBoth simultaneouslyConfig portals with internet relay

Mode 1 — Station Mode (Connect to Your Router)

#include <WiFi.h>

const char* ssid     = "YourWiFiName";     // Replace with your SSID
const char* password = "YourPassword";      // Replace with your password

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println("Connecting to WiFi...");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  // Wait for connection (max 10 seconds)
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 20) {
    delay(500);
    Serial.print(".");
    attempts++;
  }

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\nConnected!");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    Serial.print("Signal strength (RSSI): ");
    Serial.print(WiFi.RSSI());
    Serial.println(" dBm");
  } else {
    Serial.println("\nFailed to connect.");
  }
}

void loop() {
  // Check if still connected
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi lost. Reconnecting...");
    WiFi.reconnect();
    delay(5000);
  }
}

Expected output:

Connecting to WiFi...
..........
Connected!
IP address: 192.168.1.105
Signal strength (RSSI): -58 dBm

Open your router's client list and you'll see the ESP32 with the IP address shown.

Mode 2 — Access Point (Create Your Own WiFi)

#include <WiFi.h>

const char* ap_ssid     = "ESP32-Setup";
const char* ap_password = "12345678";  // Min 8 characters, or use "" for open

void setup() {
  Serial.begin(115200);

  WiFi.mode(WIFI_AP);
  WiFi.softAP(ap_ssid, ap_password);

  Serial.println("Access Point started");
  Serial.print("AP IP address: ");
  Serial.println(WiFi.softAPIP());  // Usually 192.168.4.1
  Serial.print("SSID: ");
  Serial.println(ap_ssid);
}

void loop() {
  Serial.print("Clients connected: ");
  Serial.println(WiFi.softAPgetStationNum());
  delay(5000);
}

Connect your phone/laptop to "ESP32-Setup" and navigate to 192.168.4.1 in a browser.

Build a Web Server

Control an LED from any browser on your network:

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

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

WebServer server(80);  // Port 80 = standard HTTP
const int LED_PIN = 2; // Built-in LED

// HTML page
const char* htmlPage = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
  <title>ESP32 Control</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body { font-family: Arial; text-align: center; margin-top: 50px; }
    button { padding: 15px 30px; font-size: 20px; margin: 10px; border: none; border-radius: 8px; cursor: pointer; }
    .on  { background: #4CAF50; color: white; }
    .off { background: #f44336; color: white; }
  </style>
</head>
<body>
  <h1>ESP32 LED Control</h1>
  <button class="on"  onclick="fetch('/on')">LED ON</button>
  <button class="off" onclick="fetch('/off')">LED OFF</button>
</body>
</html>
)rawliteral";

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

void handleLEDOn() {
  digitalWrite(LED_PIN, HIGH);
  server.send(200, "text/plain", "LED is ON");
  Serial.println("LED ON");
}

void handleLEDOff() {
  digitalWrite(LED_PIN, LOW);
  server.send(200, "text/plain", "LED is OFF");
  Serial.println("LED OFF");
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("\nConnected! Open: http://" + WiFi.localIP().toString());

  server.on("/",    handleRoot);
  server.on("/on",  handleLEDOn);
  server.on("/off", handleLEDOff);
  server.begin();
}

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

Upload, open Serial Monitor, and navigate to the IP shown. You'll see buttons to control the LED from any device on your network.

HTTP GET Request (Fetch Data from an API)

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

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

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected!");
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    
    // Free test API — returns random numbers
    http.begin("https://worldtimeapi.org/api/timezone/America/New_York");
    
    int httpCode = http.GET();
    
    if (httpCode == HTTP_CODE_OK) {
      String payload = http.getString();
      
      // Parse JSON
      JsonDocument doc;
      deserializeJson(doc, payload);
      
      const char* datetime = doc["datetime"];
      Serial.print("Current time: ");
      Serial.println(datetime);
    } else {
      Serial.print("HTTP error: ");
      Serial.println(httpCode);
    }
    
    http.end();
  }
  
  delay(10000);  // Fetch every 10 seconds
}

Install ArduinoJson library: Library Manager → search "ArduinoJson" by Benoit Blanchon → Install.

HTTP POST Request (Send Sensor Data)

#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid      = "YourWiFiName";
const char* password  = "YourPassword";
const char* serverUrl = "https://httpbin.org/post";  // Test endpoint

void postSensorData(float temperature, float humidity) {
  HTTPClient http;
  http.begin(serverUrl);
  http.addHeader("Content-Type", "application/json");

  String jsonPayload = "{\"temperature\":" + String(temperature, 1) +
                       ",\"humidity\":" + String(humidity, 1) + "}";

  int httpCode = http.POST(jsonPayload);

  if (httpCode > 0) {
    Serial.print("POST response code: ");
    Serial.println(httpCode);
    if (httpCode == HTTP_CODE_OK) {
      Serial.println("Data sent successfully!");
    }
  } else {
    Serial.print("POST failed: ");
    Serial.println(http.errorToString(httpCode));
  }

  http.end();
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected!");
}

void loop() {
  float fakeTemp = 23.5 + random(-10, 10) / 10.0;
  float fakeHum  = 55.0 + random(-50, 50) / 10.0;
  
  Serial.print("Sending: temp=");
  Serial.print(fakeTemp);
  Serial.print(", hum=");
  Serial.println(fakeHum);
  
  postSensorData(fakeTemp, fakeHum);
  delay(30000);  // Send every 30 seconds
}

WiFi Manager — Auto-Configure WiFi

Instead of hardcoding credentials, WiFiManager lets the user input WiFi settings via a captive portal:

#include <WiFiManager.h>  // Install: "WiFiManager" by tzapu

void setup() {
  Serial.begin(115200);
  
  WiFiManager wifiManager;
  
  // Will launch AP "AutoConnectAP" if no WiFi saved
  // Connect phone to this AP, browser opens config portal
  if (!wifiManager.autoConnect("AutoConnectAP", "password123")) {
    Serial.println("Failed to connect — restarting");
    delay(3000);
    ESP.restart();
  }
  
  Serial.println("Connected via WiFiManager!");
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());
}

void loop() {}

Install: Library Manager → search "WiFiManager" by tzapu → Install.

This is the professional way to handle WiFi credentials in production devices — no hardcoded passwords.

Scan Available Networks

#include <WiFi.h>

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);

  Serial.println("Scanning for WiFi networks...");
  int found = WiFi.scanNetworks();

  if (found == 0) {
    Serial.println("No networks found");
  } else {
    for (int i = 0; i < found; i++) {
      Serial.print(i + 1);
      Serial.print(". ");
      Serial.print(WiFi.SSID(i));
      Serial.print(" (");
      Serial.print(WiFi.RSSI(i));
      Serial.print(" dBm)");
      Serial.println(WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? " [OPEN]" : " [SECURED]");
    }
  }
}

void loop() {}

Simulate on Wokwi

Wokwi supports ESP32 WiFi simulation. The virtual Wokwi-GUEST network is always available:

const char* ssid     = "Wokwi-GUEST";
const char* password = "";  // Open network in Wokwi

This lets you test all WiFi code including HTTP requests before touching real hardware.

See the Wokwi simulator guide for setup.

Troubleshooting

"Connection failed" after many attempts:

  • Verify SSID and password (case-sensitive)
  • Check if router is on 2.4 GHz — ESP32 doesn't support 5 GHz
  • Move ESP32 closer to the router during testing
  • Try connecting phone to confirm the network is reachable

IP address is 0.0.0.0:

  • DHCP failed — your router may have run out of addresses
  • Try assigning a static IP: WiFi.config(IPAddress(192,168,1,200), gateway, subnet);

Web server works on local network but not from internet:

  • You need port forwarding on your router (not recommended for security)
  • Better approach: use MQTT broker or cloud services (ThingSpeak, Adafruit IO)

HTTPClient SSL/HTTPS errors:

  • Add root CA certificate, or disable SSL verification (not secure):
    http.begin("https://example.com/api");
    // OR for testing only:
    WiFiClientInsecure client;
    client.setInsecure();
    http.begin(client, "https://example.com/api");
    

ESP32 reboots randomly during WiFi use:

  • Power issue: USB power can't supply peak WiFi current (~500 mA bursts)
  • Add 100µF capacitor between 3.3V and GND near the ESP32
  • Use a good USB cable (not a cheap charging-only cable)

Frequently Asked Questions (FAQ)

What frequency WiFi does ESP32 support? 2.4 GHz only. 5 GHz is not supported. Check your router settings — if you have a "combined" network showing one SSID, make sure 2.4 GHz band is enabled.

Can ESP32 connect to a WiFi network with a hidden SSID? Yes. Use WiFi.begin(ssid, password, channel, bssid, connect) with the BSSID (MAC address) of the access point.

How many clients can connect to the ESP32 access point? Maximum 4 clients simultaneously in AP mode.

What is the range of ESP32 WiFi? Typically 30–50 meters indoors, up to 100+ meters outdoors. An external antenna (via U.FL connector) extends range significantly.

Can ESP32 work as both a WiFi client and access point at the same time? Yes. Set WiFi.mode(WIFI_AP_STA) to enable both modes simultaneously. This is used for configuration portals that still maintain internet connectivity.

Comentarios (0) /es/blog/esp32-wifi-tutorial