ESP8266 NodeMCU Access Point (AP) for Web Server

In this tutorial, you’ll learn how to set your ESP8266 NodeMCU as an Access Point (AP) using Arduino IDE. This allows you to connect directly to your ESP8266 via Wi-Fi without a wireless router.

ESP8266 NodeMCU Access Point AP for Web Server

To set the ESP8266 as an Access Point use WiFi.softAP(ssid, password);

ESP8266 Station and Access Point

In most of our ESP8266 NodeMCU web server projects, we connect the ESP8266 to a wireless router. In this configuration, we can access the ESP8266 through the local network.

In this scenario, the router acts as an access point and the ESP8266 is set as a station. So, you need to be connected to your router (local network) to control the ESP8266.

ESP866 NodeMCU set as a Wi-Fi Station

In some cases, this might not be the best configuration (when you don’t have a router nearby). But if you set the ESP8266 as an access point (hotspot), you can be connected to the ESP8266 using any device with Wi-Fi capabilities without the need to connect to your router.

In simple words, when you set the ESP8266 as an access point you create its own Wi‑Fi network and nearby Wi-Fi devices (stations) can connect to it (like your smartphone or your computer).

ESP866 NodeMCU Set as an Access Point (AP) Mode

In this tutorial, we’ll show you how to set the ESP8266 as an access point in your web server projects. This way, you don’t need to be connected to a router to control your ESP8266.

Because the ESP8266 doesn’t connect further to a wired network (like your router), it is called soft-AP (soft Access Point).

This means that if you try to load libraries or use firmware from the internet, it will not work. It also doesn’t work if you try to make HTTP requests to services on the internet like publishing sensor readings to the cloud.

Installing the DHT Library for ESP8266

For this example, we’ll use a previous web server project that displays sensor readings from a DHT sensor.

Having the ESP8266 Board installed in Arduino IDE, to read from the DHT sensor, we’ll use the DHT library from Adafruit. To use this library you also need to install the Adafruit Unified Sensor library.

Follow the next steps to install those two libraries:

1. Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open.

2. Search for “DHT” on the Search box and install the DHT library from Adafruit.

Installing Adafruit DHT library

3. After installing the DHT library from Adafruit, type “Adafruit Unified Sensor” in the search box. Scroll all the way down to find the library and install it.

Installing Adafruit Unified Sensor driver library

After installing the libraries, restart your Arduino IDE.

ESP8266 NodeMCU Access Point (AP)

In this example, we’ll modify the ESP8266 Web Server from a previous tutorial to add access point capabilities. Here’s the project example we’ll use: ESP8266 DHT11/DHT22 Temperature and Humidity Web Server with Arduino IDE.

What we’ll show you here can be used with any ESP8266 web server example.

Upload the sketch provided below to set the ESP8266 as an access point.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com/esp8266-nodemcu-access-point-ap-web-server/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

// Import required libraries
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>

const char* ssid     = "ESP8266-Access-Point";
const char* password = "123456789";

#define DHTPIN 5     // Digital pin connected to the DHT sensor

// Uncomment the type of sensor in use:
//#define DHTTYPE    DHT11     // DHT 11
#define DHTTYPE    DHT22     // DHT 22 (AM2302)
//#define DHTTYPE    DHT21     // DHT 21 (AM2301)

DHT dht(DHTPIN, DHTTYPE);

// current temperature & humidity, updated in loop()
float t = 0.0;
float h = 0.0;

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;    // will store last time DHT was updated

// Updates DHT readings every 10 seconds
const long interval = 10000;  

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .dht-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>ESP8266 DHT Server</h2>
  <p>
    <span class="dht-labels">Temperature</span> 
    <span id="temperature">%TEMPERATURE%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <span class="dht-labels">Humidity</span>
    <span id="humidity">%HUMIDITY%</span>
    <sup class="units">%</sup>
  </p>
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperature").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperature", true);
  xhttp.send();
}, 10000 ) ;

setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("humidity").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/humidity", true);
  xhttp.send();
}, 10000 ) ;
</script>
</html>)rawliteral";

// Replaces placeholder with DHT values
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATURE"){
    return String(t);
  }
  else if(var == "HUMIDITY"){
    return String(h);
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  dht.begin();
  
  Serial.print("Setting AP (Access Point)…");
  // Remove the password parameter, if you want the AP (Access Point) to be open
  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  // Print ESP8266 Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(t).c_str());
  });
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(h).c_str());
  });

  // Start server
  server.begin();
}
 
