Skip to content
Tutorial
12 min read
October 17, 2026

ESP32 WiFi Tutorial: Connect ESP32 to a WiFi Network (Arduino IDE)

Learn how to connect an ESP32 to WiFi with the Arduino IDE: station and access point modes, a reliable connect-with-timeout sketch, automatic reconnection, signal strength, scanning networks and the mistakes that cause connection failures.

Connecting an ESP32 to WiFi takes four lines of code. Keeping it connected for months, through router reboots, weak signal and power glitches, takes a little more. Most tutorials stop at the four lines, which is why so many projects work perfectly on the desk and then go silent a week after you install them.

This guide covers both halves. You will connect an ESP32 to your network, print its IP address, handle a failed connection properly, make it reconnect on its own, check signal strength, scan for nearby networks, and run the ESP32 as its own access point. Every sketch here works on the standard Arduino-ESP32 core with no extra libraries, and on any ESP32 board, including the DevKit V1, ESP32-S3 and ESP32-C3.

Image pending: ESP32 DevKit connected over USB to a laptop with the Arduino IDE Serial Monitor showing a successful WiFi connection and IP address

How ESP32 WiFi Works: The Three Modes

The ESP32 has a built-in 2.4 GHz radio (802.11 b/g/n) and can operate in three modes:

ModeConstantWhat it doesTypical use
Station (STA)WIFI_STAJoins your existing router like a phone or laptopSensors, web servers, MQTT, cloud APIs
Access Point (AP)WIFI_APCreates its own network that others joinSetup pages, no-router projects
Station + APWIFI_AP_STADoes both at the same timeConfiguration portals, repeaters

Almost everything you build will use Station mode. One hardware limit is worth knowing up front: the ESP32 only supports 2.4 GHz. It cannot see or join a 5 GHz-only network. Dual-band routers that broadcast one combined name are normally fine, but if your router has separate 2.4 GHz and 5 GHz names, connect the ESP32 to the 2.4 GHz one.

What You Need

  • Any ESP32 board (this guide uses a DevKit V1; see the ESP32 pinout guide if you need a pin reference)
  • A micro-USB or USB-C data cable
  • Arduino IDE with the ESP32 board package installed (Espressif Systems, via Boards Manager)
  • The name and password of a 2.4 GHz WiFi network

No extra library is required. The WiFi.h header ships with the ESP32 board package.

Select your board under Tools → Board → ESP32 Arduino → ESP32 Dev Module (or your exact board), pick the correct port, and you are ready.

Image pending: Arduino IDE Tools menu showing ESP32 Dev Module selected as the board and the correct COM port chosen

The Basic Connection Sketch

This is the shortest working version. Replace the two placeholders with your own credentials.

#include <WiFi.h>

const char* ssid     = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";

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

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("\nConnected!");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
}

Upload it, open the Serial Monitor at 115200 baud, and you should see a row of dots followed by an address such as 192.168.1.47. That address is how every other device on your network will reach the ESP32.

Why WiFi.mode(WIFI_STA) first? The ESP32 remembers its previous mode, and an old sketch may have left it in AP mode. Setting the mode explicitly guarantees you start in a known state.

Why this sketch is not good enough for real projects: the while loop waits forever. If the password is wrong, the router is off or the signal is weak, the ESP32 sits there printing dots and never does anything useful.

Image pending: Serial Monitor output showing the connecting dots followed by Connected and the assigned IP address

A Connection Function With a Timeout

A production-ready connect function gives up after a set time and lets the rest of your program decide what to do. This version waits 15 seconds, reports why it failed, and returns true or false.

#include <WiFi.h>

const char* ssid     = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";

bool connectWiFi(uint32_t timeoutMs = 15000) {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  uint32_t start = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - start < timeoutMs) {
    delay(250);
    Serial.print(".");
  }
  Serial.println();

  if (WiFi.status() == WL_CONNECTED) {
    Serial.printf("Connected. IP: %s  RSSI: %d dBm\n",
                  WiFi.localIP().toString().c_str(), WiFi.RSSI());
    return true;
  }

  Serial.printf("WiFi failed, status code %d\n", WiFi.status());
  return false;
}

