Online PDU Encoder for SMS-SUBMIT Messages
Turn a message into the hex string a GSM modem expects in PDU mode. The encoder packs GSM-7 septets, switches to UCS-2 when it has to, and adds a UDH when the message needs more than one part.
Encode a message into an SMS-SUBMIT PDU
The form starts with a known example. Change the text, the number or the options, then press Encode. The output is built by JavaScript on this machine.
PDU encoder
Offline| Part | UDH | Text in this part |
|---|
Each block starts with ----- PDU n/total -----. In PDU mode, send the hex of each block separately.
Nothing typed here is posted anywhere. The page works from a local file or from an offline copy of this site.
What PDU mode is
PDU mode hands the modem a complete protocol frame instead of a plain string.
An SMS is not just text. Around the message sit a service centre address, a destination, an encoding marker, a validity period and a length field. In text mode (AT+CMGF=1) the modem fills those in for you and shows only the readable part. In PDU mode (AT+CMGF=0) you supply the whole frame in hexadecimal, so every field is under your control.
The frame is defined in 3GPP TS 23.040. The character alphabet and its 7-bit packing are defined in TS 23.038. This encoder follows both: it removes non-digits from the number, swaps the remaining pairs into BCD, sets the type-of-address octet, selects GSM-7 or UCS-2, packs septets in order, and sets the user-data header indicator when a message is split.
Why the text looks odd. Seven-bit characters are packed into eight-bit octets, so one septet can straddle two bytes. A GSM-7 PDU is therefore not a byte-per-character dump, and editing it by hand breaks easily.
Why the first octet matters. The octet after the service centre carries the message type, the delivery-report flag and the concatenation flag. This encoder writes 0x01 plus 0x40 for a split message, 0x10 when a validity period is set and 0x20 when you request a report.
SMS-SUBMIT field structure
Reading the output from left to right, the fields are:
| Field | Octets | What it carries | What this encoder writes |
|---|---|---|---|
| SCA | 1 + n | Service centre address and its type-of-address octet | 00 when you leave it empty, otherwise the length octet, the type-of-address and the BCD digits |
| First octet | 1 | Message type, validity format, report request, user-data header flag | 01 for SMS-SUBMIT, with 40, 10 and 20 added as needed |
| MR | 1 | Message reference incremented by the handset | The concatenation reference, truncated to one octet; 00 when not set |
| Destination | 2 + n | Number length, type-of-address and BCD digits | 81 for a national number, 91 when the input starts with + |
| PID | 1 | Protocol identifier | 00, a normal short message |
| DCS | 1 | Alphabet and message class | 00 GSM-7, 08 UCS-2, 10 or 18 for a flash message |
| VP | 0, 1 or 7 | Validity period, relative, enhanced or absolute | Left out at 0 hours; otherwise one relative octet whose step size grows with the range (5-minute, half-hour, daily, weekly) |
| UDL | 1 | Length of the user data | Septet count for GSM-7 (the UDH is counted as septets), octet count for UCS-2 |
| UD | n | Optional UDH plus the packed text | 7-bit packed after a byte-aligned UDH, or big-endian UCS-2 |
The relative validity period uses one octet: values 0–143 count 5-minute steps up to 12 hours, 144–169 half-hour steps to 24 hours, 170–196 days up to 30 days and 197–255 weeks beyond that, all counted from the moment the service centre receives the message. This tool accepts 0–8760 hours (about one year).
GSM-7, UCS-2 and concatenated SMS
One PDU carries 140 octets. How many characters fit depends on the alphabet and on whether a UDH is present.
| Encoding | Single PDU | With an 8-bit UDH | With a 16-bit UDH |
|---|---|---|---|
| GSM-7 | 160 septets | 153 septets | 152 septets |
| UCS-2 | 70 units | 67 units | 66 units |
A UDH of 6 bytes takes 48 bits, which rounds up to 7 septet slots in GSM-7; a 16-bit reference adds one more octet and one more slot. This is why the split limits are 153 or 152 rather than 160.
GSM-7 covers the Latin letters, digits and punctuation that the original GSM alphabet defines. Ten characters need two septets: €, ^, {, }, [, ], ~, |, the backslash and the form-feed character. The encoder writes the escape code 1B before each of them and never splits a pair across two parts. Anything outside both tables forces UCS-2, where each character becomes two octets and the limit drops to 70.
Worked examples
These outputs come from the regression file that ships with this page. The inputs are unchanged and the expected hex was produced by an independent implementation of TS 23.038 / TS 23.040.
| Input | Encoding | PDU |
|---|---|---|
| Hello SMSDeliverer.com! | GSM-7, national number, no service centre | 000100098121436587F9000017C8329BFD064D9B5362999DB697E565B96BFC6E8700 |
| € | GSM-7 extension character | 000100098121436587F90000029B32 |
| 您好,世界! | UCS-2 | 000100098121436587F900080C60A8597DFF0C4E16754CFF01 |
The test record is assets/js/tests/pdu-vectors.json. It also keeps one string recorded from an older build; that vector is marked as failing with its defects written down, not edited until it passes.
When to use PDU instead of text mode
Text mode is easier to read. PDU mode is the only way to control what is actually sent.
Long messages
A concatenated SMS is several PDUs tied together by a UDH. The parts, their order and the reference number are visible only in PDU mode.
Integration work
If you build a gateway, a test harness or a queue that hands frames to AT+CMGS, you need the exact octets rather than a modem's interpretation of a string.
Diagnosis
Garbled text, missing accents and split messages usually come from a wrong DCS or a broken UDH. Both are visible here.
Both modes reach the same network and bill the same way. The difference is where the frame is assembled: inside the modem, or in software you can inspect. When a message must carry a specific alphabet, a validity period or a delivery-report request, PDU mode is the shorter path. Text mode still has a place for a quick manual test, and the decoder on this site can read either frame once it arrives.
Need an automated solution?
This page is a reference tool. SMS Deliverer does the same work for every message in a queue.
The Windows application splits long messages, chooses GSM-7 or UCS-2, sets a UDH reference, retries failed parts and stores the delivery report against the contact. The same encoding path is used whether you send one message or a few thousand, and the SIM cards in your own modems carry the traffic.
The GSM modem guide explains the hardware side, the desktop software page lists the sending and reporting features, and the PDU decoder reads frames captured from a modem or a phone.
Included in the encoder output
- GSM-7 septet packing and extension pairs
- UCS-2 with surrogate pairs kept whole
- 8-bit and 16-bit concatenation references
- National and international destination formats
- Relative validity period and flash class
Reviewed 2026-11. A free trial covers the send path end to end; this tool needs no licence and no installation.
Questions buyers ask
Is this encoder free, and does it need an account?
It is free and needs no account. The page is plain HTML and JavaScript, and it works from an offline copy of the site as well.
Why does my PDU start with 00?
The first octet is the service centre address length. 00 means the PDU carries no service centre, so the handset or modem uses the one stored on the SIM. Enter a service centre number if you want it written into the frame.
Why did a long message turn into several PDUs?
One PDU holds 140 octets. GSM-7 fits 160 septets, or 153 when a 6-byte UDH is present; UCS-2 fits 70, or 67 with the same header. The text is split on a character boundary and each part gets a sequence number.
Can I send the output with AT+CMGS?
Yes. Set the modem to PDU mode with AT+CMGF=0, then pass the octet count of the frame after the service centre field. Send one part at a time and keep the order, because the handset reassembles the parts by the UDH reference and sequence.