Learn how to set up Multicast DNS (mDNS) on your ESP32 programmed with the Arduino IDE. mDNS lets you refer to your ESP32 using a user-friendly name instead of its IP address. For instance, instead of having to type the ESP32 IP address to access a web server in your browser on your local network, you can simply use something like http://esp32.local.

What is mDNS?
mDNS, or Multicast DNS, allows you to assign specific names to devices on your local network, each associated with its specific IP address. This way, you can refer to them via that name instead of the IP address.
mDNS for the ESP32
This way, instead of having to remember the specific IP addresses of several of your ESP32 boards on your network, you can simply give a name to each of them, for example esp32-room, esp32-lights. Then, you can access them on your network using http://esp32-room.local, for example, instead of having to memorize or write down the specific IP address for each board.
How to Set Up mDNS on an ESP32 (Arduino IDE)?
Setting up mDNS on an ESP32 programmed with Arduino IDE is quite simple and only requires you to add a few lines to your existing code.
1) First, include the ESPmDNS library.
#include <ESPmDNS.h>
2) In the setup() of your code, after connecting to your network, set mDNS using the following lines. Pass the hostname you want to the begin() function—the one that will be used in the URL when you access an ESP32 web server.
if (!MDNS.begin(mdnsName)) {
Serial.println("Error setting up MDNS responder!");
while(1) {
delay(1000);
}
}
3) Finally, advertise your ESP32’s HTTP web service (on TCP port 80).
MDNS.addService("_http", "_tcp", 80);
ESP32 Web Server with mDNS
To show you how to implement mDNS, we’ll show you a basic “Hello World” web server with this feature implemented.
To access this web server on your browser, instead of having to type your ESP32 IP address, you can type http://myesp32.local
Here’s the example code.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-mdns-arduino/
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.
*/
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// mDNS name (customize this as needed)
const char* mdnsName = "myesp32";
// Create a web server object
WebServer server(80);
// Function to handle the root URL
void handleRoot() {
String html = "<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">";
html += "<link rel=\"icon\" href=\"data:,\">";
html += "<style>";
html += "body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: white; color: #333; margin: 20px; }";
html += "h1 { color: #4a5568; font-weight: 300; }";
html += "</style></head>";
html += "<body>";
html += "<h1>Hello World</h1>";
html += "<p>ESP32 mDNS Demo.</p>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void setup() {
Serial.begin(115200);
// Connect to Wi-Fi network
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Set mDNS
if (!MDNS.begin(mdnsName)) {
Serial.println("Error setting up MDNS responder!");
while(1) {
delay(1000);
}
}
// Add service to MDNS-SD
MDNS.addService("_http", "_tcp", 80);
Serial.println("mDNS responder started. Access your ESP32 at http://" + String(mdnsName) + ".local");
// Set up the web server to handle route
server.on("/", handleRoot);
// Start the web server
server.begin();
Serial.println("HTTP server started");
}
void loop() {
// Handle incoming client requests
server.handleClient();
}
How Does the Code Work?
To keep things simple, we’re creating the web server using the ESP32 core’s built-in WebServer library.
#include <WebServer.h>
We already explained in great detail how to build simple web servers using that library in the following tutorial:
So, we’ll just explain the relevant parts of the code for this tutorial.
Including the mDNS Library
As we mentioned previously, you need to include the ESPmDNS library.
#include <ESPmDNS.h>
Network Credentials
Insert your network credentials on the following lines so that the ESP32 can connect to your local network.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
mDNS Hostname
Add your desired hostname. In our case, we’re calling it myesp32, but you can give a different name.
const char* mdnsName = "myesp32";
Set Up mDNS
In the setup(), after initializing Wi-Fi and printing the board’s IP address…
// Connect to Wi-Fi network
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
…We set mDNS using the following lines of code:
// Set mDNS
if (!MDNS.begin(mdnsName)) {
Serial.println("Error setting up MDNS responder!");
while(1) {
delay(1000);
}
}
// Add service to MDNS-SD
MDNS.addService("_http", "_tcp", 80);
Serial.println("mDNS responder started. Access your ESP32 at http://" + String(mdnsName) + ".local");
And that’s it. You can use this method for any of your IoT projects.
Demonstration
Upload the previous code to your ESP32 board. Then, open the Serial Monitor at a baud rate of 115200 and press the ESP32 RST button so that it starts running the code.
It will print the board IP address and the link to access the web server using the hostname you’ve given in the code. In my case, I’ll access the ESP32 web server at http://myesp32.local.

