MQTT 5 Payload Format Indicator & Content Type Explained

By | July 13, 2026

MQTT has always been data-agnostic. The broker treats the payload of every PUBLISH as an opaque byte string, forwards it verbatim, and never looks inside. That is one of the protocol’s core strengths — it means MQTT can carry anything without the broker needing to understand it. But it is also historically one of its weaknesses.

In MQTT 3.1.1, if a subscriber received a message, it had no way to know from the protocol alone whether the payload was JSON, XML, a binary sensor reading, an image, or something else entirely. The receiver either had to know by convention what to expect on a topic, or it had to inspect the payload to guess, or the publisher had to encode format information inside the payload itself.

MQTT 5 fixes this with two new PUBLISH properties: the Payload Format Indicator and the Content Type. Together they let a message describe its own payload at the protocol level, so a receiver can process it correctly without inspecting it.

This article covers both properties in detail — how they are encoded, what they mean, how they interact, when they are useful, and how they compare to the user-properties mechanism for related metadata. It is a technical reference; the MQTT 5 overview, user properties, and the related feature articles have their own dedicated articles in this category.

Payload format description at a glance

PropertyTypeValuesWhere it appearsOptional?
Payload Format IndicatorByte0 (unspecified byte stream), 1 (UTF-8)PUBLISH, will properties in CONNECTYes (defaults to 0)
Content TypeUTF-8 stringAny UTF-8 string, typically a MIME typePUBLISH, will properties in CONNECTYes
Interpreted byClient applications onlyThe broker forwards both unchanged
Available inMQTT 5Not in MQTT 3.1.1

The problem: data-agnostic is not the same as self-describing

In MQTT 3.1.1, “data-agnostic” is a benefit and a limitation at the same time. The benefit is that any payload can travel through the broker unchanged, whether it is JSON, encrypted binary, an image, protobuf, or a plain integer. The limitation is that a subscriber receiving that payload has no protocol-level information about what it actually is. This forces one of three workarounds, each imperfect.

Convention on topics. A topic like sensors/site-a/temperature-json encodes the payload format into the topic name. The subscriber then knows by convention that this topic carries JSON. This works, but it hard-codes format assumptions into the topic hierarchy, and it breaks if a publisher ever needs to change the format.

Metadata inside the payload. A wrapping envelope (typically JSON) contains a type or format field alongside the data. This works, but every subscriber has to parse the envelope before it can act on the payload, and every publisher has to serialize into the envelope format. The overhead is real, and the envelope becomes yet another interface that all consumers must understand.

Assumption and prayer. The publisher and subscriber simply agree, out of band, on the format. This works for closed systems where every party is under the same control, but it breaks the moment a new subscriber or a different publisher enters the picture and does not know the convention.

MQTT 5’s payload format properties solve this directly. Instead of encoding format information into topics or payloads, the publisher can attach two protocol-level properties to any PUBLISH: one that says whether the payload is text or binary, and one that says exactly what kind of data it is. The broker forwards these to every subscriber unchanged, and each subscriber can act on the information without inspecting the payload.

Payload Format Indicator

The Payload Format Indicator is the simpler of the two properties. It is a single byte attached to a PUBLISH (or a will publish in CONNECT) that tells the receiver whether the payload should be treated as UTF-8 text or as an unspecified byte stream.

There are two valid values:

  • 0 — the payload is an unspecified byte stream. This is the default when the property is absent, and it matches the MQTT 3.1.1 behavior. The receiver should treat the payload as raw bytes and make no assumptions about what they represent.
  • 1 — the payload is UTF-8 encoded character data. The receiver can treat the payload as a UTF-8 string, and, importantly, is allowed to reject the message if the payload is not valid UTF-8.

The distinction matters because “text” and “binary” are handled very differently by most applications. A subscriber that expects UTF-8 text can decode the payload directly into a string. A subscriber that expects binary bytes can pass them to a decoder that knows what to do with them. Without the indicator, the receiver has to guess, or it has to look inside the payload for markers that suggest one or the other.

