Back to all

Understanding an MQTT Packet: Ultimate Guide

The MQTT broker is responsible for maintaining stable connections with clients, processing messages, and forwarding them to the subscribed and approved recipients – in compliance with the set flags which are part of the packets exchanged.

Before reading this article, we recommend having an overview of the MQTT basics and the different QoS levels supported in MQTT message transmissions. In this article, you will learn about the MQTT packet format, the different MQTT packet types, and how to understand MQTT packets.

What is an MQTT packet?

At its core, MQTT is a binary-based protocol that utilizes a command and command-acknowledgement format. Moreover, an acknowledgment in the form of an MQTT packet usually responds to an MQTT command. 

A packet in MQTT is a unit of data that is sent between clients and the MQTT broker. 

The following figure shows a sequence of MQTT packets exchanged between an MQTT client and an MQTT broker during a typical session:

MQTT packet command-acknowledgement sequence

This image was taken as a screenshot from the application WireShark which can be used to analyze any kind of network traffic. The column “Length” indicates the number of bytes transferred between the client and the broker, which includes the TCP overhead and the MQTT packet.

Explore the MQTT packet analysis with WireShark guide.

MQTT Packet format

The MQTT protocol exists in different versions. This article will refer to two: version 5.0 and version 3.1.1. Unless otherwise stated, the given information is version independent.

The MQTT packet format consists of the following three parts:

  1. Fixed header: Made up of the packet type, packet flags, and length of the remaining packet
  2. Variable header: Includes packet-type specific meta-data
  3. Payload: The packet-type specific payload data, e.g., the message for a PUBLISH packet

Apart from the fixed header, all other components are optional, which means different MQTT packets have different combinations. For example, an MQTT packet could have:

  • Only a fixed header, like the PINGREQ packet.
  • Fixed header and a variable header, like the PUBACK, PUBREC, and PUBREL packets.
  • All fields (fixed header, variable header, and payload), like the CONNECT or SUBSCRIBE packet.

This table gives some of the available MQTT packets and whether they contain a variable header and payload. For a complete list, refer to the MQTT Specification.

Control PacketVariable HeaderPayload
CONNECTRequiredRequired
PUBLISHRequiredOptional
SUBSCRIBERequiredRequired
UNSUBSCRIBERequiredRequired

MQTT Packet structure

Fixed header

As mentioned earlier, the MQTT packet always has a fixed header. The following image breaks it down further into the control field and remaining length.

MQTT Packet fixed header structure

As shown, the fixed header in an MQTT packet has the following:

  • A control field, also known as the MQTT control packet. We’ll take a closer look at this in the next section.
  • A remaining length denotes the remaining length of the variable header and payload data.
    • For small packets less than 127 bytes, the remaining length is stored in one byte; the 8th bit is a continuation bit.
    • For packets larger than 127 bytes and smaller than 16383 bytes, 2 bytes are used.
    • The maximum packet size is 256 MB.

Packet Type and Flags

The control field is mandatory and the first byte in each MQTT packet. It is separated into two 4-bit fields: packet type and flags.

MQTT Packet control field structure

The first 4-bits represent the control packet type of the MQTT packet. There are 15 different MQTT packet types.

Some of the packet types with value and allowed direction are given in the following table. Refer to the MQTT specification as mentioned earlier for a complete list.

NameValueDirectionDescription
CONNECT1Client -> BrokerClient request to connect to broker
CONNACK2Broker -> ClientConnect acknowledgement
PUBLISH3BothPublish message
SUBSCRIBE8Client -> BrokerClient subscribe request
DISCONNECT14Client -> BrokerClient is disconnecting

The last four bits of the MQTT control packet, the so-called control flags, are fixed corresponding to the used packet type and cannot be changed by the client, with one exception, the PUBLISH control packet type.

The four bits that the client can set are:

  • DUP: Indicates if this packet is a duplicate. Bit 3
  • QoS: The Quality of Service level. Bit 2,1
  • RETAIN: Denotes if the message shall be retained. Bit 0

Example control packet: 0b00110011 = 0x33 → PUBLISH, DUP=0, QoS=1, Retain=1.

Variable header

As the name suggests, the content and length of the variable header differ according to the packet type. For example, the following image shows the structure of the variable header for the CONNECT control packet.

