Protocols
CoAP protocolo: REST sobre UDP que cabe en 8 KB de RAM
CoAP (RFC 7252) lleva GET/POST/PUT/DELETE a dispositivos con 8 KB de RAM sobre UDP. Aprende cómo funciona Observe, DTLS
Official spec ↗CoAP protocolo: REST sobre UDP que cabe en 8 KB de RAM
MQTT dominates continuous telemetry. HTTP dominates APIs. CoAPCTermCoAPCoAP (Constrained Application Protocol) is a REST-like web protocol over UDP for highly constrained devices, defined in IETF RFC 7252.View profile fills the space neither of them can cover well: devices with 8-64 KB of RAM, multi-year battery life, networks with 10-20% packet loss, and the need for a request/response model like REST — not pub/sub.
If you're designing firmware for a low-end MCU and HTTP feels too heavy while MQTTProtocolMQTTThe standard pub/sub protocol of IoTView profile feels too stateful, the CoAP protocol (Constrained Application Protocol) is the RFC you need to read.
Executive summary
- CoAP (Constrained Application Protocol) is a specialized web transfer protocol for constrained nodes, defined in RFC 7252 by the IETF in 2014 (accessed: 2026-05).
- It runs over UDP (not TCP), with a header of just 4 bytes. The target MTU is 1280 bytes (IPv6), with its own fragmentation via Blockwise Transfer (RFC 7959).
- It mirrors HTTP REST: the GET, POST, PUT, DELETE methods plus analogous response codes (2.01 Created, 4.04 Not Found, and so on).
- Observe (RFC 7641): a client can subscribe to a resource and receive notifications when it changes — similar to pub/sub, but with no broker.
- Security: DTLS (Datagram TLS) over UDP for authentication and encryption.
- Reference implementations: Eclipse Californium (Java, server/proxy side) and libcoap (C, embedded and server) (accessed: 2026-05).
- Don't use it when: you need pub/sub at scale (use MQTT), the device has more than 256 KB of RAM and stable connectivity (use HTTP/2), or you need reliable multicast with guaranteed QoSMTermMQTT QoSMQTT QoS (Quality of Service) defines a message's delivery guarantee at three levels: 0 (at most once), 1 (at least once) and 2 (exactly once).View profile.
What CoAP is and what it's for
CoAP grew out of an obvious observation: the cheapest, lowest-power IoTITermIoT (Internet of Things)The IoT (Internet of Things) is the network of physical objects with sensors, software and connectivity that collect and exchange data and act autonomously.View profile devices — temperature sensors, simple actuators, energy meters — can't run HTTP. Not because HTTP is conceptually complex, but because its text headers, the overhead of TCP (handshake, flow control, retransmissions), and the memory footprint of standard TLS stacks exceed the available resources.
The IETF formed the CoRE (Constrained RESTful Environments) working group in 2010 to solve exactly this problem. The result was RFC 7252, published in June 2014.
CoAP is part of the broader ecosystem of IoT protocols that Plataforma IoT covers. Understand the rest of the IoT ecosystem to put into context where it fits.
How CoAP works
Message structure
A CoAP message has four mandatory fields in the header (4 bytes total):
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Ver| T | TKL | Code | Message ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Token (if any, 0-8 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options (if any) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1 1 1 1 1 1 1 1| Payload (if any) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- Ver (2 bits): version (always 1).
- T (2 bits): message type — CON (Confirmable), NON (Non-confirmable), ACK, RST.
- TKL (4 bits): Token length.
- Code (8 bits): method (0.xx) or response code (2.xx–5.xx).
- Message ID (16 bits): for deduplication and ACK.
Message types
CoAP defines four types that handle reliability over UDP:
| Type | Description |
|---|---|
| **CON** (Confirmable) | Requires an ACK. If none arrives, it retransmits with exponential backoff. The equivalent of "guaranteed delivery" over UDP. |
| **NON** (Non-confirmable) | Fire-and-forget. For telemetry where losing a data point is acceptable. |
| **ACK** | Acknowledgment of a CON. Can carry the response piggybacked. |
| **RST** | Rejects a message — the receiver can't process the CON/NON. |
Methods and response codes
The methods are semantically identical to HTTP:
| CoAP method | HTTP equivalent | Use |
|---|---|---|
| GET | GET | Read a resource |
| POST | POST | Create/process |
| PUT | PUT | Idempotent update/create |
| DELETE | DELETE | Delete a resource |
Response codes follow the c.dd scheme: 2.01 Created, 2.05 Content, 4.04 Not Found, 5.00 Internal Server Error. Familiar to anyone who knows HTTP, but compressed into a single byte.
Observe (RFC 7641): notifications without a broker
The Observe extension turns CoAP into a reactive system with no need for a broker. A client sends a GET with the Observe=0 option (subscribe). The server registers the client and sends it notifications on every change to the resource.
Client Server (sensor)
|---GET /temperatura Observe:0--->|
|<--2.05 Content Observe:1 21.3--| # initial state
|<--2.05 Content Observe:2 21.7--| # temperature changes
|<--2.05 Content Observe:3 22.1--|
|---GET /temperatura Observe:1--->| # cancel subscriptionThe client can cancel by sending a GET with Observe=1, or simply by ignoring the notifications until the server expires them (via timeout or RST).
Security with DTLS
CoAP without encryption exposes payloads in the clear — unacceptable in production. DTLS (Datagram TLS) provides authentication and encryption over UDP, using the same handshake model as TLS but adapted for datagrams.
The four CoAP security modes are:
- NoSec: no security (lab/closed LAN only).
- PreSharedKey: pre-shared key, low overhead, suitable for a fleet of known devices.
- RawPublicKey: public key without an X.509 certificate, reduces handshake size.
- Certificate: full X.509, maximum security, highest overhead.
For very constrained devices (8-32 KB RAM), PreSharedKey with DTLS 1.2 is the usual sweet spot. The article on IoT security covers the threat model in detail.
Real-world use cases
| Sector | Concrete example |
|---|---|
| **Smart metering** | Water/gas meters with a 32 KB RAM MCU and 6LoWPAN. CoAP GET /reading with Observe to push data. |
| **Building automation** | BACnet/CoAP sensors in HVAC; actuators accept PUT /setpoint with the new temperature value. |
| **Precision agriculture** | LoRa+CoAP-over-UDP nodes in the field; they report every 15 minutes via NON (no acknowledgment needed). |
| **Industrial wearables** | Vibration sensors on EPC32/nRF with CoAP over 6LoWPAN BLE; data to the gateway every 5 s. |
| **Academic sensor networks** | TinyOS and Contiki have supported CoAP since 2012; a large research base. |
The ESP32 with the libcoap library supports CoAP natively. The memory footprint of libcoap in client mode is under 20 KB of flash and 4 KB of RAM — perfectly manageable even on ESP32HardwareESP32Dual-core WiFi + BT/BLE SoC at €-tier priceView profile-C3 or ESP32-H2 variants.
When NOT to use CoAP
CoAP isn't the universal tool some tutorials make it out to be:
If you need pub/sub at scale, use MQTT. CoAP Observe works well with dozens of clients per resource. With thousands of subscribers, the notification logic on the server gets complicated; MQTT with a Mosquitto/EMQXETermEMQXEMQX is a highly scalable open-source MQTT broker (written in Erlang) for IoT production, with clustering and multi-protocol support.View profile broker scales better.
If the device has enough RAM and a stable network, HTTP/2 is more interoperable. An ESP32 with 520 KB of SRAM can run a lightweight HTTP stack. The overhead difference between CoAP and HTTP becomes marginal if you have no battery or bandwidth constraints.
If you need robust end-to-end delivery guarantees over very noisy networks, MQTT QoS 2 with a broker that persists messages is more mature than CON CoAP plus manual retransmissions.
Without DTLS support in the stack, don't use CoAP in production. NoSec CoAP over UDP is trivially interceptable. If the firmware can't fit DTLS, check whether you can move security to the network layer (VPN, LoRaWAN
ProtocolLoRaWANOpen long-range, low-power LPWANView profile with an AppSKey).
CoAP vs MQTT vs HTTP
| Aspect | CoAP | MQTT | HTTP |
|---|---|---|---|
| Model | Request/Response + Observe | Pub/Sub | Request/Response |
| Transport | UDP | TCP | TCP |
| Header | 4 bytes | 2 bytes (fixed) | Variable (text, ~200-800 B) |
| Broker required | No | Yes | No |
| Reliability | CON/NON (own layer) | QoS 0/1/2 (TCP + broker logic) | TCP |
| Multicast | Yes (NON over UDP multicast) | No | Not standard |
| Minimum RAM | ~8 KB | ~32 KB (with TCP stack) | ~64 KB (with TLS) |
| REST interoperability | High (HTTP-analogous methods) | Low (requires adaptation) | High |
CoAP is the natural choice when: the radio is 6LoWPAN6Term6LoWPAN6LoWPAN (IPv6 over Low-Power Wireless Personal Area Networks) is a standard that adapts IPv6 to low-power networks over IEEE 802.15.4. It is the basis of Thread.View profile (Thread/ZigbeeProtocolZigbeeVeteran 2.4 GHz mesh — backbone of many smart home hubsView profile IP), the device can't maintain TCP, and the access pattern is request/response or Observe with few clients.
Getting started: CoAP on the ESP32 with libcoap
1. Add libcoap to your ESP-IDF project
# In your ESP-IDF project directory
idf.py add-dependency "espressif/coap==4.3.5"Or add it directly in idf_component.yml:
dependencies:
espressif/coap: "^4.3.5"2. Minimal CoAP server (ESP32, C)
#include "coap3/coap.h"
static void hnd_get_temperatura(coap_resource_t *resource,
coap_session_t *session,
const coap_pdu_t *request,
const coap_string_t *query,
coap_pdu_t *response) {
float temp = read_sensor_temperature(); // your function
char buf[16];
snprintf(buf, sizeof(buf), "%.1f", temp);
coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
coap_add_data(response, strlen(buf), (uint8_t *)buf);
}
void app_main(void) {
coap_context_t *ctx = coap_new_context(NULL);
coap_address_t addr;
coap_address_init(&addr);
addr.addr.sin.sin_family = AF_INET;
addr.addr.sin.sin_port = htons(5683); // standard CoAP port
coap_endpoint_t *ep = coap_new_endpoint(ctx, &addr, COAP_PROTO_UDP);
coap_resource_t *r = coap_resource_init(
coap_make_str_const("temperatura"), 0);
coap_register_handler(r, COAP_REQUEST_GET, hnd_get_temperatura);
coap_add_resource(ctx, r);
while (1) {
coap_io_process(ctx, 1000); // process events for 1 s
}
}3. CoAP client from the LAN (using coap-client)
# macOS / Linux (install libcoap-bin or use Docker)
coap-client -m get coap://192.168.1.42/temperatura
# Response: 22.34. Observe from the command line
coap-client -m get -s 10 coap://192.168.1.42/temperatura
# -s 10: observe for 10 seconds, receive notifications automaticallyCoAP in the IoT stack: where it fits with other protocols
CoAP doesn't exist in isolation. In a real deployment, it coexists with other protocols at different layers. A typical case in 6LoWPAN sensor networks would be:
Network transport layer: Thread or BLE with 6LoWPAN
Application layer: CoAP (GET/PUT/Observe)
Security: DTLS with PreSharedKey
Backend integration: CoAP→HTTP proxy (Eclipse Californium)
Data broker: MQTT over TCP for cloud storageThe sensor speaks CoAP directly to the Border Router. The Border Router has a CoAP-HTTP proxy that translates the requests to the REST backend. The backend stores the data in a database and publishes metrics over MQTT to the monitoring dashboards.
This pattern is common in smart building installations: the sensors are tiny (8-32 KB RAM), they speak CoAP over 6LoWPAN, and the backend doesn't need to change — it consumes HTTP as always.
The choice between MQTT and CoAP at the application layer isn't binary. They can coexist in the same system: CoAP for the most constrained sensors, MQTT for the gateways and devices with more resources.
Primary sources
- RFC 7252 — The Constrained Application Protocol (CoAP) — official IETF spec (accessed: 2026-05)
- Eclipse Californium — CoAP Framework Java — server/proxy implementation (accessed: 2026-05)
- GitHub — obgm/libcoap — C implementation for embedded systems (accessed: 2026-05)
Frequently asked questions
Does CoAP work over TCP?+
Yes, RFC 8323 defines CoAP over TCP and WebSockets. Useful when the firewall blocks UDP or you need NAT traversal. It loses the minimal-overhead advantage but keeps the REST methods and Observe. In practice, CoAP-TCP is less common than CoAP-UDP.
What port does CoAP use?+
UDP/5683 (plain CoAP) and UDP/5684 (CoAP over DTLS). These are registered IANA ports. On NB-IoT, operators usually allow these ports outbound.
Is CoAP interoperable with HTTP?+
With a CoAP-HTTP proxy (Eclipse Californium includes one). The proxy translates GET coap://sensor/temp to GET http://backend/sensor/temp and vice versa. Californium acts as a reverse proxy, letting HTTP backends consume CoAP resources without changing the sensor firmware.
What's the practical difference between CON and NON?+
CON waits for an ACK; if none arrives within ~2 seconds, it retransmits up to 4 times with exponential backoff. NON doesn't retransmit — if the UDP packet is lost, it's gone. For temperature telemetry where losing one reading in a hundred doesn't matter, NON saves battery. For an actuator receiving a valve-open command, CON is mandatory.
Does CoAP support multicast?+
Yes. CoAP over UDP NON allows sending to IPv6 multicast addresses (e.g., ff02::fd for All-CoAP-Nodes). Useful for resource discovery: GET coap://[ff02::fd]/.well-known/core returns the resources of every node on the local network. There's no equivalent in MQTT.
Is CoAP adopted in NB-IoT?+
Yes. 3GPP and the lightweight IoT architecture specify CoAP as the preferred application protocol for NB-IoT and LTE-M when using the NIDD (Non-IP Data Delivery) profile or UDP. The NB-IoT guide goes into detail on integration with the cellular data plane.