ESP-NOW gives ESP32 peer-to-peer Wi-Fi without an access point
A connectionless Wi-Fi communication protocol
At a glance
- What is it?
- ESP-NOW is an Espressif component for connectionless Wi-Fi communication between ESP32 devices, supporting one-to-many and many-to-many device connection and control for uses like network configuration, firmware upgrade and debugging. It is distributed through the ESP-IDF component manager rather than as a standalone library, and the examples are the fastest way to understand it.
- Who is it for?
- ESP-NOW fits an ESP32 project that needs devices to exchange short messages directly with each other rather than through a router, and it fits the cases the README names, network configuration, firmware upgrade and debugging, especially where the target device has no Wi-Fi credentials yet. It does not fit a project that needs throughput, guaranteed delivery or a general purpose network, and it does not fit a team that is not already working in ESP-IDF.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 43 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 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What ESP-NOW actually is, in the README's own words
The repository description is one line: a connectionless Wi-Fi communication protocol. Everything else follows from that.
The README states that ESP-NOW supports one-to-many and many-to-many device connection and control, and that it can be used for mass data transmission, like network config, firmware upgrade and debugging.
Read that list of use cases carefully, because it defines the scope better than any feature list would. Network configuration is the canonical case: a device that has no Wi-Fi credentials yet cannot join a network, so something has to hand it the credentials, and ESP-NOW is a way to send them from a device that is already provisioned. Firmware upgrade is the second: pushing a new image to a node without any infrastructure. Debugging is the third, and the topics tags confirm the emphasis with control, debugger, esp32, iot and ota.
The connectionless part is what makes it work. There is no access point, no router and no association step. Devices communicate directly over Wi-Fi radio. That is also the constraint: there is no network path, so there is no IP, no TCP and no guarantee of delivery.
The component is published through the Espressif Component Registry, and the README links a user guide and a Chinese version of it. The primary language is C, the licence is Apache-2.0, and the repository is not archived.
Adding the component goes through the ESP-IDF component manager
There is no git submodule and no copy of a source tree. The component is installed with the ESP-IDF component manager, and the README says to use the add-dependency command to add esp-now to the project's dependency, noting that during the CMake step the component will be downloaded automatically.
idf.py add-dependency "espressif/esp-now=*"The version specifier is a wildcard, which means your build resolves to whatever the registry currently serves for that component. For a production firmware that is a decision you may want to revisit by pinning a version instead, but the README documents the wildcard form and nothing else.
The examples come from the same mechanism, using create-project-from-example.
idf.py create-project-from-example "espressif/esp-now=*:coin_cell_demo/bulb"The example is then downloaded into the current folder, and the README says you can check it in for build and flash. Checking a generated example into your own repository is a deliberate choice worth making, because it freezes the example against future registry changes and lets you diff it when you upgrade.
The component manager, not the component, is what the troubleshooting section is about. The documented failure is CMakeLists.txt not found in project directory, and the documented cause is that an older version of the package manager was used, with the fix being to run pip install -U idf-component-manager in the ESP-IDF environment.
That is a small entry in a Q&A section, and it is the most common thing a new user hits, because the error message points at a missing CMakeLists.txt when the real problem is a stale tool.
Eight examples, and the pair that explains the protocol
The README lists eight examples, and the list is really a map of what ESP-NOW is used for.
The coin_cell_demo has two halves, bulb and switch. The switch is the sender and the bulb is the receiver, and together they are the smallest complete system in the repository. A coin cell powered switch that has no Wi-Fi credentials still needs to send a message, and a battery powered bulb that is meant to last a long time should not hold an association open. Connectionless messaging is a good fit for both.
The control example covers device connection and control. The get-started example is the entry point for the protocol itself. The ota example is firmware upgrade over ESP-NOW. The security example covers securing the channel. The solution example sits alongside it. The wireless_debug example covers the debugging case.
There is also a provisioning directory in the repository listing, which the README's example list does not mention, alongside the eight it does. The README notes you can download the examples from the esp-now repository directly, and links each one.
The ordering of that list is the suggested learning path. get-started, then the coin cell pair, then control, then the harder cases of security and ota. Anyone evaluating this component should read get-started and the coin cell pair first, because the other six examples assume you already understand how a sender is paired with a receiver and how the channel and peer address are set.
What the repository contains beyond the examples
The top level entries show this is a component in the ESP-IDF sense, not a loose library.
There is a CMakeLists.txt, which is how the component manager integrates with an ESP-IDF build, an idf_component.yml declaring the component's metadata, and a Kconfig file, which is how ESP-IDF exposes compile-time configuration options to the project's menuconfig. There is a src directory holding the implementation, and an examples directory with the eight sample projects.
There are two user guides, User_Guide.md and User_Guide_CN.md, linked from the README as the primary documentation. The README itself is deliberately short and points there for the detail, which is the normal arrangement for an Espressif component.
The rest of the repository is the standard set of project infrastructure: a CHANGELOG.md, a SECURITY.md, a LICENSE file, a .gitlab-ci.yml alongside a .gitlab directory and a .github directory for the two CI systems, a .pre-commit-config.yaml, a .codespellrc, and a docs directory.
Two details in that list are worth noting. The presence of both GitLab and GitHub CI configuration reflects how Espressif components are built and mirrored internally. And a SECURITY.md means the project has a published process for reporting vulnerabilities, which for a protocol component handling device communication is a meaningful thing to have rather than a formality.
The release history shows one tagged release, v1.0, dated 2022-03-14, and the last push to the repository was on 2026-09-10. A single v1.0 tag with a much later push history means the component has not had a versioned release in a long time, so anyone depending on it in a shipped product is tracking the default branch.
The tradeoff a connectionless protocol makes
The design decision that defines ESP-NOW is that there is no connection, and everything follows from that choice.
What you get is a device that can send a message to a peer without any infrastructure, without credentials and without a router. For the provisioning case, that is the entire point: the device being provisioned cannot use Wi-Fi yet, so the only way to reach it is over the radio directly.
What you give up is the delivery guarantees that a connection implies. There is no association, so there is no connection state to monitor and no link layer to retransmit on your behalf. A message that does not arrive is simply lost, and the application has to decide whether that matters and what to do about it. The same applies to power: a device that is not associated is not holding a connection open, which is a large part of why the coin cell demo exists at all.
The payload size limit is the other constraint that follows from using the Wi-Fi radio directly rather than going through IP. The README does not state a payload size, and the user guide is where you would look for it, but the design implies the practical limit of a single Wi-Fi frame rather than an IP datagram, and anything larger has to be chunked by the application.
There is also the security question, and the repository is honest that it needs attention. The security example exists precisely because connectionless does not mean unencrypted, and the README links a user guide that covers the details. An ESP-NOW deployment on devices that are physically reachable should not be assumed safe by default.
Where ESP-NOW is the wrong choice
The first limitation is that it only works between ESP32 devices, or more precisely, it is an Espressif component for the ESP-IDF framework. There is no standard Wi-Fi peer to peer mode in a laptop's Wi-Fi chipset, so you cannot test the receiving side from a general purpose machine without an ESP32 acting as a bridge. That is a real constraint on a test setup.
The second is throughput and reliability. Connectionless messaging is not a data channel. If your application needs ordered delivery, retries, acknowledgements or a decent payload size, you are building a protocol on top, and at that point a real network protocol such as TCP over an access point is less work.
The third is the dependency on ESP-IDF itself. The component is installed with idf.py, built with CMake and configured with Kconfig, and the examples are ESP-IDF projects. If your firmware is not on ESP-IDF, this is not a drop-in piece of C you can compile into another framework.
The fourth is the versioning situation. One tag, v1.0 from 2022, with the last push on 2026-09-10, means there is no release stream to pin, no changelog with semantic version history, and no obvious upgrade path between versions. For a component that is Apache-2.0 licensed and maintained by the chip vendor, that is unusual, and it is worth asking about before you depend on it.
The fifth is security, and it is the one to plan around rather than discover later. The presence of a security example and a SECURITY.md tells you the project takes it seriously, and it also tells you that getting it right is your job.
How it compares with Wi-Fi provisioning and Bluetooth
The realistic alternatives for talking to a device that has no network are the ones that already exist in the Wi-Fi and Bluetooth worlds.
Wi-Fi provisioning through SoftAP is the closest alternative and it is the one ESP-NOW competes with directly. With SoftAP, the unprovisioned device runs its own access point, the phone or laptop joins it, and the credentials are transferred over that link. The difference is the radio behaviour: SoftAP has the device listening for an association, ESP-NOW has the device listening for a frame addressed to it. A SoftAP link also has to be torn down afterwards, and while it is up the device is spending power on an access point.
Bluetooth is the other option, and Bluetooth Low Energy is a serious contender for a button-sized device with a coin cell. BLE gives you a connection-oriented link with pairing, bonding and a defined profile layer, at the cost of a stack that is heavier than what ESP-NOW needs for a short message.
ESP-NOW's case is the cases where the message is short, the device is sleepy and the network is not available. The coin cell demo in the repository is exactly that: a switch that must send a small message and then sleep, to a bulb that must not be listening for an association.
Against a cloud IoT service, the comparison is not close. ESP-NOW has no cloud, no account and no fleet management, which is why the debugging and firmware upgrade use cases work at all when the device has never been online. The trade is that you get exactly one primitive, message delivery between peers, and you build everything else on it.
Editorial conclusion
ESP-NOW fits an ESP32 project that needs devices to exchange short messages directly with each other rather than through a router, and it fits the cases the README names, network configuration, firmware upgrade and debugging, especially where the target device has no Wi-Fi credentials yet. It does not fit a project that needs throughput, guaranteed delivery or a general purpose network, and it does not fit a team that is not already working in ESP-IDF. Before adopting, work through the get-started example first, then the coin_cell_demo bulb and switch pair, because that pairing is the smallest complete system in the repository, and read the User_Guide.md for the parts the README does not cover, including the security and OTA examples that show what has to be added before this goes on air.
Frequently asked questions
What is ESP-NOW and what is it used for?
ESP-NOW is a connectionless Wi-Fi communication protocol, distributed as an Espressif component for ESP-IDF. The README says it supports one-to-many and many-to-many device connection and control for mass data transmission such as network config, firmware upgrade and debugging.
How do I add the ESP-NOW component to my ESP-IDF project?
Use the component manager command idf.py add-dependency "espressif/esp-now=*", which downloads the component automatically during the CMake step. Examples are pulled with idf.py create-project-from-example "espressif/esp-now=*:coin_cell_demo/bulb", which downloads the example into the current folder so you can check it in for build and flash.
Which ESP-NOW examples are there and which should I start with?
The README lists coin_cell_demo/bulb, coin_cell_demo/switch, control, get-started, ota, security, solution and wireless_debug, and the repository listing also shows a provisioning directory. The get-started example covers the protocol itself and the coin cell pair is the smallest complete system, so those are the natural starting points.
What should I do if idf.py create-project-from-example reports CMakeLists.txt not found?
The README attributes that error to an older version of the package manager and gives the fix: run pip install -U idf-component-manager inside the ESP-IDF environment, then retry the command.
Is the ESP-NOW component still being maintained?
The repository is not archived and the last push was on 2026-09-10, but it carries a single tagged release, v1.0 from 2022-03-14, so there is no version stream to pin or to upgrade between. The project ships a CHANGELOG.md, a SECURITY.md and two user guides, one in English and one in Chinese.
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/espressif-esp-now)Was this useful?