Practical consequences of Payload Format Indicator = 1

When the Payload Format Indicator is set to 1, the receiver is entitled to enforce that the payload really is valid UTF-8. A payload that fails UTF-8 validation on a PUBLISH marked as UTF-8 is a protocol error, and the broker can respond with a PUBACK or PUBREC carrying reason code 0x99 (Payload Format Invalid). This is one of the negative acknowledgements that MQTT 5’s improved feedback makes possible, and it lets the broker refuse a specific publish without dropping the entire connection.

This validation is optional on the broker side; not every broker performs it. But the possibility is there, and it is what makes the indicator meaningful as a contract rather than a hint. A publisher setting Payload Format Indicator = 1 is committing to a UTF-8 payload; if the payload is not actually UTF-8, the publish may be rejected.

When to use each value

Setting Payload Format Indicator = 1 is appropriate when the payload is genuinely UTF-8 text: JSON, XML, plain-text log lines, human-readable messages, structured formats that are themselves text. In these cases the indicator both improves receiver processing (the payload can be decoded to a string with confidence) and gives the broker the option to validate.

Setting Payload Format Indicator = 0, or omitting the property, is appropriate for binary payloads: images, protobuf, MessagePack, encrypted data, raw sensor readings in binary form, or any format where the bytes are not text. The default is 0, so binary payloads simply do not need to set the indicator at all.

The indicator does not say more than “text or bytes.” For anything more specific about the payload — that it is JSON, or a specific MIME type, or a particular schema version — you use the Content Type property.

Content Type

The Content Type property is a UTF-8 string attached to a PUBLISH (or a will publish) that identifies the specific format of the payload. Unlike the indicator, which is a two-value byte, the Content Type is free-form: any UTF-8 string that both publisher and subscriber understand.

The MQTT 5 specification does not mandate what the Content Type string must look like. In practice, the near-universal convention is to use a MIME type — the same string format that HTTP uses in its Content-Type header. Examples include:

  • application/json — for JSON payloads
  • application/xml or text/xml — for XML payloads
  • text/plain — for plain text
  • text/csv — for comma-separated values
  • application/x-protobuf — for Protocol Buffers
  • image/png, image/jpeg — for images
  • application/octet-stream — for generic binary data
  • application/vnd.acme.sensor.v2+json — for application-specific formats with a versioned MIME type

Using MIME types has significant advantages. They are a well-known, IANA-registered set of identifiers that developers already know how to interpret from HTTP. Existing tools and libraries can parse them. New consumers can look up an unfamiliar MIME type in standard references. And they compose cleanly: an application-specific format can register a custom MIME type and use it in MQTT the same way it would in HTTP.

Nothing in MQTT 5 requires the Content Type to be a valid MIME type. If your system has its own convention (sensor-v2, internal:protobuf, whatever), the protocol will pass it through. But using MIME types is strongly recommended for anything that will be consumed by more than one team or more than one system, because it aligns with a body of existing tooling and convention.

Content Type and Payload Format Indicator together

The two properties are complementary. The indicator says whether the bytes are text or binary at the coarsest level; the Content Type says what specific format the payload is in. A JSON payload, for example, is naturally described by:

  • Payload Format Indicator = 1 (it is UTF-8 text)
  • Content Type = application/json (it is specifically JSON)

A protobuf payload:

  • Payload Format Indicator = 0 (it is binary)
  • Content Type = application/x-protobuf (specifically protobuf)

An image:

  • Payload Format Indicator = 0 (binary)
  • Content Type = image/png

Sending both properties gives the receiver the fastest and safest processing path. It knows immediately whether to decode the payload as text or bytes, and it knows exactly what format to expect inside.

Where the properties can appear

Both properties are PUBLISH properties, so they attach to individual messages. They can also appear as will properties inside a CONNECT, which means they apply to the will message the broker will publish on ungraceful disconnect. This is useful when the will message itself is structured data that consumers need to decode; the will is a normal PUBLISH once the broker sends it, and consumers benefit from the same format description that any other PUBLISH would carry.

