Zum Hauptinhalt springen
Zum Hauptinhalt springen

Protocols

CoAP

CoAP (RFC 7252) brings GET/POST/PUT/DELETE to devices with 8 KB of RAM over UDP. How Observe and DTLS work, and when to pick it over MQTT.

Official spec ↗
Audio summary
0:00 / 0:00
TopicsMQTT

MQTT dominates continuous telemetry. HTTP dominates APIs. CoAP 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 MQTT 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 QoS.

What CoAP is and what it's for

CoAP grew out of an obvious observation: the cheapest, lowest-power IoT 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):

text
 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:

TypeDescription
**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 methodHTTP equivalentUse
GETGETRead a resource
POSTPOSTCreate/process
PUTPUTIdempotent update/create
DELETEDELETEDelete 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.

text
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 subscription

The 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

SectorConcrete 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 ESP32-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/EMQX 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 with an AppSKey).

CoAP vs MQTT vs HTTP

AspectCoAPMQTTHTTP
ModelRequest/Response + ObservePub/SubRequest/Response
TransportUDPTCPTCP
Header4 bytes2 bytes (fixed)Variable (text, ~200-800 B)
Broker requiredNoYesNo
ReliabilityCON/NON (own layer)QoS 0/1/2 (TCP + broker logic)TCP
MulticastYes (NON over UDP multicast)NoNot standard
Minimum RAM~8 KB~32 KB (with TCP stack)~64 KB (with TLS)
REST interoperabilityHigh (HTTP-analogous methods)Low (requires adaptation)High

CoAP is the natural choice when: the radio is 6LoWPAN (Thread/Zigbee 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

bash
# In your ESP-IDF project directory
idf.py add-dependency "espressif/coap==4.3.5"

Or add it directly in idf_component.yml:

yaml
dependencies:
  espressif/coap: "^4.3.5"

2. Minimal CoAP server (ESP32, C)

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)

bash
# macOS / Linux (install libcoap-bin or use Docker)
coap-client -m get coap://192.168.1.42/temperatura
# Response: 22.3

4. Observe from the command line

bash
coap-client -m get -s 10 coap://192.168.1.42/temperatura
# -s 10: observe for 10 seconds, receive notifications automatically

CoAP 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:

text
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 storage

The 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

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.

Related articles