Sparkplug B data types define exactly how each metric value is encoded, from an 8-bit signed integer to a full table of rows and columns. This reference lists every datatype code with the Protobuf field it uses, explains metric properties and quality codes, and shows decoded examples so you can recognise each type when you inspect real traffic.
Why Sparkplug Has Its Own Data Types
JSON has numbers, strings and booleans. Industrial systems need more precision than that. A PLC register might be an unsigned 16-bit integer, a counter might be a 64-bit unsigned value, and a timestamp must not be confused with an ordinary number. Sparkplug B gives every metric an explicit datatype code so that a host application on the other side of the world interprets the value exactly as the edge node intended.
The datatype is declared for every metric in birth messages. Data messages can omit it, which is why consumers store datatypes from the births, as described in our Sparkplug B payload guide.
Scalar Sparkplug B Data Types
| Code | Name | Protobuf value field | Notes |
|---|---|---|---|
| 0 | Unknown | none | Placeholder, should not appear in valid metrics |
| 1 | Int8 | int_value | Signed, two's complement in an unsigned field |
| 2 | Int16 | int_value | Signed, two's complement |
| 3 | Int32 | int_value | Signed, two's complement |
| 4 | Int64 | long_value | Signed, two's complement in uint64 |
| 5 | UInt8 | int_value | Unsigned |
| 6 | UInt16 | int_value | Unsigned |
| 7 | UInt32 | int_value | Unsigned |
| 8 | UInt64 | long_value | Unsigned |
| 9 | Float | float_value | 32-bit IEEE 754 |
| 10 | Double | double_value | 64-bit IEEE 754 |
| 11 | Boolean | boolean_value | true or false |
| 12 | String | string_value | UTF-8 text |
| 13 | DateTime | long_value | Milliseconds since Unix epoch, UTC |
| 14 | Text | string_value | Longer text, same encoding as String |
| 15 | UUID | string_value | UUID in string form |
| 16 | DataSet | dataset_value | Table of typed columns and rows |
| 17 | Bytes | bytes_value | Raw binary data |
| 18 | File | bytes_value | File content, described by MetaData |
| 19 | Template | template_value | User-defined type or instance |
Codes 20 and 21 (PropertySet and PropertySetList) are used for property values, not metric values.
The signed integer trap
The most common decoding bug in Sparkplug is reading signed integers directly. Because int_value is an unsigned 32-bit field, an Int32 of -5 arrives as 4294967291, and an Int64 of -1 arrives as 18446744073709551615 in long_value. The consumer must apply two's complement using the declared datatype. Edge nodes must do the reverse when encoding. If a dashboard suddenly shows a temperature of four billion degrees, this is almost always the reason.
DateTime is not a number
A DateTime metric and an Int64 metric use the same field, but they mean different things. Treat DateTime as milliseconds since the epoch in UTC and convert it for display. Never send seconds, and never send local time.
Array Data Types
Sparkplug also defines arrays of scalar types. They travel in bytes_value as packed little-endian values, an encoding that Sparkplug 3.0 spells out precisely (see our Sparkplug 3.0 comparison for what else was clarified).
| Code | Name | Code | Name |
|---|---|---|---|
| 22 | Int8Array | 29 | UInt64Array |
| 23 | Int16Array | 30 | FloatArray |
| 24 | Int32Array | 31 | DoubleArray |
| 25 | Int64Array | 32 | BooleanArray |
| 26 | UInt8Array | 33 | StringArray |
| 27 | UInt16Array | 34 | DateTimeArray |
| 28 | UInt32Array |
Array support varies between products. If you depend on arrays across vendors, test them early with both ends connected to the same broker.
Metric Flags
Each metric can carry boolean flags that change how consumers treat it:
| Flag | Meaning | Consumer behaviour |
|---|---|---|
| is_null | The metric exists but has no value | Show as null or bad quality, do not substitute zero |
| is_historical | Value is from the past, for example store and forward | Store it, do not overwrite the live value |
| is_transient | Value should not be historized | Display it, do not store it |
Metrics also have an optional timestamp, separate from the payload timestamp. Use it to record when the value was sampled at the source.
Metric Properties
A metric can carry a PropertySet: parallel lists of keys and typed values. Property values use the same datatype codes plus PropertySet (20) and PropertySetList (21), which allow nesting.
The Quality property
The one property the specification gives a defined meaning is Quality, an Int32:
| Value | Meaning |
|---|---|
| 192 | Good |
| 0 | Bad |
| 500 | Stale |
A host that receives a metric with Quality 0 should display it as bad, even if a value is present. Many edge platforms set Quality 500 when they lose contact with the underlying device but still keep the node connected.
Other common properties
Engineering units, ranges, descriptions and display formats are frequently carried as properties, but their key names are conventions of each platform rather than part of the specification. Agree on a property vocabulary across your edge nodes, or your host application will see the same concept under different keys.
DataSets
A DataSet is a small typed table inside a single metric. It has a column count, column names, a datatype code for each column and a list of rows. Each row value uses a restricted set of fields: int, long, float, double, boolean or string.
Decoded, a recipe parameter table might look like this:
{
"name": "Recipe/Steps",
"datatype": 16,
"datasetValue": {
"numOfColumns": 3,
"columns": ["Step", "Temperature", "Duration"],
"types": [3, 9, 7],
"rows": [
{ "elements": [{ "intValue": 1 }, { "floatValue": 180.0 }, { "intValue": 600 }] },
{ "elements": [{ "intValue": 2 }, { "floatValue": 220.0 }, { "intValue": 300 }] }
]
}
}
DataSets are useful for batches of related values that must stay together. For structured equipment models, templates are usually a better fit; see Sparkplug templates and UDTs.
Decoded Examples
Here is a birth fragment with several data types and a Quality property, as you would see it after decoding:
[
{ "name": "Pump/Running", "alias": 1, "datatype": 11, "booleanValue": true },
{ "name": "Pump/Speed", "alias": 2, "datatype": 9, "floatValue": 1475.0,
"properties": { "keys": ["Quality"], "values": [{ "type": 3, "intValue": 192 }] } },
{ "name": "Pump/StartCount", "alias": 3, "datatype": 8, "longValue": "18342" },
{ "name": "Pump/LastService", "alias": 4, "datatype": 13, "longValue": "1789000000000" },
{ "name": "Pump/Offset", "alias": 5, "datatype": 2, "intValue": 4294967286 },
{ "name": "Pump/Serial", "alias": 6, "datatype": 12, "stringValue": "P-0042" }
]
Note the Int16 offset: the raw value 4294967286 is -10 after two's complement. Also note that some JSON renderings show 64-bit values as strings to avoid precision loss in JavaScript.
Checking Data Types in Practice
The quickest way to verify datatypes is to read decoded births. ConnectMQ decodes Sparkplug B in the portal topic explorer, so you can open an NBIRTH or DBIRTH and check each metric's datatype and value without writing code. For automated checks, the decoder in our tutorial on how to decode Sparkplug B in Python maps codes to names and handles signed conversion.
When you test on the public MQTT test broker, use a random group ID and remember everything there is readable by everyone.
Data Type Checklist for Edge Node Configuration
- Match each Sparkplug type to the source register type; do not widen everything to Double.
- Use unsigned types for counters that never go negative.
- Use DateTime for timestamps, always in milliseconds UTC.
- Set Quality on metrics whose source can fail independently of the node.
- Use is_null rather than zero when a value is unavailable.
- Flag store-and-forward data as historical.
- Agree on property key names across all edge nodes.
- Test arrays, DataSets and templates end to end before rollout.
Where Data Types Fit
Correct data types are what let Sparkplug data feed historians, SCADA and a Unified Namespace without per-tag fixes. For architecture guidance, see the Industrial IoT with MQTT guide. Any compliant MQTT broker carries these payloads; a fully managed MQTT service that also decodes them makes verification much faster.
Get Started with ConnectMQ
Create a free Serverless broker at app.connectmq.com, no credit card required. Connect your edge node and check every metric's datatype, value and quality in the ConnectMQ topic explorer.
Frequently Asked Questions
How many Sparkplug B data types are there?
The specification defines scalar types with codes 1 to 19, property set types 20 and 21, and array types 22 to 34. Code 0 is Unknown.
Why is my negative Sparkplug value showing as a huge number?
Signed integers are stored in unsigned Protobuf fields. Apply two's complement based on the declared datatype, or use a decoder that does it for you.
What does Quality 192 mean in Sparkplug?
It means good quality. The Quality property uses 192 for good, 0 for bad and 500 for stale.
Are Sparkplug data types required in data messages?
They are required in birth messages and optional in NDATA and DDATA. Consumers should remember each metric's datatype from the birth.