The properties do not appear on CONNECT, CONNACK, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, or the QoS acknowledgement packets. They are strictly about describing the payload of a message, so they are only meaningful on messages that carry a payload.

What the broker does with them

For both properties, the broker’s behavior is simple: it forwards them unchanged to every subscriber that receives the message. They are message metadata, part of the description the publisher attached, and the broker’s job is to deliver them along with the payload. The publisher’s properties on a PUBLISH become the same properties on every delivered copy of that PUBLISH.

The one exception is the Payload Format Indicator, which the broker may optionally use to validate the payload. If Payload Format Indicator = 1 and the payload is not valid UTF-8, the broker is allowed (though not required) to reject the publish with reason code 0x99 (Payload Format Invalid). This is the only case where the broker inspects or acts on the format description; otherwise, the properties simply pass through.

Practical patterns

Two patterns come up often enough to be worth calling out.

Sending JSON in a way subscribers can trust

For JSON payloads, always set both properties: Payload Format Indicator = 1 and Content Type = application/json. This makes three useful things explicit:

  • The receiver knows it can decode the payload as UTF-8 text safely.
  • The receiver knows it should expect valid JSON and can parse accordingly.
  • If the payload accidentally is not valid UTF-8 (perhaps due to a bug), the broker may catch it and reject the publish before it reaches any subscriber, preventing bad data from spreading.

This is a cheap contract, and it makes JSON messaging in MQTT 5 as clean as it is in HTTP.

Describing binary data with a specific format

For binary payloads that have a specific structure — protobuf, MessagePack, a custom binary format — set Payload Format Indicator = 0 (or omit it) and Content Type to a MIME type identifying the format. A subscriber receiving Content-Type: application/x-protobuf can immediately hand the payload to the protobuf decoder without needing to know from the topic name that this is what it will get.

For binary payloads with no particular structure — an encrypted blob, an image whose format is unknown, arbitrary bytes — the Content Type may be application/octet-stream or omitted entirely. The default behavior (no indicator, no content type) is the MQTT 3.1.1 behavior, and it remains a valid choice when there is genuinely nothing useful to say about the format.

A worked example: schema-versioned JSON

To see the properties working together with related MQTT 5 features, trace a versioned JSON message through the broker.

A publisher wants to send a temperature reading in JSON, but the payload schema has changed over time and subscribers may be running different versions of the parser. It publishes to sensors/site-a/temperature:

Payload:  {"value": 22.4, "unit": "celsius", "ts": 1710000000}

Payload Format Indicator: 1
Content Type:             application/vnd.acme.temperature.v2+json
User properties:
  schema-version = "2"
  publisher      = "device-7"
  trace-id       = "abc123"

The Content Type uses a vendor-specific MIME type with a version suffixapplication/vnd.acme.temperature.v2+json — following the standard vnd. prefix convention for organization-specific MIME types. The +json suffix tells any generic JSON tooling that despite the specific media type, the payload can be parsed as JSON. The user property schema-version = "2" duplicates the version information in a form easier to branch on, since a subscriber can compare integers more cheaply than parsing a MIME type.

Two subscribers receive the message:

  • A v2-aware subscriber reads the Content Type, recognizes application/vnd.acme.temperature.v2+json, and processes the payload with its v2 parser. It gets exactly what it expects.
  • A legacy v1 subscriber reads the Content Type and does not recognize v2. Rather than crashing, it inspects the schema-version user property, sees "2", and applies its v1-to-v2 compatibility logic (or logs the mismatch and discards the message, depending on its policy).

Without payload format description, the legacy subscriber would have to parse the payload just to discover its version, and might not detect the mismatch until it encountered fields it did not expect. With the format description properties, the version is visible at the protocol level, before the payload is even opened. Both properties working together — Content Type at the protocol level, plus user property for cheap branching — is a common and effective pattern for schema-versioned messaging.

