← All projects
IoT / Web Beginner

Wi-Fi Setup Without Reflashing: The WiFiManager Captive Portal

Get the Wi-Fi password out of your code: on first boot the ESP32 opens its own access point with a web form to pick a network and set custom parameters.

Difficulty
Beginner
Time
30 min
Category
IoT / Web

The problem

Most examples hard-code the SSID and password in the sketch. That's a pain: new router — reflash; give the device to a friend — reflash. The WiFiManager library solves it the same way off-the-shelf smart plugs do:

  1. If the board has no saved network or can't connect, it creates an access point called ESP32-Setup.
  2. You join it from your phone and a setup page opens automatically (captive portal).
  3. Pick a network from the list, enter the password — the board stores it in flash.

It's worth adding this to any project on this site that you plan to use long-term.

What you need

  • Any ESP32 board
  • The WiFiManager library (by tzapu) — install it from the Library Manager

Code

Besides Wi-Fi, the portal also stores a custom parameter — the MQTT server address. Holding BOOT for 3 seconds at startup resets the settings.

#include <WiFi.h>
#include <WiFiManager.h>
#include <Preferences.h>

const int RESET_PIN = 0;   // BOOT button

WiFiManager wm;
Preferences prefs;
char mqttHost[40] = "";

void setup() {
  Serial.begin(115200);
  pinMode(RESET_PIN, INPUT_PULLUP);

  // Custom parameters live in NVS (non-volatile storage)
  prefs.begin("config", false);
  prefs.getString("mqtt", mqttHost, sizeof(mqttHost));

  // BOOT held for 3 s at startup → forget Wi-Fi
  if (digitalRead(RESET_PIN) == LOW) {
    delay(3000);
    if (digitalRead(RESET_PIN) == LOW) {
      Serial.println("Resetting Wi-Fi settings");
      wm.resetSettings();
    }
  }

  WiFiManagerParameter mqttParam("mqtt", "MQTT server", mqttHost, sizeof(mqttHost) - 1);
  wm.addParameter(&mqttParam);

  wm.setConfigPortalTimeout(180);   // 3 min to configure, then reboot
  if (!wm.autoConnect("ESP32-Setup", "setup1234")) {
    Serial.println("Portal timeout, restarting");
    ESP.restart();
  }

  strlcpy(mqttHost, mqttParam.getValue(), sizeof(mqttHost));
  prefs.putString("mqtt", mqttHost);

  Serial.printf("Connected! IP: %s, MQTT: %s\n",
                WiFi.localIP().toString().c_str(), mqttHost);
}

void loop() {
  // your main code
}

How to use it

  1. Flash the board and open the Serial Monitor.
  2. On your phone, join the ESP32-Setup network (password setup1234).
  3. If the page doesn't open by itself, go to http://192.168.4.1.
  4. Configure WiFi → choose your network, enter the password and MQTT address → Save.
  5. The board connects to your router. Future boots connect automatically, no portal.

Useful options

Method Why
wm.setConnectTimeout(20) How many seconds to wait for the saved network
wm.setConfigPortalBlocking(false) + wm.process() in loop() The portal doesn't block the rest of your code
wm.setHostname("kitchen-sensor") Device name shown in your router
wm.startConfigPortal("ESP32-Setup") Open the portal on demand, e.g. on a button press

Tips

  • The access point password must be at least 8 characters, otherwise it won't start.
  • With several identical devices, append part of the MAC address to the AP name to tell them apart.
  • WiFiManager only supports 2.4 GHz networks — just like the ESP32 itself.