ESP8266 OTA Updates with Arduino IDE | Over the Air

OTA (Over the Air) update is the process of loading a new firmware to ESP8266 module using WiFi connection rather than a serial communication. This type of functionality is extremely useful in case of no physical access to the ESP module.

Uploading a new sketch wirelessly from Arduino IDE is intended for the following typical scenarios:

  • during firmware development – as a quicker alternative to uploading a new sketch over a serial
  • for updating the firmware of multiple ESPs in your network

If you like the ESP and you want to do more projects you can read my eBook Home Automation using ESP8266.

Let’s get started!

Step #1 – Uploading BasicOTA.ino with serial communication

In order to upload firmware to your ESP8266 wirelessly, you have to upload the BasicOTA.ino sketch example first.

Having the latest Arduino IDE software installed from arduino.cc/en/Main/Software. Follow these next instructions:

1) Connect your ESP8266 to your computer with a USB cable:

2) Go to Tools to select your ESP board model. You also have to choose your ESP’s COM port

3) Open the BasicOTA.ino example: File > Examples > Arduino OTA > BasicOTA.ino or copy the following sketch to your Arduino IDE

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com
  Arduino IDE example: Examples > Arduino OTA > BasicOTA.ino
*********/

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

// Replace with your network credentials
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  // ArduinoOTA.setHostname("myesp8266");

  // No authentication by default
  // ArduinoOTA.setPassword((const char *)"123");

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  ArduinoOTA.handle();
}

View raw code

Note: you have to change the sketch example with your SSID and password.

4) Press the “Upload” button in the Arduino IDE and wait for the “Done uploading” message

5) Open the Arduino IDE serial monitor at a baud rate of 115200. If you’ve entered the right network credentials you should see your ESP IP address after a few seconds:

Step #2 – Uploading a new sketch OTA (Over the Air)

Now your ESP8266 is ready to receive OTA firmware updates. You can unplug your ESP8266 from your computer and power it through any power source (for example a power bank). If your ESP8266 has a wireless connection to your router, you should be fine to upload new firmware.

1) Go to your Arduino IDE. Open Tools tab select the Port option and you should see something like this: esp8266-xxxxxx at your_esp_ip_address

2) Copy the following sketch to your Arduino IDE and upload it to your ESP8266. This sketch blinks the ESP12-E NodeMCU kit built-in LED every second

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com
  Arduino IDE example: Examples > Arduino OTA > BasicOTA.ino
*********/

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

// Replace with your network credentials
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

const int ESP_BUILTIN_LED = 2;

void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  // ArduinoOTA.setHostname("myesp8266");

  // No authentication by default
  // ArduinoOTA.setPassword((const char *)"123");

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  pinMode(ESP_BUILTIN_LED, OUTPUT);
}

void loop() {
  ArduinoOTA.handle();
  digitalWrite(ESP_BUILTIN_LED, LOW);
  delay(1000);
  digitalWrite(ESP_BUILTIN_LED, HIGH);
  delay(1000);
}

View raw code

Note: you have to change the sketch example with your SSID and password.

3) Press the “Upload” button in the Arduino IDE and wait for the “Done uploading” message

4) Your ESP should have it’s built-in LED blinking every second

Wrapping Up

I hope this tutorial was useful. Now, you can have your ESP8266 in a remote location and update its firmware without having physical access to the ESP device.

Do you have any questions? Leave a comment down below.

Thanks for reading. If you like this post probably you might like my next ones, so please support me by subscribing my blog and my Facebook Page.


Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

