ElegantOTA: a firmware update web portal in three lines
The original over-the-air update library for wireless microcontrollers (since 2019).
At a glance
- What is it?
- ElegantOTA gives an ESP32, RP2040 or ESP8266 a browser-based over-the-air update page at /update, with a capacity check, MD5 verification and optional HTTP Basic auth, and it integrates in three lines of C++. The catch is the AGPL-3.0 licence and a hard flash-partition requirement on the Pico boards.
- Who is it for?
- Adopt ElegantOTA if you ship a WiFi microcontroller and want a firmware update path that does not need a cloud service, a second app on the phone, or any HTML work on your part, and if you are prepared to satisfy the AGPL-3.0 terms. Do not adopt it if your product is closed source, since the Pro tier exists precisely for a commercial licence, and do not skip the flash layout step on the Pico boards.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 48 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The update mechanism is a web page on the device itself
ElegantOTA is an over-the-air update library for wireless microcontrollers, described as the original one, in use since 2019. The mechanism is deliberately plain. The device hosts a small web server, and one of its routes serves an update portal. You point a browser at the device address with the /update path, choose a .bin file, and the library writes it to flash while showing live progress, a transfer rate and byte counts. There is also a filesystem update path, so the same portal handles a filesystem image as well as firmware. The design decision worth naming is that the device is the server. There is no account, no dashboard and no vendor backend, which is the whole appeal for a maker or a small product team, and also the reason the security story is entirely yours to own. The project describes the payload as a .bin, and it is a C++ library, so the target is a firmware project that already has a web server running.
No HTML, no CSS, no JavaScript on your side
The pitch in the project's own words is three lines of code, with no HTML, CSS or JavaScript to write. What the library actually contributes is a self-contained portal: a page with light and dark themes, keyboard reachable, and readable down to a width of 320px. The library ships the markup and styling itself so that the integrator does not have to assemble a form, handle a multipart upload or render a progress bar. The features list adds the parts that usually break naive implementations. There is a capacity check up front, so an oversized build is rejected before it half-writes rather than after. There is MD5 integrity verification on the uploaded image. There is optional HTTP Basic auth on the portal, which matters because the update route is otherwise open to anyone on the same network. The practical read is that the three-line claim is about your integration effort, not about the total amount of functionality being handled for you.
Supported boards, and the LittleFS partition the Pico needs
The supported hardware table is short and specific. ESP32 is listed first, including the S2, S3, C3 and C6 variants. RP2040 with WiFi is supported, for example the Raspberry Pi Pico W, and it requires a LittleFS partition. RP2350 with WiFi is also supported, for example the Pico 2 W, and it has the same LittleFS requirement. ESP8266 is listed as legacy, still maintained, with new projects steered towards ESP32 or RP2350. The partition note is the part that will bite you. The important callout explains that RP2040 and RP2350 boards stage the incoming image inside the filesystem region, so a LittleFS partition is mandatory, and in the Arduino IDE you pick Tools > Flash Size > 2MB (Sketch 1MB, FS 1MB) or a similar layout. A board without a WiFi chip cannot run the library at all, since the update portal is served over the network.
Installing it: the Arduino IDE menu or a PlatformIO block
There are two documented install routes. In the Arduino IDE you use Sketch > Include Library > Manage Libraries, search for ElegantOTA, and install it. For PlatformIO the project asks for a specific version and, importantly, a compatibility mode setting, because the library supports several architectures and PlatformIO would otherwise try to resolve dependencies for all of them and produce build errors:
lib_deps =
ayushsharma82/ElegantOTA@^4.0.0
; ElegantOTA supports several architectures, and PlatformIO will otherwise try
; to resolve dependencies for all of them. Without this you will hit build errors.
lib_compat_mode = strictIf a .pio/libdeps folder already exists from an earlier build, the documentation says to delete it before rebuilding. The repository root carries the files that make the library installable in both ecosystems: library.json, library.properties, platformio.ini and platformio_upload.py, alongside the src/ directory that holds the implementation and the examples/ directory with the Demo and AsyncDemo sketches. The current release is 4.0.0 and the last push to the repository was on 2026-09-05.
The three lines are an include, a begin and a loop call
The quick start sketch shows the whole integration, and it is short enough to read closely. The library is included as a header, ElegantOTA.begin is called with a pointer to your web server, and ElegantOTA.loop is called from the main loop:
#include <WiFi.h>
#include <WebServer.h>
#include <ElegantOTA.h> // 1
WebServer server(80);
void setup() {
WiFi.mode(WIFI_STA);
WiFi.begin("ssid", "password");
while (WiFi.status() != WL_CONNECTED) delay(500);
server.on("/", []() {
server.send(200, "text/plain", "Hi! This is ElegantOTA Demo.");
});
ElegantOTA.begin(&server); // 2
server.begin();
}
void loop() {
server.handleClient();
ElegantOTA.loop(); // 3
}Note the ordering: your own routes are registered before the library takes the server, and the server is started last. Once the sketch is running, opening http://<device-ip>/update in a browser gives you the portal. The three marked lines are the entire integration surface, and the surrounding lines are the ordinary boilerplate of a WiFi web server sketch.
Async mode is a build flag, and the two servers cannot coexist
ElegantOTA can serve its routes through ESPAsyncWebServer rather than the built-in synchronous server. In PlatformIO this is enabled with a build flag, and in the Arduino IDE, which has no way to set build flags, you edit ELEGANTOTA_USE_ASYNC_WEBSERVER directly in src/ElegantOTA.h:
build_flags = -D ELEGANTOTA_USE_ASYNC_WEBSERVER=1The constraint that follows is stated plainly: you cannot run the synchronous WebServer and ESPAsyncWebServer in the same firmware, so you pick one. That matters for anyone porting an existing sketch, because the choice is not only a flag but an architectural decision about which server object owns the routes. The documentation points to the async mode guide for the per-platform TCP dependencies, which is where the platform-specific parts live. The examples directory holds both shapes, with Demo.ino for the synchronous webserver and AsyncDemo.ino for ESPAsyncWebServer, so the two variants can be compared side by side rather than guessed at.
The upgrade path: AGPL-3.0 now, a commercial licence later
ElegantOTA Lite covers a project end to end, and the paid tier exists for what a shipped product tends to need. The Pro version adds two extra OTA modes, Direct Download where the device fetches firmware from a URL itself, and Auto Update using update channels, plus the ability to toggle OTA modes at runtime, hardware ID and firmware version shown on the UI, whitelabel branding, and a commercial licence. The licensing of the free version is the practical obstacle for a commercial product. The repository is licensed AGPL-3.0, and the Pro tier is the route the project itself points at when a commercial licence is needed. That is a legal question rather than a technical one, but the practical effect is architectural: if you build a device that ships to customers, the licence choice for the OTA component is a decision you have to make before you wire the portal into the product, not after. The other upgrade cost is platform migration. The board table is explicitly steering new work away from ESP8266, and the synchronous to async move is a rewrite of the server setup, so a long-lived product should settle both early.
Editorial conclusion
Adopt ElegantOTA if you ship a WiFi microcontroller and want a firmware update path that does not need a cloud service, a second app on the phone, or any HTML work on your part, and if you are prepared to satisfy the AGPL-3.0 terms. Do not adopt it if your product is closed source, since the Pro tier exists precisely for a commercial licence, and do not skip the flash layout step on the Pico boards. Before you start, pick the board and check the partition scheme, because RP2040 and RP2350 need a LittleFS partition of the kind labelled 2MB (Sketch 1MB, FS 1MB) in the Arduino IDE, and decide whether you will run the synchronous WebServer or ESPAsyncWebServer because the two cannot coexist in one firmware.
Frequently asked questions
Which microcontrollers does ElegantOTA support?
The documented list covers ESP32 including the S2, S3, C3 and C6 variants, RP2040 with WiFi such as the Raspberry Pi Pico W, RP2350 with WiFi such as the Pico 2 W, and ESP8266, which is marked legacy and still maintained.
Do I need a LittleFS partition on a Raspberry Pi Pico?
Yes for RP2040 and RP2350 boards. They stage the incoming image inside the filesystem region, so a LittleFS partition is mandatory, and in the Arduino IDE you select a layout such as 2MB (Sketch 1MB, FS 1MB) under Tools > Flash Size.
How do I install ElegantOTA in PlatformIO?
Add `ayushsharma82/ElegantOTA@^4.0.0` to lib_deps and set lib_compat_mode = strict, because without it PlatformIO tries to resolve dependencies for every supported architecture and the build fails. Delete any existing .pio/libdeps folder before rebuilding.
Can ElegantOTA and ESPAsyncWebServer be used together?
You pick one server per firmware. The synchronous WebServer and ESPAsyncWebServer cannot run in the same build, and async mode is switched on with the build flag ELEGANTOTA_USE_ASYNC_WEBSERVER=1, or by editing src/ElegantOTA.h in the Arduino IDE.
Is ElegantOTA free for a commercial product?
The repository is licensed AGPL-3.0, and the paid Pro tier lists a commercial licence among its features, along with Direct Download and Auto Update modes. Which terms fit your product is a legal question to settle before you ship.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ayushsharma82-elegantota)Was this useful?