Debugging Payload Format Invalid errors

Because the Payload Format Indicator is one of the few properties the broker can validate against, it is also one of the few that produces a specific negative acknowledgement when things go wrong: reason code 0x99 (Payload Format Invalid). Understanding when this fires, and how to debug it, is a useful piece of practical knowledge.

The reason code appears on PUBACK (for QoS 1 publishes) or PUBREC (for QoS 2) when the broker has validated the payload against Payload Format Indicator = 1 and found it not to be valid UTF-8. It can also appear on a broker-sent DISCONNECT if the broker decides to terminate the connection over repeated violations. The exact policy depends on the broker.

Common causes of the error, in rough order of frequency:

Wrong encoding somewhere upstream. The publisher is producing what it thinks is UTF-8, but the source data is actually in another encoding (Latin-1, UTF-16, Windows-1252). The bytes look like text when displayed with the right decoder, but they are not valid UTF-8 and the broker rejects them. Fix by explicitly encoding to UTF-8 before publishing.

Binary data marked as text by mistake. A payload that is actually binary (perhaps a compressed JSON, a protobuf message, or a raw image) has been published with Payload Format Indicator = 1 because the publisher assumed all payloads were text. Fix by setting the indicator to 0 (or omitting it) for binary payloads. The presence of application/octet-stream or similar in Content Type is often a hint that the indicator should not be 1.

Corrupt or truncated payloads. If a payload is corrupted between the application and the network — a partial write, a broken serialization, an off-by-one in a byte buffer — the result may look like UTF-8 in some regions and not in others, and the broker’s validator catches the invalid regions. Fix by finding the corruption at the source.

Byte order marks (BOMs) and other UTF-8 subtleties. UTF-8 does not require a BOM, and some UTF-8 validators accept BOMs while others do not. If your publisher is prepending a BOM and the broker is strict, this can trigger the error. Similarly, invalid UTF-8 sequences that some libraries will “clean up” silently on decode may be rejected outright by the broker.

The broker’s behavior on Payload Format Invalid is optional and configurable in most implementations. Some brokers ignore the indicator entirely and forward everything unchanged; some validate strictly and reject; some do both depending on configuration. If you are getting mysterious rejections on a topic that seems to be working elsewhere, checking whether the specific broker validates Payload Format Indicator = 1 is a useful diagnostic. Consult the broker’s documentation for the specific validation policy.

Finally, the error is a negative acknowledgement on a specific publish, not a fatal error. The connection remains open, and the publisher can immediately publish again with a corrected payload. This is one of the everyday benefits of MQTT 5’s expanded reason codes: a specific publish problem produces a specific error, not a mysterious connection drop.

Comparison with user properties

MQTT 5’s user properties (covered in their own article) also let a publisher attach metadata to a PUBLISH, so it is worth being clear about when to use payload format description and when to use user properties.

Use payload format description for what the payload is. The type of the data — its encoding (text or bytes) and its format (JSON, protobuf, PNG). This is what the Payload Format Indicator and Content Type properties are designed for, and receivers will handle them consistently because they are standard protocol properties with well-defined meaning.

Use user properties for everything else. Application-defined metadata about the publisher, the message’s trace ID, the schema version, the tenant, the units, the priority — anything that is not “what format is this” belongs in user properties. User properties are more flexible but also more application-specific.

The two mechanisms complement each other rather than competing. A well-described message might carry Payload Format Indicator = 1, Content Type = application/json, and user properties like schema-version = "2.1", publisher = "device-7", and trace-id = "abc123". The standard properties describe the payload; the user properties describe everything else about the message.

Common misconceptions

A few things people believe about payload format description that are not quite right.

“The broker validates JSON automatically if I set Content Type to application/json.” No. The broker does not parse Content Type or validate against it. Only Payload Format Indicator = 1 gives the broker the option to validate UTF-8 encoding, and even that is optional. Content Type is purely descriptive metadata for subscribers.