87 thoughts on “ESP8266 OTA Updates with Arduino IDE | Over the Air”

  1. Hi, Thank you for such a nice tutorial. This looks good if both the ArduinoIDE machine and the esp are within the same LAN (say home wi-fi). If my esp resides at a distant place under a different network, what changes need to be incorporated in the above steps and where, please? Thanks in advance.- Anupam

      • One solution to this is to use a hotspot wifi connection on your phone. Then you can bring your laptop and your phone with you to the remote location.
        Normally, you use a hotspot to access the internet through your carrier but I think this should still work even where there is no coverage for your carrier.

    • To be honest I couldn’t find any Python file that is running during over the updates, but according to the official documentation it’s required Python 2.7 to run the OTA updates.

      • It is definitely running Python because on my system, the upload fails because it can’t find the executable! I posted earlier about this problem and am waiting for a reply.

  2. Thanks for a great addition to ESP8266. I have been wondering how to do OTA change for a long time. It will be useful for my auto lawn sprinkling system that uses a NodeMCU.

  3. Hi Rui, in the second sketch, ESP_BUILTIN_LED variable is defined inside setup and is not known in loop.
    It must be declared as a global variable before setup
    After that, the led blinks !
    Alain

        • I am having the same password problem. The password line ” // ArduinoOTA.setPassword((const char *)”123″);” is commented out, but when I try to open the serial monitor it still prompts for a password. If I type 123 it still says wrong password. I even tried UNcommenting the password line and set it to “abc” to see if I could force it but when I type abc in the password field it still doesn’t accept it. I tried restarting the IDE and still no luck. Anyone have any thoughts?

  4. On compiling the first script, I got an error regarding the ESP_BUILTIN_LED, so I moved its definition to the line before the setup() module.
    The Arduino IDE now sees the new device on the IP address assigned. I selected the new device but when I attempt to load second script via OTA, it fails:
    Sketch uses 238533 bytes (22%) of program storage space. Maximum is 1044464 bytes.
    Global variables use 32881 bytes (40%) of dynamic memory, leaving 49039 bytes for local variables. Maximum is 81920 bytes.
    12:18:37 [ERROR]: No response from device
    12:18:37 [ERROR]: No response from device

    Using Arduino 1.8.0 Hourly Build 2016/12/21 04:34 (Windows) for loading the first script.
    Using the same and Arduino 1.8.0 Hourly Build 2016/12/29 04:25 (Linux) to attempt the OTA load.

  5. Could you explain this type of instruction ? I am lost…
    ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf(“Progress: %u%%\r”, (progress / (total / 100)));
    });
    Thanks,
    Alain

      • Thanks Rui, I understand what it does, it is similar to a software interrupt or callback, but I am lost with the syntax : what is the role of [ ] at the beginning ? maybe to put inside a function name (here, function is anonymous)
        Alain

  6. Hi Rui,

    I have made your sketch and it is blinking at the end, however if i open the serial monitor it is asking “type board password to access its console” how about that, i tried differend passwords but with no effect.
    Does something goes wrong or do i something wrong.

    Regards Ton.

  7. Excellent tutorial, Rui.
    There was one problem on my system. The definition of a constant was not found as valid when the compiler was in the loop portion of the sketch. I had to add this inside the loop in the sketch: const int ESP_BUILTIN_LED = 2;
    That worked. This is a nice capability.
    When I tried to access the serial monitor when the blink program was running, it asked me for a password to access the board. I tried the WiFi password, but that didn’t work. Can you read the board’s serial port when it is running on WiFi?

  8. Just tried using OTA to upload a Weather Station sketch to an ESP-12.
    The process appeared to work – the sketch compiled and wirelessly uploaded and started to run. But it fails to establish the WiFi connection it needs to download weather data. The sketch worked when loaded directly via USB. I presume there is a conflict with the WiFi that is used to transfer the program. Any hints on how to solve this?

    • Stew, did you ever solve your issue? I seem to have a similiar issue. My sketch monitors sensors and initiates a http session to a server to upload the data. When i add the OTA code to the working sketch, it no longer is able to connect to the server to update sensor data. (connection fails). ArduinoOTA definitely conflicts with ESP8266HTTPClient code.

      • Hi Robert –
        Sorry, I abandoned that project a ling time ago. I do hope you can get it working somehow.
        Good luck.

  9. I enjoy your tutorials, they are great (I even bought a couple of your books).
    This time however, I get stuck here::

    1) Go to your Arduino IDE. Open Tools tab select the Port option and you should see something like this: esp8266-xxxxxx at your_esp_ip_address

    I get the IP address through the serial monitor but I can’t see the esp8266–xxxxxx at 192.168.1.x port after uploading the sketch in the Arduino IDE (version 1.6.13).
    I tried two different computers, 3 different ESP, two different IDE versions all with the same results.
    I can run Python 2.7 from Windows 10 through the run command so the path is installed correctly as well.
    I Googled this procedure and it’s not any different from your tutorial, I’m at a loss, it’s as if I am missing a step somewhere…

    • Hi,
      I hope you are doing well!

      I think you might either need to restart your Arduino IDE or check if you have your firewall enabled. That might be blocking the connection…

      Thank you for supporting my work,
      Rui

    • I couldn’t get it to work without installing “Bonjour” – Windows doesn’t have this by default (although you may have installed it with something else historically).

  10. If you are using the wifi part of the ESP (ie. More than just blinking a light) do you have to set up a switch (MQTT/Nodered) to choose updating and running. I saw this somewhere else. This feature would be a great add-on to you Home Automation book ( which I loved).

  11. This sentence: “If your ESP8266 as a wireless connection to your router, you should be fine to upload new firmware.” doesn’t make sense as written. Is there a typo? Maybe it should say “If your ESP8266 HAS a wireless connection to your router…”? But even then, what does that mean? Does the OTA program take care of creating a wireless connection to the router? And my application makes the 8266 into an AP. Once I power up after loading my app, will I still be able to update the app over the air?

    • It was a typo. I’ve fixed it and thanks for letting me know.

      The ESP needs to be in the same network of your computer, otherwise you will not find the ESP in the Arduino IDE.

      Yup, that’s the idea, if you always upload a sketch that is capable of being updated over the air.
      It has to be a sketch with a similar structure as the section: “Step #3 – Uploading a new sketch OTA”

  12. I followed your tutorial, but do not run IDE on Windows but on a MAC. I installed Python 2.7.13 for MAC.
    However, I dont see the proper ESP wifi port. What is the role of Python in this tutorial? Do I miss something or is this project not meant /tested for MAC?

    • If you do a search with an IP scanner in your network, can you see your ESP8266 IP address? (Or with the Arduino IDE serial monitor)

      To be honest I couldn’t find any Python file that is running during over the updates, but according to the official documentation it’s required Python 2.7 to run the OTA updates.

      Note: If OTA port does not show up, exit Arduino IDE, open it again and check if port is there. If it does not help, check your firewall and router settings. OTA port is advertised using mDNS service.

  13. Kinda unrelated, but what would you recommend?

    A Wemos D1 mini or an Amica NodeMCU?

    Both of them cost pretty much the same (ok the Wemos is about 50 cents cheaper, but whatever)

  14. I’ve had problems with this. It uploaded OK and showed in the Serial Monitor that it was connected, but there was subsequently no other option showing under ports only the com port in use.

    Also, if I close and reopen the Serial Monitor there’s no response. It’s the same if I hit the reset on the Node MCU – nothing.

    It appears to be connected to the router as I’. seeing 5c:cf:7f:11:89:05 on IP address 137…

    Any ideas?

  15. how do I add OTA to an existing sketch that doesn’t have it to upload to a sonoff/esp8266? I have an Sonoff/esp8266 that has a sketch on it that has OTA. But I need to change it to a new one. The problem is the new one doesn’t have OTA in the code. How do I add it? I’m totally new to all this as you can probably tell. Thanks!

  16. Seems like a lot of people are running into password issues when trying to open the serial monitor over the air. Anyone have any ideas? I’m on a Mac, running the prerequisite Python and still get a password error every time I try to open the serial monitor. I tried all the obvious passwords, made sure the password line in the sample code is commented out. HELP IS GREATLY APPRECIATED.

  17. As I wasn’t sure whiich of the files Rui had edited (bug fixed), I downloaded and reinstalled the Basic OTA sketch – no problems, it’s connected to the router and the serial monitor works. As before.

    I then downloaded and reinstalled the OTA Blink sketch – no blinking LED and the serial monitor is still demanding a password…

    I think there’s still a problem here Rui…!!!

    NodeMCU board is an ESP12 type, not a 12E – not sure if that makes any difference.

  18. I tried uncommenting the password line, other password, entering with and without “”, eveeything I could think of – then I found two things that may be relevant to this problem, but they’re a bit beyond me…

    github.com/esp8266/Arduino/issues/965

    github.com/esp8266/Arduino/blob/master/doc/ota_updates/readme.md#password-protection

    Rui, can you work out a solution from those and explain it in an undestandable manner?

    Thanks

  19. I get as far as step 3-3 Press the Upload button … and I get the following error:
    java.io.IOException: Cannot run program “python.exe”: CreateProcess error=2, The system cannot find the file specified

    But I have python installed and it is in the path. For example, I can open a CMD window and type python, and it runs. I haven’t modified either of the two sketches other than changing the SSID and password on each of them. Any ideas?

  20. I fixed the Python not found problem. I had to uninstall all previous Python installs. I should have looked at the Path variable before I did this to see what it had in it, maybe a reference to one of the earlier installs. But now it all works – at least with your test app. Now to try it with my own app. This will be great if it work with my app because all my ESP8266’s are inside enclosures and I don’t want to have to open them up every time I update the app.

  21. Fantastic, Rui! I was afraid that I would have problems because my app makes the 8266 an Access Point with no password, while my network connection is a hotspot running on my phone and it has a different SSID and also a password. But DAMN, it all works. I am making and selling ESP8266-powered devices and the 8266’s are in enclosures . I frequently need to update the software, so being able to do this without taking the enclosure apart and hooking up a USB cable is a really nice thing for me. Thanks for the tutorial!

  22. I am having problems now. I run into two different problems. Sometimes the Port list on the Arduino IDE shows a network port and sometimes it only shows COM ports. When it doesn’t, of course I can’t do OTA update. And I can’t figure out how to force the network port to appear in the list.

    So that is problem 1. Why doesn’t the network port appear in the list and how can I force it to? When the network port does appear, the IP address that is part of the port address is always the same: 192.168.43.64. But the IP address that is displayed in the Serial Monitor when I upload the OTA loader often varies. And when the IP in the Port addres does not correspond with the IP displayed in the Serial Monitor, the update fails. But if the IP addresses match, then the update works fine. So I am assuming that the OTA loader saves the IP address it finds and expects the 8266 to always be at that address, which it is not. I don’t know how to get around this one either.

    I should note that since I don’t have a router, I use a hotspot on my phone. I have double checked the SSID and password of the hotspot with those in the OTA loader and they are the same. I guess that is obvious from the fact that it sometimes works.

    Any thoughts?

  23. I am double posting these questions here and on the FB site to get a wider exposure in hopes that I can get this problem solved soon. The problem is that the Arduino IDE does not find and display the network port for the ESP. But from running an IP scanner, I can verify that the port exists and is live. The odd thing is that maybe once in twenty times that I open an instance of the IDE, the port shows up. The rest of the time it does not. Any ideas on this? I posted this problem to the Arduino forum also.

    • I found the solution! I did not find the root problem but I found the solution. Restarting the Bonjour Service is the solution. I do not know why that works but it does. On my Windows 10 machine the Bonjour Service was Running but I restarted it anyway and voila! The ESP appears in the port list! Just thought you would like to know!

      • Too soon! It turns out that restarting the Bonjour Service only worked once –
        ust like other tries at a solution that I thought were the answer! What the hell is going on with this thing?

        • I have a similar problem (I don’t find it even once in 20 times 😛 ) However, if I remove blink code in loop, OTA can be found without any problem. For some reason, adding blink code (4 lines) causes the port not to be found.

          • It is working for me. I changed following line:
            const int ESP_BUILTIN_LED = 2;
            to
            const int ESP_BUILTIN_LED = 1;
            Since in ESP-01 module LED is connected to GPIO1.
            WARNING: THIS WILL DISABLE SERIAL COMMUNICATION WITH ESP. Since GPIO1 is also used as serial line. However, programing with serial port (along with OTA) will still work as putting ESP in program mode will not run sketch & hence GPIO1 becomes free.

    • Hi.
      That means you don’t have the drivers installed in your computer.
      Search for the drivers and install it on your operating system.

    • Arrygon, you’ll see ESP8266 in ports only after you have downloaded the OTA sketch once. First time you need to download this sketch using serial port. Once done, restart your Arduino GUI & you should see ESP8266 in ports. However, before downloading first time using serial, you need to make sure to install the board support package for ESP in Arduino

    • Hi Rick.
      Yes, if you want to be able to upload code over the air in the future, you need to include OTA code in all your sketches.
      Regards,
      Sara 🙂

  24. I had a problem but I found a solution, however crude. I’m posting this in case other users have a similar problem.

    There was an error message when I tried to upload code to esp8266-xxxxxx. The loader espota.py was not found at location …/2.5.0-beta3/espota.py

    The solution: click on Tools -> Board: -> Boards manager. Search for 8266 in upper right search box. One of the choices is esp8266 by ESP8266 community. The version that was already installed was 2.5.0-beta3. I clicked on the Select Version box and selected version 2.5.0-beta2 and updated it. Then it loaded.

    Thanks for a really great tutorial.

  25. Do you have a tutorial (or a tweak to this tutorial) that addresses configuring the WeMos “ATmega2560 ESP8266 CH340G” board for OTA? In particular, when to use the USB ESP8266 (firmware) switch settings vs. the USB ESP8266 (work) switch settings.

    Or, does ArduinoOTA even work with the WeMos board?

    The WeMos board is available here: banggood.com/Wemos-Mega-WiFi-R3-ATmega2560ESP8266-32Mb-Memory-USB-TTL-CH340G-Compatible-For-Arduino-Mega-p-1205437.html?cur_warehouse=CN

    The identical RobotDyn board is available here: robotdyn.com/mega-wifi-r3-atmega2560-esp8266-flash-32mb-usb-ttl-ch340g-micro-usb.html

    • Hi Ron.
      I don’t have any tutorial about what you’re looking for. Also, I’m not familiar with those boards.
      I’m sorry that I can’t help much.
      If anyone here knows something about this topic, please share.

      Regards,
      Sara

  26. hi
    thank you for your sharing
    does it possible to do with gsm modem for example upload code on sim800l or sim808 with atmega328p?

    Best Regards

  27. I had a novel problem that might help others. The OTA BLINK sketch always worked: the network port showed up, and I was able to reflash. The same exact code in my program (in the same places) almost never showed the network port. Background: after setup() I run a 5 minute routine and then go into a lower-power mode (not Deep-sleep) for 30 minutes, and then the main loop starts again with turning the WiFi on since it just came out of low-power mode. Once I moved all of the OTA initialization AFTER that WiFi re-enable in loop(), everything worked. I tried simply moving the ArduinoOTA.begin() and ArduinoOTA.handle() after the WiFi re-enable, but that wasn’t enough. I guess you need to run the entire OTA initialization any time the WiFi has been re-enabled or re-configured. Of course the OTA can’t run with the WiFi in WiFi.forceSleepBegin(), but that’s OK. I can always power cycle it or hit it with RST to restart the 5 minute routine if I don’t want to wait for the loop to restart.

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.