Variable header for MQTT CONNECT packet
  • Protocol name length: Indicates the length in bytes of the Protocol Name
  • Protocol name: ASCII representation of the protocol name, e.g., MQTT (0x4d 0x51 0x54 0x54)
  • Protocol level: “4” for MQTT v3.1.1, “5” for MQTT v5.0.
  • Connect flag: A 1-byte field with information about connection options like retention, QoS, clean session, etc. An example of this is attached just below.
    • Will retain:  if enabled, the message will be set as retained.
    • Will QoS: Indicates the Qos level with which the message will be sent.
      • Denotes the QoS level in 2 bits, i.e., QoS 0 = “0” and “0,” QoS 1 = “1” and “0,” QoS 2 = “0” and “1.”
    • Will flag: if activated, the broker sends a Last Will message (LWT) on behalf of the client when it disconnects unexpectedly.
    • Clean session: if active, the broker will clear any existing session when this client connects and not store any session data after the client disconnects. Note that in MQTT v5.0, this flag is called “clean start” and only affects the start of the session.
  • Keep alive: Denotes the maximum time period the client will leave before sending a packet to the broker.

Connect flags are defined by:

Bit76543210
username flagpassword flagwill retainwill QoSwill flag*)reserved
xxxxxxx0
*) represents ‘clean session’ in the case of version 3.1.1 and ‘clean start’ in the case of version 5.0.

Payload

The payload holds the data related to the packet being sent. For a PUBLISH packet, this is the actual message being sent. The message can be in any format, but most often in ASCII-encoded characters formatted as JSON, XML, or text.

Example payload with six bytes: 0x43 0x65 0x64 0x61 0x6c 0x6f → Cedalo.

MQTT Packet size

The overall MQTT packet needs a minimum packet size of 2 bytes (defined by the fixed header) and a maximum of 256MB. For example, in MQTT v3.1.1, a DISCONNECT packet only has the control packet type field and packet length field, equating to 2 bytes. In this case, no variable header or payload is needed, as the client simply wants to disconnect.

MQTT packet example sequence

We’ve shared a lot of information about MQTT packets, and we know it can be challenging to put it all together, so let’s look at one packet.

As an example, an MQTT packet that is sent from a client to the broker can have the following content written as hexadecimal bytes:

82 0d 00 01 00 00 07 6d 79 74 6f 70 69 63 01

These 15 bytes represent the action the client wants to subscribe to on the topic “mytopic” with quality of service level 1 in protocol version 5.0. With the following examples, the structure of the MQTT packets will be explained in detail to understand how the bytes are set.

We take the sequence given at the very beginning of this article. An MQTT client connects to an MQTT broker, subscribes on a topic, publishes a message, and disconnects.

The examples given shall be interpreted as follows. The left column cells contain the bytes in hexadecimal representation. The explanation is provided in the right column and refers to the bytes marked by “||” in the left column. Numbers in the right column are always in the decimal number system.

Connect packet example

The connect packet example is given for both protocol versions, 3.1.1 and 5.0. The difference is in the meaning of the connect flag and the extension of the session properties in the case of version 5.0. Here,  a session expiry interval of 1800 seconds is set – client id, user name, and password are used for the authentication.

Case protocol version 5.0 (38 bytes)

10 24 00 04 4d 51 54 54 05
||........................
...||.....................
......||.||...............
............||.||.||.||...
........................||

Fixed Header: Connect Command (16)
Remaining Length: 36
Protocol Name Length: 4
Protocol Name: “MQTT” (77 81 84 84)
Version: MQTT v5.0 (5)
c2 00 3c
||......
...||.||

Connect Flags: User Name, Password, QoS, Clean Start
Keep Alive: 60
05 11 00 00 07 08
||...............
...||............
......||.||.||.||

Properties Total Length: 5
ID: Session Expiry Interval (17)
Value: 1800
00 04 6d 79 50 79
||.||............
......||.||.||.||

Client ID Length: 4
Client ID: “myPy”
00 06 63 6c 69 65 6e 74
||.||..................
......||.||.||.||.||.||

User Name Length: 6
User Name: “client”
00 0a 70 61 73 73
||.||............
......||.||.||.||

Password Length: 4
Password: “pass”

Case protocol version 3.1.1 (32 bytes)

10 1e 00 04 4d 51 54 54 05
||........................
...||.....................
......||.||...............
............||.||.||.||...
........................||

Fixed Header: Connect Command (16)
Remaining Length: 30
Protocol Name Length: 4
Protocol Name: “MQTT” (77 81 84 84)
Version: MQTT v5.0 (5)
c2 00 3c
||......
...||.||

Connect Flags: User Name, Password, QoS, Clean Session
Keep Alive: 60
00 04 6d 79 50 79
||.||............
......||.||.||.||

Client ID Length: 4
Client ID: “myPy”
00 06 63 6c 69 65 6e 74
||.||..................
......||.||.||.||.||.||