Open a browser on your local network, and type http://myesp32.local, or any other name you’ve given (you need to add the .local at the end), and you should get access to the web server.

This is just a simple web server for testing purposes, but this can be applied to any other web servers, web apps, and so on.
Multiple Devices with Same Hostname
When using the ESPmDNS library, if you give the same hostname as a device that already exists on the local network, the library will automatically handle that and add a suffix to the name. For example, if esp32.local already exists, it will rename it to esp32-2.local, and so on. The library does this in the background.
To know what the actual hostname given to the device is, we need to use more low-level functions like mdns_hostname_get() included in the mdns.h library from ESP-IDF.
The following code is similar to the previous example, but it uses the mdns_hostname_get() function to get the actual hostname given to the device. This is useful if you happen to mistakenly give the same hostname to multiple devices or if there is already another device with the same name on the network.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-mdns-arduino/
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.
*/
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <mdns.h> // For low-level mDNS functions from ESP-IDF
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// mDNS name (customize this as needed)
const char* mdnsName = "myesp32";
// Create a web server object
WebServer server(80);
// Function to handle the root URL
void handleRoot() {
String html = "<!DOCTYPE html><html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">";
html += "<link rel=\"icon\" href=\"data:,\">";
html += "<style>";
html += "body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: white; color: #333; margin: 20px; }";
html += "h1 { color: #4a5568; font-weight: 300; }";
html += "</style></head>";
html += "<body>";
html += "<h1>Hello World</h1>";
html += "<p>ESP32 mDNS Demo.</p>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void setup() {
Serial.begin(115200);
// Connect to Wi-Fi network
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Set mDNS
if (!MDNS.begin(mdnsName)) {
Serial.println("Error setting up MDNS responder!");
while(1) {
delay(1000);
}
}
delay(5000);
// Add service to MDNS
MDNS.addService("_http", "_tcp", 80);
// Retrieve and print the actual (resolved) hostname - checking if there are any conflicts in the network
char actualHostname[MDNS_NAME_BUF_LEN]; // MDNS_NAME_BUF_LEN is 64 from mdns.h
esp_err_t err = mdns_hostname_get(actualHostname);
if (err == ESP_OK) {
String actualName = String(actualHostname);
Serial.println("mDNS responder started. Given name: " + String(mdnsName));
Serial.println("Current hostname: http://" + actualName + ".local");
if (actualName != mdnsName) {
Serial.println("Hostname renamed.");
}
} else {
Serial.println("Failed to retrieve current hostname (error: " + String(err) + ")");
}
// Set up the web server to handle route
server.on("/", handleRoot);
// Start the web server
server.begin();
Serial.println("HTTP server started");
}
void loop() {
// Handle incoming client requests
server.handleClient();
}
How Does the Code Work?
In this code, we include the mdns.h library from ESP-IDF.
#include <mdns.h> // For low-level mDNS functions from ESP-IDF
After setting up mDNS on the ESP32, we use the mdns_hostname_get() function to get the actual hostname given to the device.
// Retrieve and print the actual (resolved) hostname - checking if there are any conflicts in the network
char actualHostname[MDNS_NAME_BUF_LEN]; // MDNS_NAME_BUF_LEN is 64 from mdns.h
esp_err_t err = mdns_hostname_get(actualHostname);
if (err == ESP_OK) {
String actualName = String(actualHostname);
Serial.println("mDNS responder started. Given name: " + String(mdnsName));
Serial.println("Current hostname: http://" + actualName + ".local");
if (actualName != mdnsName) {
Serial.println("Hostname renamed.");
}
} else {
Serial.println("Failed to retrieve current hostname (error: " + String(err) + ")");
}
Testing the Code
To test this code, you need to keep the previous code running on another board. Then, upload this new code to a different board.
Since we’re trying to use the myesp32 hostname that was already taken by the previous device, the library will automatically change the hostname to myesp32-2.

In the same way, you can access the web server on http://myesp32-2.local on your web browser.

Wrapping Up
In this tutorial, you learned how to use and set up mDNS on your ESP32 boards programmed with Arduino IDE. mDNS allows you to assign specific hostnames to your devices on your local network. This way, you can refer to them using the hostname, which is more user-friendly, rather than the IP address.
Using the mDNS.h library, it is quite easy to add this feature to your ESP32 web server projects.
We hope you’ve found this tutorial useful.
Learn more about the ESP32 with our resources:




Lovin’ this tutorial. I did not come across mDNS ever until you published this. I will have to try it asap on my CO2 Sensor which already runs a webserver! No more checking the IP address of the sensor! Thanks folks!!!
I believe mDNS responder is included with the OTA library, so if you implement OTA, you get mDNS without additional code.
mDNS has never worked for me using any code on any board.
That is true for my Windows 10 laptop as well, doesn’t resolve the mDNS propagated. On my Windows 11-machine and an Android-15-phone everything worked fine (names myesp32 and myesp32-2 auto-negotiated and reachable). See my other post further down for details of my test setup.
The example uses the wifi library exported by “WiFi.h”. This library already provides a function for setting a dns hostname,
for example:
WiFi.setHostname(“esp32_aa_bb”);
So my question is:
why to use the extra library “mdns.h”?
The only reason to use “mdns.h” is for service decoration like in your example:
MDNS.addService(“_http”, “_tcp”, 80);
For my taste that is only a small advantage.
I tested the dns stuff with both libraries exports “wire.h” and “mdns.h” in combination with the DNS-Server from pihole.
My experience:
The wire.h name setting function brought the most reliable results.
I am curious of other user experiences.
One thought: I guess setting the hostname in wifi.h will not check for duplicates. Specifically when using the same esp32-setup multiple times (in my case multiple CO2 sensors) the auto-generated postfix created by mDNS.h to avoid duplicates would be a great benefit… I’ll try both in my setup…
To not generate duplicates as it is error prone i setup an unique hostname that contains the class of esp32-device as prefix and the unique build-in mac address as trailor.
I totally agree. I use a prefix with the last 2 bytes of the mac (i.e: C3_96CB). In hundreds of units, I’ve yet to hit a dupe.
A good option I will keep in mind – I was generating a random number, not thinking about using a piece of the MAC which definitely is easier. However… you still have to somehow know the MAC address and cannot guess it… so, only limited benefit over looking up the IP that was assigned (which, unlike the MAC, can of course change in a DHCP environment so the hostname_MAC is still a better option). Anyhow, I am starting to become a fan of mDNS… see my other post.
I really had to try it (and succeeded before midnight local time…). Conclusion:
a) Trying with Espressif Framework 2 in VSCode partially worked… ChatGPT helped integrating it into my existing code right away but under Framework 2 the established mDNS name could not be read back (function does not seem available? Or maybe has a different name). However, it was another ChatGPT disappointment as it explicitely logged to browse randomnerdtutorials (kudos to this webpage) but did not come up with a solution and did not ask for the Framework version installed, which seems to be relevant.
b) Knowing all examples on RNT here are based on FW3 I went to good old ArduinoIDE 2.3.4 and switched it to Espressif Framework 3.1.0. The sample script above still failed at ‘char actualHostname[MDNS_NAME_BUF_LEN];’ but with a “manual” declaration of ‘char actualHostname[64];’ it compiled without other changes and installed on a 3.5-inch CYD and an old Wroom-Devkit. c) outcome: the ESP-boards properly negotiated for ‘myESP32’ and ‘myESP32-2’ regardless of Framework Version used, maybe there is just no way in the (outdated) Framework 2 to find out the negotiated name. My yet-to-be-upgraded Windows-10 Laptop was totally ignorant and did not find the ESP webpages under those mDNS-names. On Windows 11 and and Android 15 the ESPs were reachable under the mDNS names. Lessons learned: I am still very fond of using this mDNS solution in my projects but should finally move to Framework 3 in VSCode to be able to read back the negotiated mDNS name… nevertheless: guessing the CO2-sensors could be named like “CO2”, “CO2-2” or “CO2-3” instead of explicitely knowing the dynamic IP or part of the MAC-address (or how ever a unique hostname was constructed) is a lovely solution! Of course, any programmatic/scripted access to the sensors still would want to use a stable hostname (e.g. based on the MAC as proposed in other feedback) as with mDNS and naming conflicts you could not really know which sensor got the -2, -3 suffix… but for casual browser-access to the sensors through the mDNS-Name without any static configuration it is good enough. Thanks again for this inspiring tutorial. ChatGPT will yet have to steal this solution from here! Still have to find out why my environment doesn’t like to resolve MDNS_NAME_BUF_LEN despite FW3 and proper includes.
This is a nice idea that will improve with time as more browsers support .local.
I’d like to suggest using WiFiManager by tzapu. It eliminates the need to hardcode WiFi credentials.