Choosing an IoT Protocol: HTTP vs MQTT vs CoAP vs WebSocket Compared
Once an ESP32 has a reading to send, it needs an application protocol to carry it. The four you will meet most often are HTTP, MQTT, CoAP and WebSocket. All four can run on an ESP32, and all four can move a temperature value from a sensor to a server. They differ in how connections are made, who starts the conversation, how much overhead each message carries, and how well they handle commands coming back to the device.
This tutorial explains each protocol from the device's point of view, compares them in one table, and shows how to test each from a PC terminal so you can see the difference before writing firmware.
Request-Response vs Publish-Subscribe
Request-response is the web model. A client sends a request to a known server address, the server replies, and the exchange is over. HTTP and CoAP work this way. It is simple and easy to debug, but the server cannot start a conversation. If a phone app wants to switch a relay, the device has to keep asking "any commands for me?", which is called polling.
Publish-subscribe puts a broker in the middle. Devices publish messages to named topics such as home/kitchen/temp, and any client subscribed to that topic receives them. Publishers and subscribers never know each other's addresses. The device keeps one connection open to the broker, so commands can be pushed to it instantly. MQTT is the standard publish-subscribe protocol for IoT.
WebSocket is different again: it is a full-duplex channel that starts as an HTTP request and is then upgraded. Either side can send at any time, but the protocol defines no topics or routing; your application decides what messages mean.
The Four Protocols in Brief
HTTP / HTTPS
Runs over TCP, usually port 80 or 443 for HTTPS. Every request carries text headers, so even a tiny JSON body travels with a few hundred bytes of headers. Its strength is universality: every cloud service, every web framework and every firewall understands it. Use it for occasional uploads, for battery nodes that wake, send once and sleep, and for talking to REST APIs you do not control.
MQTT
Runs over TCP, port 1883 plain or 8883 with TLS. After a one-time CONNECT, each PUBLISH has a fixed header of only 2 bytes plus the topic name and payload. MQTT adds features that matter for devices: three QoS levels (0 at most once, 1 at least once, 2 exactly once), retained messages that give new subscribers the last value immediately, and a Last Will message the broker publishes if a device disappears. Use it for always-on devices, two-way control and many devices sharing one backend.
CoAP
The Constrained Application Protocol (RFC 7252) looks like HTTP, with GET, POST, PUT and DELETE on URIs such as coap://host/sensors/temp, but runs over UDP port 5683 with a compact binary 4-byte header. It supports confirmable messages with retransmission and an Observe option that lets a client subscribe to a resource. It suits very constrained networks such as 6LoWPAN and Thread. Library and cloud support is thinner than for HTTP and MQTT, so on Wi-Fi ESP32 projects it is used less often.
WebSocket
Runs over TCP, on the same ports as HTTP. After the upgrade handshake, frames have a header of only a few bytes. It is ideal when a browser must talk to a device or server in real time, for example a live control page served by the ESP32 itself. MQTT brokers such as Mosquitto can also accept MQTT over WebSocket so browser dashboards can subscribe directly.
Side-by-Side Comparison
| Feature | HTTP | MQTT | CoAP | WebSocket |
|---|---|---|---|---|
| Transport | TCP | TCP | UDP | TCP |
| Default port | 80 / 443 | 1883 / 8883 | 5683 / 5684 (DTLS) | 80 / 443 |
| Pattern | Request-response | Publish-subscribe via broker | Request-response plus Observe | Bidirectional stream |
| Per-message overhead | High (text headers) | Low (2-byte fixed header) | Low (4-byte header) | Low after handshake |
| Server can push to device | No, device must poll | Yes | Yes, with Observe | Yes |
| Delivery guarantee | TCP plus app retries | QoS 0, 1, 2 | Confirmable messages | TCP only |
| Security | TLS | TLS | DTLS | TLS (wss) |
| Best fit | Occasional uploads, REST APIs | Telemetry and control | Constrained mesh networks | Browser real-time UIs |
Try Each Protocol from a Terminal
Before involving the ESP32, send the same reading with command-line tools. This isolates server problems from firmware problems. Install curl (already present on Windows 10 and 11), the Mosquitto clients, and optionally coap-client from libcoap on Linux.
# HTTP: POST a JSON reading to a REST endpoint (replace with your server)
curl -X POST http://192.168.1.50:5000/api/readings \
-H "Content-Type: application/json" \
-d '{"id":"node1","temp_c":28.4}'
# MQTT: subscribe in one terminal ...
mosquitto_sub -h 192.168.1.50 -t 'home/+/temp' -v
# ... and publish from another terminal
mosquitto_pub -h 192.168.1.50 -t 'home/kitchen/temp' -m '{"temp_c":28.4}'
# MQTT retained message: new subscribers get it immediately
mosquitto_pub -h 192.168.1.50 -t 'home/kitchen/temp' -m '{"temp_c":28.4}' -r
# CoAP: GET a resource from a CoAP server (libcoap tools)
coap-client -m get coap://192.168.1.60/sensors/temp
Watch the MQTT subscriber: the message appears the moment it is published, with no request from the subscriber. That push behaviour is the single biggest reason MQTT dominates device control.
A Practical Decision Guide
- If the cloud service only offers a REST API (ThingSpeak's update endpoint, a college server, a webhook), use HTTP.
- If the device must receive commands quickly, such as relays, locks or motors, use MQTT with a persistent connection.
- If the node runs on battery and wakes every few minutes, either works: HTTP is simpler, while MQTT with a short connection is lighter on the wire. Measure both if battery life matters.
- If a browser page must update live from a device on the same network, serve a WebSocket from the ESP32 or use MQTT over WebSocket on the broker.
- If you are working on a low-power mesh such as Thread or 6LoWPAN rather than Wi-Fi, look at CoAP.
Common Mistakes
- Polling an HTTP endpoint every second for commands. It wastes power and bandwidth; switch to MQTT.
- Assuming MQTT QoS 2 is always better. It needs four packets per message; QoS 0 or 1 is right for most sensor data.
- Using a public test broker for real projects. Anyone can read and publish to your topics there.
- Forgetting that UDP (CoAP) can lose packets silently unless you use confirmable messages.
Summary
HTTP is universal and simple but heavy and one-directional. MQTT is light, two-way and built for devices, at the cost of running a broker. CoAP brings REST to UDP for constrained networks. WebSocket gives browsers a real-time channel. Most ESP32 projects end up using MQTT for device traffic and HTTP for talking to third-party services, which is exactly how the following tutorials are organised.