void loop(){  
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time you updated the DHT values
    previousMillis = currentMillis;
    // Read temperature as Celsius (the default)
    float newT = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    //float newT = dht.readTemperature(true);
    // if temperature read failed, don't change t value
    if (isnan(newT)) {
      Serial.println("Failed to read from DHT sensor!");
    }
    else {
      t = newT;
      Serial.println(t);
    }
    // Read Humidity
    float newH = dht.readHumidity();
    // if humidity read failed, don't change h value 
    if (isnan(newH)) {
      Serial.println("Failed to read from DHT sensor!");
    }
    else {
      h = newH;
      Serial.println(h);
    }
  }
}

View raw code

Customize the SSID and Password

You need to define a SSID name and a password to access the ESP8266. In this example we’re setting the ESP8266 SSID name to ESP8266-Access-Point, but you can modify the name to whatever you want. The password is 123456789, but you can also modify it.

const char* ssid     = "ESP8266-Access-Point";
const char* password = "123456789";

Setting the ESP8266 as an Access Point (AP)

There’s a section in the setup() to set the ESP8266 as an access point using the softAP() method:

WiFi.softAP(ssid, password);

There are also other optional parameters you can pass to the softAP() method. Here’s all the parameters:

.softAP(const char* ssid, const char* password, int channel, int ssid_hidden, int max_connection)
  • ssid (defined earlier): maximum of 31 characters
  • password (defined earlier): minimum of 8 characters. If not specified, the access point will be open (maximum 63 characters)
  • channel: Wi-Fi channel number (1-13). Default is 1
  • ssid_hidden: if set to true will hide SSID
  • max_connection: max simultaneous connected stations, from 0 to 8

Next, get the access point IP address using the softAPIP() method and print it in the Serial Monitor.

IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);

Note: by default, the access point IP address is 192.168.4.1

These are the snippets of code you need to include in your web server sketches to set the ESP8266 as a soft access point.

To learn how the full web server code works, read: ESP8266 NodeMCU DHT11/DHT22 Temperature and Humidity Web Server with Arduino IDE.

Parts Required

To proceed with this tutorial, you need the following parts:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematic Diagram

Assemble all the parts by following the next schematic diagram:

ESP8266 NodeMCU Access Point (AP) Web Server Circuit Schematic Diagram DHT sensor

Connecting to the ESP8266 Access Point

Having the ESP8266 running the sketch, in your smartphone open your Wi-Fi settings and tap the ESP8266-Access-Point network:

Connect to ESP8266 NodeMCU Access Point (AP Mode)

Enter the password you’ve defined earlier.

ESP8266 NodeMCU Access Point (AP) Enter Password

Open your web browser and type the IP address http://192.168.4.1. The web server page should load:

ESP8266 NodeMCU Access Point Web Server using Arduino IDE

The web server page is a bit different from the original web server. That web server displays two icons next to the temperature and humidity. Those icons are loaded from the Font Awesome website. However, because the ESP8266 acts a soft access point (it is not connected to the internet) we cannot load those icons.

Wrapping Up

In this tutorial you’ve learned how to set the ESP8266 as a soft access point. This allows you to connect to the ESP8266 web server directly via Wi-Fi without the need to connect to a router.

However, note that the ESP8266 is not connected to the internet, so you can’t make HTTP requests to other services to publish sensor data or to get data from the internet (like loading the icons).

You may also like reading:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