User Name Length: 6
User Name: “client”
00 0a 70 61 73 73
||.||............
......||.||.||.||

Password Length: 4
Password: “pass”

MQTT subscribe packet example

For the subscribe packet example, the client sends a packet to subscribe on the topic named “mytopic” with a quality of service level 1

In the case of protocol version 5.0, the subscription properties can be set by the client. In the given example, no additional properties are set.

Case protocol version 5.0 (15 bytes)

82 0d 00 01
||.........
...||......
......||.||

Fixed Header: Subscribe Request (130)
Msg Len: 13
Message Identifier: 1
00 00 07 6d 79 74 6f 70 69 63 01
||..............................
...||.||........................
.........||.||.||.||.||.||.||..
||

Properties Total Length: 0
Topic Length: 7
Topic: “mytopic”
Retain Handling: Send msgs at subscription time, QoS: 1

Case protocol version 3.1.1 (14 bytes)

82 0c 00 01
||.........
...||......
......||.||

Fixed Header Flags: Subscribe Request (130)
Msg Len: 12
Message Identifier: 1
00 07 6d 79 74 6f 70 69 63 01
||.||........................
......||.||.||.||.||.||.||...
||

Topic Length: 7
Topic: “mytopic”
QoS: 1

MQTT publish packet example

To publish a message “Cedalo,” the client in the example given sends a packet with control type PUBLISH and the flags quality of service level = 1 and retain = 1 (True). Read the MQTT retained message guide to learn how they work and where to use. In the case of protocol version 5.0, the packet is extended by the message properties. In the given example below, a Publication Expiry Interval, also known as Message Expiry Interval, of 30 seconds is set by the client. Subsequently, this results in the situation that if another client subscribes within 30 seconds to the same topic, it will receive the message because it is set to be retained. If another client subscribes later than 30 seconds after the message has been published, the broker will send no message to the new client. As stated before, this is a version 5.0-only feature.

Case protocol version 5.0 (22 bytes)

33 14
||...
...||

Fixed Header, Flags: Publish Message, QoS Level: 1, Retain: 1
Msg Len: 20
00 04 69 6e 66 6f 00 02 
||.||..................
......||.||.||.||......
..................||.||

Topic Length: 4
Topic: “info”
Message Identifier: 2
05 02 00 00 00 1e
||...............
...||............
......||.||.||.||

Properties Total Length: 5
ID: Publication Expiry Interval (2)
Value: 30
43 65 64 61 6c 6f
||.||.||.||.||.||

Message: “Cedalo”

Case protocol version 3.1.1 (16 bytes)

33 0e
||...
...||

Fixed Header, Flags: Publish Message, QoS Level: 1, Retain: 1
Msg Len: 14
00 04 69 6e 66 6f 00 02 
||.||..................
......||.||.||.||......
..................||.||

Topic Length: 4
Topic: “info”
Message Identifier: 2
43 65 64 61 6c 6f
||.||.||.||.||.||

Message: “Cedalo”

Wrap up

MQTT is a binary-based protocol that uses a command and command-acknowledgement format. Each command and acknowledgment response comes in the form of an MQTT packet. 

A typical MQTT packet has a fixed header (also known as a control packet) and could have a variable header and/or payload, depending on the MQTT packet type. The MQTT control packet is a mandatory 1-byte field containing information about the packet type and flags.

MQTT packets must adhere to a minimum packet size of 2 bytes and a maximum of 256MB. The packet size could vary depending on the packet type, as some MQTT packet types only contain the fixed header, such as the DISCONNECT packet.

Start using MQTT packets in your next project with Mosquitto or Pro Edition for Eclipse Mosquitto. You can test some of the pro features by signing up for a free 14-day trial. And if you hit any roadblocks while using the open-source version, take advantage of our new professional support service.

Click to rate this post!
[Total: 5 Average: 5]
About the author
Avatar photo

Laurenz Dallinger

Customer Success Manager at Cedalo

Laurenz Dallinger, a go-to expert for IoT use cases, problem-solving, and customer care, brings a wealth of experience to Cedalo's MQTT and IoT-focused blog. With a diverse professional background, including previous roles as an Application Engineer and a role explaining the digitization of the German health system, Laurenz is well-versed in navigating complex technological landscapes.

Beyond his professional pursuits, Laurenz is passionate about art and tirelessly conveys to customers that digitalization is akin to the canals of Venice. He likens it to the digital Canal Grande, emphasizing the importance of navigating the smaller canals—the intricacies of digital transformation.

Newsletters icon

Subscribe for monthly updates