SMPP PDU decoder.
Paste the hex of an SMPP v3.4 PDU to decode its 16-byte header — command_length, command_id (with its name), command_status and sequence_number — and see the mandatory body-field layout for submit_sm and deliver_sm. Nothing leaves your device.
ESME_ROK — No error
Header-only PDU — no body (typical of enquire_link, unbind and most _resp acknowledgements).
The short answer
What is an SMPP PDU?
A PDU (Protocol Data Unit) is a single SMPP message on the wire. Every PDU — a bind, a submit_sm, a delivery receipt, an enquire_link — starts with the same 16-byte header of four 32-bit big-endian integers: command_length (the total byte length including the header), command_id (which operation it is), command_status (the result, which is 0 / ESME_ROK on a successful response) and sequence_number (used to match a response to its request). Any body fields follow the header.
The 16-byte header layout
| Bytes | Field | Meaning |
|---|---|---|
| 0–3 | command_length | Total length of the PDU in octets, header included. |
| 4–7 | command_id | Identifies the operation (e.g. 0x00000004 = submit_sm). |
| 8–11 | command_status | Result code; 0 = ESME_ROK. Only meaningful on responses. |
| 12–15 | sequence_number | Correlates a request with its response. |
submit_sm / deliver_sm body fields
After the header, a submit_sm or deliver_sm carries its mandatory fields in a fixed order, optionally followed by TLV (optional) parameters. This tool lists the order; it does not fully parse the variable-length C-Octet strings, because their boundaries depend on null terminators and the sm_length field.
| Field | Type | Meaning |
|---|---|---|
| service_type | C-Octet String | Indicates SMS Application service (null = default). |
| source_addr_ton | Integer (1) | Type of Number of the sender. |
| source_addr_npi | Integer (1) | Numbering Plan Indicator of the sender. |
| source_addr | C-Octet String | Address of the message originator. |
| dest_addr_ton | Integer (1) | Type of Number of the recipient. |
| dest_addr_npi | Integer (1) | Numbering Plan Indicator of the recipient. |
| destination_addr | C-Octet String | Destination MSISDN / short code. |
| esm_class | Integer (1) | Message mode & type (e.g. 0x04 = delivery receipt). |
| protocol_id | Integer (1) | Protocol identifier (network specific). |
| priority_flag | Integer (1) | Priority level of the message. |
| schedule_delivery_time | C-Octet String | Scheduled delivery time (null = immediate). |
| validity_period | C-Octet String | Validity period of the message (null = default). |
| registered_delivery | Integer (1) | Whether a delivery receipt (DLR) is requested. |
| replace_if_present_flag | Integer (1) | Replace an existing message if present. |
| data_coding | Integer (1) | Encoding scheme (0 = GSM-7, 8 = UCS-2). |
| sm_default_msg_id | Integer (1) | Pre-defined message identifier. |
| sm_length | Integer (1) | Length in octets of the short_message field. |
| short_message | Octet String | The message payload (up to 254 octets). |
Frequently asked questions
What are the four fields in the SMPP header?
Every SMPP PDU begins with a 16-byte header of four 32-bit big-endian integers: command_length (total PDU length in octets including the header), command_id (the operation, such as 0x00000004 for submit_sm), command_status (the result code, 0 = ESME_ROK) and sequence_number (which correlates a response with its originating request).
Why is command_status usually 0 on my requests?
command_status is only meaningful on response and generic_nack PDUs. On request PDUs (submit_sm, bind, enquire_link) it is reserved and should be set to 0. A non-zero value on a _resp indicates an error — for example 0x00000058 is ESME_RTHROTTLED.
Are SMPP integers big-endian?
Yes. SMPP encodes multi-octet integers in network byte order (big-endian, most significant byte first). This decoder reads each 4-byte header field as a big-endian unsigned 32-bit integer.
Does this tool decode the message text?
It decodes the fixed 16-byte header and lists the body-field order for submit_sm and deliver_sm, but it does not parse the variable-length body into individual values. C-Octet strings are null-terminated and short_message length is carried in sm_length, so a full body parse depends on those boundaries — this tool keeps to the standards-based header layout.
Where can I look up a command_status I don't recognise?
Use the SMPP error-code reference, which lists every SMPP v3.4 command_status value by hex and symbolic name with a plain-English meaning and the likely cause and fix.
Need a real SMPP bind?
BroadNet offers direct SMPP 3.4 binds alongside a REST API and delivery webhooks across 200+ countries. Talk to our team about throughput and routing.