54 thoughts on “ESP8266 NodeMCU Access Point (AP) for Web Server”

  1. Great article,

    Note: by default, the access point IP address is 192.168.4.1

    Is it possible to change the default IP address so that multiple access points can be created?

    Thank you

    Reply
    • Hi Ben.
      Yes, you can do that using the following function to configure the access point:
      softAPConfig (local_ip, gateway, subnet)
      Regards,
      Sara

      Reply
  2. Hy dears,
    I’m wondering if a “non NodeMCU” ESP8266 model will go to the same.
    I have some older ESP01 by hand, but perhaps these boards haven’t enough memory to load the sketch. Or are there any other reasons they couldn’t do the staff ?

    Best regards and thanks for your job.
    Gatsby

    Reply
  3. Hi thanks for another great tutorial. I have used many of your tutorials and books to learn iot. i am a little puzzled where I would actually use a soft ap with no connection to the rest of the network. To me the point of iot is that it’s all connected together using my node red server and that i can get telegram messages about what is going on when I’m not at home. Am I missing something here.

    Reply
    • Hi Archer,
      I see your point. But in some cases, people found it more practical to use an access point rather than connecting to a wi-fi network. For example, to control a toy robot that you want to take anywhere, having an access point can be more practical.
      Thank you for your comment and thank you for supporting our work.
      Regards,
      Sara

      Reply
  4. Hi Sara, Thank you for the reply

    Yes, you can do that using the following function to configure the access point:
    softAPConfig (local_ip, gateway, subnet)

    Pardon my lack of knowledge,
    In the code I donot see where “gateway” and “subnet” are defined
    do I do add something like

    const char* local_ip = “192.168.4.2”; // ESP8266 IP desired
    const char* gateway = “192.168.0.1”; // ESP8266 gateway desired
    const char* subnet = “255.255.255.0”; // ESP8266 subnet desired

    and put
    softAPConfig (local_ip, gateway, subnet)
    in void setup()
    just after
    WiFi.softAP(ssid, password); // ?
    How do I choose the gateway and subnet numbers?

    Thanks
    Ben

    Reply
  5. Hi, Rui and Sara, thaks for this tutorial.
    Using an ESP8266 as a soft AP, is it possible to control a card with relays? For example to turn on a light or to trigger an electric lock?
    Best regards
    Luciano

    Reply
  6. Hi. I have a problema with softap configuration. My nodemcu still show the first I created. I can’t change the name or any other para meter. What is the problem please?

    Reply
    • Hi.
      It should create a new one as long as you upload new code.
      In your smartphone, maybe it is better to “Forget” the older access point name, so that it is able to find the new one.
      Regards,
      Sara

      Reply
    • Hi.
      What libraries are you referring to?
      Just write the library name without the signs on each side. Otherwise, I can’t see the libraries you’re referring to.
      Regards,
      Sara

      Reply
  7. Hi Sara, thanks for this tutorial. There is one question actually I didn’t solve. It’s about DHCP. For security reasons, I want to manage DHCP ESP8266 service. I would like to decide how it will work, wich IP address it can deliver and so on. I was looking for 3 weeks on the WEB, but I didn’t realy find a useful information. For example, I’m unable to find the library involved in realtime DHCP managment. Can you help ?
    Vicor (France)

    Reply
  8. HI sara madam,
    Could you please tell me is it possible to connect to internet via ESP-01, if want to make it a bridge between router and my phone?

    Reply
  9. Hi Rui and Sara, i want to change the AP name and also the server IP address to something else then 191.168.4.1. Is this possible ? This is because i want to run 2 board in the same time who act like Access-points. But my phone or laptop always point me to the other esp8266 device.
    I find nowhere how to change the ip address to 192.168.5.1 for example.

    Also i find like the soft AP is like hard coded in my first esp8266 device who runs now as a client to my network for other things , but in the same time still act as Acess-point like before, how is that possible ?

    Reply
    • An example to answer your question.
      Station Mode
      #include <ESP8266WiFi.h>
      IPAddress apIP(192, 168, 5, 1); // Static Ip Address
      IPAddress apGW(192, 168, 5, 1); // Gateway Address to Zero if no Internet access demanded
      IPAddress apMSK(255, 255, 255, 0); // Class C network mask
      IPAddress staDns(1, 1, 1, 1); //DNS
      Setup section
      //================================================
      // Configure le module WiFi
      //================================================
      WiFi.mode(WIFI_STA);
      delay(200);
      WiFi.config(apIP, apGW, apMSK,staDns);
      delay(200);

      //================================================
      WiFi.begin(ssid, password); //Connect to wifi

      Acces Point Mode
      #include <ESP8266WiFi.h>

      // Network setup
      // ———————————
      IPAddress apIP(192, 168, 5, 1); // IP Adress for the device
      IPAddress apGW(0, 0, 0, 0); // Gateway to 0 for our needs (you have to adapt it to your’s)
      IPAddress apMSK(255, 255, 255, 240); // Network limited to 14 devices (standard is 255,255,255,0)

      int port = 8888; // Numéro de port pour établir le lien TCP (80 or 8080 for HTTP purpose)
      WiFiServer server(port);

      const char ssid = “YourSSID”; //Server SSID
      const char *password = “YourPassword”; // Password
      const char
      deviceName = “YourDeviceName”; // Device Name

      Setup section
      WiFi.softAP(ssid, password); // Acces Point Setup
      delay(150);
      WiFi.softAPConfig(apIP, apGW, apMSK); // Ethernet setup
      delay(200);

      Serial.print(“Configuration du PA … “);
      Serial.println(WiFi.softAP(ssid) ? “Ready” : “Failed!”);

      Serial.print(“Adresse IP du PA = “);
      Serial.println(WiFi.softAPIP());

      Serial.print(“ESP8266 MAC: “);
      Serial.println(WiFi.macAddress());

      // Start Server
      server.begin();

      For more info, see « Kolban’s Book on ESP32 &ESP8266 »,. I used 2016/10 Edition (more than 450 pages to read, but really well done and usefull,

      I’ll hope it will help a little bit and go further in your project,

      Info to Sarah, finaly I succed in managing DHCP.

      Take care All of You.

      Reply
  10. Hello Sara and Rui,
    I establish soft AP + STA mode. First a host device is connected to AP then STA is connected to a router on different channel than AP and after this the host is disconnected from AP.
    Is there a way to send channel switch announcement from AP to host prior changing the channel to keep host connected?
    I run ESP12F with Lua
    Thank you

    Reply
  11. Great tutorial for another highly valuable nodemcu feature.

    I will try it but am a bit ..will it really work as all my previous attempts to run the OTA code transfer on nodemcu did not work at all.

    Pls help with a properly working OTA tutorial.

    Thank you so much for all the articles Sara !!!

    Reply
  12. Dear Sara, with the above tutorial can I browse webpages of google or any other website, like surfing the internet. If i can’t, please how do I achieve it?
    Thank you

    Reply
  13. Very good!!! Just a question, how do I accept temperature with decimal number, example: connect with 25.7 and disconnect in 26.5. Thank you, very good project

    Reply
  14. Hi Sara, when we are connecting to the AP, can we display the password that the user tries to input?
    For example if I want to connect to my AP, I will just open my phone’s wifi settings and enter the password. So in that case if I entered a wrong password, can we just show that wrong password in the serial monitor?

    Reply
    • Hi.
      Since the password is written in the device’s Wi-Fi settings, I don’t know how to get that.
      I’m sorry that I can’t help much.
      Regards,
      Sara

      Reply
  15. Thank you for very well education pages
    Why do I get wrong signs shoving like Centigrade/Celsius will be °C with a letter before °C.

    Reply
  16. I am using IDE 1.8.19 with current esp8266 (3.0.2).
    I copied and pasted the code form above but get an error that states:

    “ESP8266-Access-Point.ino” contains unrecognized characters. If this code was created with an older version of Arduino, you may need to use Tools -> Fix Encoding & Reload to update the sketch to use UTF-8 encoding. If not, you may need to delete the bad characters to get rid of this warning.

    I can not find these “unrecognized characters”.

    Do you have an github with this code ?

    thank You

    Reply
  17. Hello

    I want to open access point ip on web browser automatically at a time my device connected to AP.

    Please help to achieve this without wifi manager library

    Reply
  18. Is there a follow up to this tutorial that changes the access point web page to a configuration page that allows the user to set the SSID and the password of their WiFi network that is connected to the internet?

    Use case: I create a fancy weather station and want to send it to my grandkids. They power on the device. I tell them to connect their wifi to the AP Access WiFI and give them the 123456789 password. Then I tell them to navigate to http://192.168.4.1 so they can enter their own WiFi credentials so I don’t have to hard code theirs in the sketch and if they change the password or SSID I don’t have to have them send it back to me to change the sketch.

    I know there are other sketches that do this, but I’ve already go a lot of time invested in the Ruis code. I don’t want to have to figure out how to meld different codes together.

    Thank you!!

    Reply
  19. ESP8266 libraries 3.0.2 require a softAP password length of at least 8 characters, if not – go to “default” configuration and do not configure DHCP. written in line 112 of ESP8266WiFiAP.cpp. it took me 3 days to find why DHCP does not work

    Reply
  20. Hello Sara,
    I would like to ad a button to switch on and off a GPIO.
    Could you please give me a little help how to do that ?

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.