void setup() {
  Serial.begin(115200);
  if (!connectWiFi()) {
    Serial.println("Continuing without WiFi...");
  }
}

void loop() {
}

The status code tells you what went wrong:

StatusValueMeaning
WL_CONNECTED3Connected and has an IP
WL_NO_SSID_AVAIL1The network name was not found (wrong name, out of range, or 5 GHz only)
WL_CONNECT_FAILED4Found the network but authentication failed (usually a wrong password)
WL_CONNECTION_LOST5Was connected, then lost the link
WL_DISCONNECTED6Not connected, often still trying

For a full diagnosis flow, see our ESP32 WiFi troubleshooting guide.

Automatic Reconnection

Routers reboot, signals dip, and DHCP leases expire. A sketch that connects once in setup() and never checks again will eventually go offline for good. There are two reliable ways to handle it.

Method 1: Check in the loop (simple)

unsigned long lastCheck = 0;

void loop() {
  if (millis() - lastCheck > 10000) {
    lastCheck = millis();
    if (WiFi.status() != WL_CONNECTED) {
      Serial.println("WiFi lost, reconnecting...");
      WiFi.disconnect();
      WiFi.reconnect();
    }
  }

  // your normal code here
}

This uses millis() instead of delay(), so the rest of your program keeps running while WiFi recovers.

Method 2: React to WiFi events (cleaner)

The ESP32 fires events when it connects, gets an IP and disconnects. Registering a handler lets you reconnect the moment the link drops.

void onWiFiEvent(WiFiEvent_t event) {
  switch (event) {
    case ARDUINO_EVENT_WIFI_STA_GOT_IP:
      Serial.print("Got IP: ");
      Serial.println(WiFi.localIP());
      break;
    case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
      Serial.println("Disconnected. Reconnecting...");
      WiFi.reconnect();
      break;
    default:
      break;
  }
}

void setup() {
  Serial.begin(115200);
  WiFi.onEvent(onWiFiEvent);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
}

Event handlers run in a separate task, so keep them short: print, set a flag, or call reconnect(). Do not put long delays or heavy work inside them.

The ESP32 also has WiFi.setAutoReconnect(true), which is on by default for most cores. It handles simple drops, but it will not rescue you from a changed password or a router that stayed off for hours, so keeping an explicit check in your code is still worth it.

Image pending: Serial Monitor log showing a disconnect event after turning off the router, followed by a successful automatic reconnection when it comes back

Checking Signal Strength (RSSI)

WiFi.RSSI() returns the received signal strength in dBm. It is a negative number, and closer to zero is better.

RSSIQualityWhat to expect
-30 to -50 dBmExcellentFast and stable
-50 to -60 dBmGoodReliable for most projects
-60 to -70 dBmFairFine for small data, may slow down streaming
-70 to -80 dBmWeakFrequent drops, slow responses
Below -80 dBmVery poorExpect disconnects
Serial.printf("Signal: %d dBm\n", WiFi.RSSI());

If your ESP32 disconnects often and the RSSI is worse than about -75 dBm, no code will fix it. Move the board closer, point the antenna away from metal, or use a board with an external antenna connector.

Image pending: Diagram of RSSI signal strength zones from excellent to very poor, with the ESP32 placed at different distances from a router

Scanning for Nearby Networks

Scanning is useful for debugging ("can the ESP32 even see my router?") and for building network pickers.

#include <WiFi.h>

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

  Serial.println("Scanning...");
  int n = WiFi.scanNetworks();

  if (n == 0) {
    Serial.println("No networks found");
  } else {
    for (int i = 0; i < n; i++) {
      Serial.printf("%2d: %-32s  %4d dBm  ch %2d  %s\n",
        i + 1,
        WiFi.SSID(i).c_str(),
        WiFi.RSSI(i),
        WiFi.channel(i),
        WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? "open" : "secured");
    }
  }
}

