Use curl with EMQX
curl is a widely used command-line tool for data transfer and automation. Since 2020, curl has supported the MQTT protocol, and starting from curl 8.19.0 (expected March 2026), it also supports MQTTS (MQTT over TLS).
With curl, developers can connect to EMQX, publish messages, and subscribe to topics directly from the command line, without installing any language-specific MQTT client SDKs. This makes curl a convenient choice for quick testing, scripting, and IoT prototyping.
This page explains how to use curl with EMQX for MQTT and MQTTS communication, including connection, publish/subscribe, authentication, TLS configuration, and common troubleshooting scenarios.
curl Version Requirements
| Feature | Minimum Version | Release |
|---|---|---|
MQTT (mqtt://) | 7.70.0 | April 2020 |
MQTTS (mqtts://) | 8.19.0 | Early March 2026 |
Check your installed curl version:
curl --versionEnsure that mqtt (and mqtts for curl ≥ 8.19.0) appears in the Protocols list.
If your curl version is too old, upgrade via your package manager or download from https://curl.se/download.
On macOS, use
brew install curlto install the latest version.
MQTT Broker Setup
You need an MQTT broker to connect to. This guide uses EMQX, which supports both MQTT and MQTTS.
EMQX Public Broker (Testing)
For quick testing without deploying your own broker, you can use the EMQX public broker.
| Parameter | Value |
|---|---|
| Broker | broker.emqx.io |
| MQTT Port | 1883 |
| MQTTS Port | 8883 |
The public broker is intended for testing and demonstration purposes only.
EMQX Enterprise Deployment
For production scenarios, connect curl to your own EMQX Enterprise deployment using the broker address, ports, authentication credentials, and TLS configuration defined in your environment.
Typical configurations include:
- Custom broker hostname or IP address
- MQTT and/or MQTTS listeners enabled in EMQX Enterprise
- Username/password authentication, token-based authentication, or mutual TLS
- Access control rules (ACLs) applied to topics
Refer to your EMQX Enterprise listener, authentication, and TLS configuration when constructing curl commands.
Notes
- Replace
broker.emqx.iowith your EMQX Enterprise broker address in all examples when testing against your own deployment. - Ensure the corresponding MQTT or MQTTS listener is enabled in EMQX Enterprise before connecting.
In addition to self-managed EMQX Enterprise deployments, you can also use curl to connect to the fully managed MQTT service EMQX Cloud (Serverless or Dedicated).
The curl MQTT/MQTTS usage remains the same. Use the broker address, ports, and authentication information provided by EMQX Cloud.
Connect to EMQX Enterprise with curl
In MQTT, clients establish a connection to the broker as part of an operation, such as subscribing to a topic or publishing a message. There is no separate “connect” command.
When using curl with EMQX Enterprise, a connection is established automatically when you run a subscribe or publish command using your Enterprise broker address (and authentication or TLS settings, if configured).
For example, the following command connects to EMQX Enterprise and subscribes to a topic in a single step:
curl -N mqtts://your-enterprise-broker.example.com/curl/testNote: MQTTS (
mqtts://) requires curl 8.19.0 or later. For curl versions 7.70.0 to 8.18.x, usemqtt://instead.
Understand curl MQTT URL Scheme
curl uses a URL-based syntax for MQTT operations:
mqtt[s]://[user:password@]broker[:port]/topicWhere:
mqtt[s]indicates the protocol (mqttormqtts).[user:password@]is optional authentication.brokeris the broker hostname or IP address.[:port]is the optional port number. If no port is specified, curl uses the default:1883formqtt://8883formqtts://
/topicis the MQTT topic path, for example,/sensor/temperature.
curl MQTT Output Format
When subscribing to a topic, curl outputs raw MQTT message data in the following format:
[2 bytes: topic length (big-endian)] [topic string] [payload]For example, a message "hello" on the topic curl/test appears as:
curl/testhelloThe output is a binary format where the topic name and payload are concatenated together, making it difficult to read without parsing.
This output is binary and not human-readable by default. See Parse MQTT Messages below for conversion examples.
Subscribe to Topics
Subscribing keeps the connection open and prints incoming messages to stdout.
Basic Subscription (Unencrypted)
curl -N mqtt://broker.emqx.io/curl/test --output messages.binThe -N option disables output buffering, allowing messages to appear immediately.
Secure Subscription with MQTTS (curl ≥ 8.19.0)
curl -N mqtts://broker.emqx.io/curl/test --output messages.binSubscription with Authentication
curl -N -u "username:password" \
mqtts://your-broker.emqxsl.com/curl/test --output messages.binParse MQTT Messages
When subscribing to a topic, curl outputs MQTT messages in a binary format rather than a formatted text representation.
Each incoming message is structured as:
- 2 bytes: topic length (big-endian)
- topic string
- payload (raw bytes)
As a result, the output appears as a concatenation of topic and payload and is not human-readable by default.
Bash One-Liner
To make subscription output readable, pipe curl output through a shell parser:
curl -sN mqtt://broker.emqx.io/curl/test | \
while IFS= read -r -d $'\0' d; do
[ -z "$d" ] && continue
# curl's MQTT subscribe output is: 2-byte topic length (MSB,LSB), topic, payload.
# This loop uses NUL (0x00) as a delimiter, so we are seeing the LSB first and
# implicitly using MSB=0 (works for topic lengths 0..255).
lsb=$(printf "%d" "'${d:0:1}")
topic_len=$((lsb))
echo "[${d:1:$topic_len}] ${d:$((1 + topic_len))}"
doneOutput format:
[curl/test] helloThis parser uses a simplified approach suitable for demonstration purposes.
It works as follows:
- The stream is split on null bytes.
- The topic length is derived from the lower byte of the two-byte topic length field. This approach is valid only for topics shorter than 256 bytes, where the high byte is zero.
- The topic string and payload are extracted using the length prefix.
- Each message is printed as
[topic] payload.
Save Raw Output for Inspection
To better understand the binary structure of MQTT messages, you can save the raw subscription output to a file and inspect it manually.
Save the output:
curl -sN mqtt://broker.emqx.io/curl/test > messages.binInspect the file using hexdump:
hexdump -C messages.binThis allows you to clearly see the topic length prefix, topic bytes, and payload layout.
Reusable Shell Function
For repeated use, the parser can be wrapped in a reusable shell function:
mqtt_subscribe() {
curl -sN "$1" | while IFS= read -r -d $'\0' d; do
[ -z "$d" ] && continue
# curl's MQTT subscribe output is: 2-byte topic length (MSB,LSB), topic, payload.
# This loop uses NUL (0x00) as a delimiter, so we are seeing the LSB first and
# implicitly using MSB=0 (works for topic lengths 0..255).
lsb=$(printf "%d" "'${d:0:1}")
topic_len=$((lsb))
echo "[${d:1:$topic_len}] ${d:$((1 + topic_len))}"
done
}Usage example:
mqtt_subscribe "mqtt://broker.emqx.io/curl/test"For production use or complex parsing requirements, consider MQTTX CLI, which provides properly formatted output, full MQTT 5.0 support, QoS handling, and wildcard subscriptions.
Publish Messages
To publish, use curl's -d (data) flag with the message payload.
Basic Publish (Unencrypted)
curl -d "Hello from curl" \
mqtt://broker.emqx.io/curl/testSecure Publish with MQTTS (curl ≥ 8.19.0)
curl -d "Secure message from curl" \
mqtts://broker.emqx.io/curl/testPublish JSON Payloads
curl -d '{"sensor_id":"temp-001","value":23.5}' \
mqtt://broker.emqx.io/sensors/temperaturePublish with Authentication
curl -u "username:password" \
-d '{"status":"online"}' \
mqtts://your-broker.example.com/devices/statusRelevant curl Options
The following table summarizes curl command-line options used throughout this document.
| Option | Description | Typical Usage |
|---|---|---|
-N | Disable output buffering (required for subscriptions) | Subscribe |
-d | Message payload to publish | Publish |
-u user:pass | Username and password authentication | Authentication |
-v | Verbose output (shows MQTT handshake) | Troubleshooting |
-s | Silent mode (suppress progress output) | Scripts |
--cacert | CA certificate for TLS verification | MQTTS |
--cert | Client certificate for mutual TLS | MQTTS |
--key | Client private key for mutual TLS | MQTTS |
-k | Skip TLS verification (testing only) | Troubleshooting |
For a complete list of curl options, see the official curl documentation.
TLS Configuration (MQTTS)
CA Certificate Verification
curl --cacert /path/to/ca.crt \
-d "TLS verified message" \
mqtts://your-broker.example.com/secure/topicMutual TLS (mTLS)
curl --cacert /path/to/ca.crt \
--cert /path/to/client.crt \
--key /path/to/client.key \
-d "mTLS message" \
mqtts://your-broker.example.com/secure/topicUse
-kto skip certificate verification for testing only.
Common Use Cases
Broker Connectivity Testing
curl -v mqtt://broker.emqx.io/curl/testThis verifies DNS resolution, TCP connectivity, and MQTT handshake.
Successful connection indicators
When the connection is successful, the verbose output typically shows:
- The broker hostname resolving to one or more IP addresses
- A successful TCP connection to port
1883(MQTT) or8883(MQTTS) - An MQTT handshake completed without errors
If no errors are printed and the command exits normally, the connection to the EMQX broker is established.
Shell Scripting and IoT Prototyping
Example: Simulate a temperature sensor publishing data every 5 seconds.
#!/bin/bash
BROKER="mqtt://broker.emqx.io"
TOPIC="sensors/room1/temperature"
while true; do
TEMP=$(awk -v min=20 -v max=30 'BEGIN{srand(); print min+rand()*(max-min)}')
PAYLOAD="{\"temperature\": $TEMP, \"timestamp\": $(date +%s)}"
curl -s -d "$PAYLOAD" "$BROKER/$TOPIC"
sleep 5
doneLimitations of curl for MQTT
While curl is useful for testing and scripting, it has the following limitations:
| Limitation | Description |
|---|---|
| QoS 0 only | No support for QoS 1 or 2 |
| Binary output | Subscription output is not formatted |
| No wildcards | Cannot subscribe using + or # |
| Single topic | One topic per command |
| No persistent sessions | Stateless connections |
For advanced MQTT features, use MQTTX CLI or EMQX client SDKs.
Verify MQTT Support in curl
curl --version | grep -i mqttIf the command produces output containing mqtt (or mqtts for curl ≥ 8.19.0), your curl build includes MQTT support. If MQTT is missing, you may need to:
- Upgrade curl to version 7.70.0 or later
- Install a build with MQTT enabled
- Compile curl from source with
--enable-mqtt
Troubleshooting
This section lists common issues when using curl with EMQX and how to resolve them.
Connection Refused or Timeout
Description
Connection refusedFailed to connect to broker- Connection hangs and then times out
Possible causes
- Incorrect broker address or port
- Network firewall blocking MQTT/MQTTS ports
- Broker is not running or is not listening on the specified port
Solution
- Verify the broker address and port:
- MQTT:
1883 - MQTTS:
8883
- MQTT:
- Check network connectivity using verbose mode:
curl -v mqtt://broker.emqx.io/curl/testMQTT or MQTTS Not Supported by curl
Description
Protocol "mqtt" not supportedUnknown protocol
Possible causes
- curl was built without MQTT support
- curl version is too old
Solution
- Verify protocol support:
curl --versionEnsure mqtt (and mqtts for TLS) appears in the Protocols list.
- Upgrade curl or install a build with MQTT enabled.
TLS Handshake or Certificate Errors (MQTTS)
Description
SSL certificate problemTLS handshake failedUnable to get local issuer certificate
Possible causes
- Missing or incorrect CA certificate
- Broker uses a private or self-signed certificate
Solution
- Specify the CA certificate explicitly:
curl --cacert /path/to/ca.crt \
mqtts://your-broker.example.com/topic- For testing only, skip verification (not recommended for production):
curl -k mqtts://your-broker.example.com/topicNo Messages Received When Subscribing
Description
- Subscription command runs, but no output is displayed
Possible causes
- Output buffering enabled
- No messages published to the topic
- Topic name mismatch
Solution
- Always use
-Nfor subscriptions:
curl -N mqtt://broker.emqx.io/curl/test- Verify that messages are being published to the same topic.
Authentication Failed
Description
- Connection closes immediately
- Authorization or authentication errors in broker logs
Possible causes
- Incorrect username or password
- ACL restrictions on the topic
Solution
- Verify credentials:
curl -u "username:password" \
mqtts://your-broker.example.com/topic- Check authentication and ACL configuration in EMQX.
More Information
For a detailed, step-by-step walkthrough of using curl with MQTT and MQTTS, including background explanations, additional examples, and usage considerations, see the blog post: Using curl for MQTT: Connect, Publish, and Subscribe with Secure IoT Communication.
The blog complements this Enterprise-focused guide by providing deeper explanations and extended examples.