“Setting Content Type is required for JSON.” No. Both properties are optional. Setting them is strongly recommended for the reasons above, but a payload without them is still a valid PUBLISH; the broker will forward it, and subscribers will receive it. The properties give the receiver more information; they do not gate delivery.

“Payload Format Indicator = 1 means the payload is JSON.” No. It only means the payload is UTF-8 text. JSON, XML, CSV, and plain text are all UTF-8 text. The Content Type is what distinguishes them.

“Content Type must be a MIME type.” No, technically. Any UTF-8 string is legal. But MIME types are strongly recommended because they align with well-known conventions and tooling.

“These properties exist in MQTT 3.1.1.” No. They are new in MQTT 5. In MQTT 3.1.1, format description had to be handled by topic conventions or payload envelopes.

How payload format description connects to the rest of MQTT 5

Payload format description is one of the smaller MQTT 5 features by scope, but it touches several others:

  • PUBLISH is the packet these properties attach to, as covered in the publish/subscribe operations article.
  • Will messages can carry these properties, so a will payload can be self-describing when the broker publishes it (see the Last Will and Testament article).
  • User properties complement payload format description for application-level metadata (see the User Properties article).
  • Negative acknowledgements are what let the broker reject a payload that violates Payload Format Indicator = 1 (see the Improved Client Feedback and Negative Acknowledgements article).
  • MQTT 5 as a whole frames why properties exist and how they change the protocol; see the What’s New in MQTT 5 article.

Used consistently, payload format description turns implicit “everyone knows this topic is JSON” agreements into explicit protocol-level contracts that new consumers can pick up without out-of-band coordination.

Frequently asked questions

What is the Payload Format Indicator in MQTT 5? A single-byte property on a PUBLISH that says whether the payload is an unspecified byte stream (value 0) or UTF-8 encoded text (value 1). It is optional; when absent, the default is 0.

What is the Content Type property in MQTT 5? An optional UTF-8 string property on a PUBLISH that identifies the specific format of the payload. It is typically set to a MIME type such as application/json or image/png, though any UTF-8 string is technically valid.

Are these properties available in MQTT 3.1.1? No. Both are new in MQTT 5. MQTT 3.1.1 has no protocol-level way to describe the payload format; applications had to encode this in topics or inside payloads.

Does the broker validate payloads based on these properties? Only for Payload Format Indicator = 1, and only optionally. A broker may reject a PUBLISH whose payload is marked as UTF-8 but is not valid UTF-8, using reason code 0x99 (Payload Format Invalid). The broker does not validate against Content Type.

Should I always set Content Type? It is strongly recommended for any payload with a well-known format, especially when multiple teams or systems consume the messages. It costs almost nothing to include and gives subscribers explicit information about how to process the payload.

What MIME type should I use for binary data with no specific format? application/octet-stream is the standard MIME type for arbitrary binary data. Or you can omit the Content Type property entirely; there is no requirement to set it.

Can I use payload format description without user properties, or vice versa? Yes. The two mechanisms are independent. Payload format description covers “what the payload is”; user properties cover “everything else about the message.” A PUBLISH can carry either, both, or neither.

Do these properties travel to subscribers, or are they only between publisher and broker? They travel to subscribers. Both are PUBLISH properties, and the broker forwards them unchanged to every subscriber that receives the message. Subscribers can read the properties on the delivered PUBLISH exactly as the publisher set them.

What happens if a receiver does not understand the Content Type I sent? It is up to the receiver. The protocol delivers the message regardless. A receiver that recognizes the Content Type can process the payload appropriately; a receiver that does not may fall back to a default behavior, log a warning, or discard the message. This is application logic, not a protocol concern.

Author: Zakaria El Intissar

I've spent 13 years in power system automation, electrical protection, and SCADA communication, as an automation and industrial computing engineer. ScadaProtocols.com is where I turn what I've learned on site into plain guides and working tools — so other engineers can decode, analyze, and troubleshoot industrial communication protocols without the guesswork.