void loop() {
}

If your network does not appear in this list, the ESP32 cannot connect to it. The usual reasons are that your router is broadcasting only on 5 GHz, the network name is hidden, or the board is simply too far away.

Image pending: Serial Monitor output of the WiFi scan listing network names, signal strength, channel and security type

Running the ESP32 as an Access Point

In AP mode the ESP32 creates its own WiFi network. Phones and laptops join it directly, with no router needed. This is how you build setup pages, local control panels and projects for places without internet.

#include <WiFi.h>

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

  WiFi.mode(WIFI_AP);
  bool ok = WiFi.softAP("ESP32-Setup", "12345678"); // password: 8+ characters

  Serial.println(ok ? "Access point started" : "AP failed");
  Serial.print("AP IP address: ");
  Serial.println(WiFi.softAPIP()); // default: 192.168.4.1
}

void loop() {
}

Join ESP32-Setup from your phone and the ESP32 is reachable at 192.168.4.1. The password must be at least 8 characters. Pass NULL as the password to create an open network. A single ESP32 accepts only a handful of simultaneous clients (the default limit is 4, and the maximum is 10), so AP mode suits control panels rather than shared hotspots.

If you want users to type their home WiFi details into a web page instead of editing code, read the WiFiManager captive portal guide.

Image pending: Phone WiFi settings screen showing the ESP32-Setup access point and the browser opening the ESP32 page at 192.168.4.1

Good Habits for Real Projects

Keep credentials out of your main sketch. Put them in a separate secrets.h file and add that file to .gitignore so you never publish your WiFi password by accident.

// secrets.h
#define WIFI_SSID     "YOUR_WIFI_NAME"
#define WIFI_PASSWORD "YOUR_WIFI_PASSWORD"
#include "secrets.h"
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

Set a hostname. A name like esp32-garage is much easier to spot in your router's device list than espressif. Call WiFi.setHostname("esp32-garage"); after WiFi.mode(WIFI_STA) and before WiFi.begin().

Give it a fixed address when other things depend on it. Home Assistant, dashboards and port forwarding all work better if the ESP32 always has the same IP. See the static IP guide.

Do not use delay() for long waits. Use millis() timing so WiFi tasks and your own code keep running.

Mind the power supply. The WiFi radio draws current spikes of roughly 300 to 400 mA while transmitting. A weak USB port or long thin cable causes brownouts that look exactly like WiFi bugs.

Image pending: Router admin page device list showing the ESP32 under its custom hostname with its assigned IP and MAC address

Frequently Asked Questions

Can the ESP32 connect to 5 GHz WiFi? No. The original ESP32, ESP32-S3 and ESP32-C3 are 2.4 GHz only. Newer parts such as the ESP32-C5 add 5 GHz, but the common boards do not.

Why does my ESP32 connect but show "IP: 0.0.0.0"? It joined the network but did not receive an address from DHCP yet. Wait a second and read the IP again, or check your router's DHCP settings.

Can I use WiFi and Bluetooth together? Yes, but they share one radio and memory, so both slow down and RAM gets tight. The BLE-only or WiFi-only designs are far more stable.

Does WiFi block my analog readings? On ADC2 pins, yes. Use ADC1 pins (GPIO 32 to 39) whenever WiFi is active. Details in the ESP32 ADC guide.

What is the next step after connecting? Serve a web page, talk to an API, or publish data. Good follow-ups are HTTP GET and POST requests, MQTT, and WebSockets for real-time data.

Signal In

Built from what makers search for

The lookups piling up in SolderHub's search bar every day shape what we publish next — new component pages, board guides, and firmware notes, sent out as they go live.

By subscribing you agree to our Privacy Policy. Unsubscribe anytime.