This is an old revision of the document!
CoAP — the Constrained Application Protocol — is a compact, web-inspired protocol designed for tiny devices and lossy networks. Think of it as “HTTP’s cousin” for the Internet of Things: it preserves RESTful ideas (resources, methods, content types) but trims the bandwidth and processing overhead so microcontrollers running on batteries can still speak the language of the web.
Classic HTTP works well on desktops and phones, but it assumes abundant memory, stable links, and generous power budgets. Constrained nodes and low-power lossy networks (LoWPAN, BLE, long‑range sub‑GHz, shared mesh) rarely have those luxuries. CoAP targets this environment. It keeps the resource model developers love while reducing message size, connection setup cost, and round‑trips. The protocol is simple enough to fit in a few kilobytes of code, yet expressive enough to model real devices and digital twins.
CoAP embeds a REST design: resources are identified by URIs, and clients interact using familiar methods. A minimal binary header replaces HTTP’s verbose text format, and the transport defaults to UDP. Reliable delivery is still achievable through confirmable messages and retransmissions handled by the CoAP layer, not the transport.
Methods mirror HTTP semantics with a leaner encoding: GET, POST, PUT, DELETE. Servers can expose well-known endpoints (for example, /.well-known/core/) to advertise available resources and interfaces using the CoRE Link Format. Content types are represented by compact numeric Content‑Format identifiers rather than long MIME strings, cutting repeated overhead dramatically.
Every CoAP message carries a tiny fixed header followed by Options and an optional Payload. Options are encoded in a delta/length scheme that compresses repeated numbers and elides absent fields. Four message types shape reliability and control flow:
The combination allows request/response exchanges over UDP without a connection handshake. Message IDs and Tokens help match responses to requests, even across retransmissions or when responses are sent later (separate response).
A CoAP URI looks like coap://host:port/path?query (or coaps:// for DTLS-secured). Discovery usually begins with GET coap://device/.well-known/core, which returns a set of typed links describing resources, interfaces, and content formats. Because links and attributes are compactly encoded, devices can publish meaningful self‑descriptions without burning through budgeted bytes.
CoAP supports content negotiation via Accept and Content‑Format options. Common formats include application/json, application/cbor, and sensor‑oriented binary representations. CBOR pairs well with CoAP because it offers dense, schema‑agnostic encoding with minimal overhead on tiny MCUs.
CoAP borrows HTTP’s cache validators (ETag, Max‑Age) so intermediaries and clients can avoid redundant transfers. An ETag is a small opaque token that changes when the resource representation changes. With Max‑Age, clients can confidently reuse cached data until it expires, then revalidate or fetch an update.
Polling wastes energy. CoAP’s Observe extension lets a client register interest in a resource, turning the server into a notifier. After the initial GET with an Observe option, the server streams changes as normal CoAP responses, each correlated by the original token. Ordering and freshness are guided by a sequence number (often a monotonic value) so clients can discard stale deliveries. Observe works through intermediaries, letting gateways or proxies fan out updates to many clients efficiently.
Small MTUs and duty‑cycle limits make large payloads tricky. Block1 and Block2 options slice requests and responses into manageable chunks. The client or server moves block‑by‑block, using the options to indicate size and index. This allows firmware downloads, log retrieval, or model updates without exceeding link constraints, while keeping memory footprints small on each side.
Security comes in layers. The simplest path is DTLS (for UDP) or TLS (when using CoAP over TCP), providing channel protection similar to HTTPS. In constrained meshes, channel security alone can be fragile; topologies change, and intermediaries may need to route or cache. OSCORE (Object Security for Constrained RESTful Environments) protects the message payload and options end‑to‑end using COSE, independent of the transport. This enables proxies to function while keeping application data confidential and authenticated between true endpoints. Keys can be derived from pre‑shared material, EDHOC handshakes, or other provisioning schemes.
While UDP is the default, CoAP also runs over TCP, TLS, and WebSockets. The TCP/TLS mapping preserves CoAP’s method and option model but leans on the stream for reliability and congestion control. This is handy when middleboxes block UDP or when a deployment prefers a connection‑oriented flow for policy reasons. The coap+ws and coaps+ws schemes allow traversal of web infrastructure while retaining CoAP semantics.
A powerful feature is native proxying. CoAP‑to‑HTTP and HTTP‑to‑CoAP gateways translate methods, status codes, options/headers, and payloads. This is how a tiny sensor can appear as a normal web resource or how a cloud app can issue requests to a sleepy field device without teaching every service a new protocol. Proper mapping of caching directives and content types ensures the two worlds remain consistent.
Because it rides over UDP by default, CoAP specifies conservative retransmission backoff, leaky‑bucket style pacing, and limits on simultaneous confirmable messages. Implementations typically expose tunables for ACK_TIMEOUT, ACK_RANDOM_FACTOR, and MAX_RETRANSMIT. The aim is politeness on shared, lossy links: back off early, avoid bursts, and prefer NON traffic when eventual consistency suffices.
Plan the resource tree as if you were designing a public API. Use nouns for resources, reserve verbs for state changes, and stick to predictable shapes so intermediaries can cache intelligently. Choose compact encodings (CBOR) for high‑volume telemetry but keep human‑readable JSON for diagnostics. Embrace ETags and Max‑Age to cut chatter; adopt Observe for state that changes often; and reach for Block‑Wise when transferring anything larger than your typical MTU. For security, default to OSCORE when proxies are involved, and to DTLS/TLS when you control both endpoints and want a protected channel. Document your Content‑Format numbers and keep a registry in your codebase to avoid mismatches during updates.
Below is a minimal round‑trip. The client fetches a temperature resource and receives a piggybacked response. Encoding is shown schematically rather than byte‑exact:
Client → Server CON, MID=0x4A3B, Token=0xC1 Code=GET Uri-Path: "sensors" Uri-Path: "temp" Accept: application/cbor Server → Client ACK (to 0x4A3B), Token=0xC1 Code=2.05 Content Content-Format: application/cbor Payload: { "t": 21.6, "u": "C" }
Subsequent updates could use Observe so the server pushes new readings as they happen, each carrying the same token and an incremented Observe sequence value.
Pick CoAP when you need web‑style resource semantics on severely constrained devices, when UDP is available and cheap, and when gateways, caches, and multicast discovery will simplify your topology. It shines for sensor/actuator fleets, smart buildings, and industrial telemetry with intermittent connectivity. Prefer HTTP/HTTP/2 or gRPC when you require continuous high‑throughput streams, large messages without chunking, or when infrastructure mandates strictly connection‑oriented flows and rich middleware that already speaks HTTP at every hop.
term:: RFC 7252 — base CoAP specification (methods, message formats, reliability). term:: RFC 7641 — Observe (server‑initiated notifications). term:: RFC 7959 — Block‑Wise transfers (chunking). term:: RFC 8323 — CoAP over TCP, TLS, and WebSockets. term:: RFC 8613 — OSCORE (object security, end‑to‑end protection). term:: CoRE Link Format / /.well-known/core/ — discovery and typed links.