USSD Session Flow, Explained
Introduction¶
USSD (Unstructured Supplementary Service Data) is the interactive text menu
behind codes like *123# — balance checks, mobile money, roaming menus. Unlike
SMS it's session-oriented and real-time: the dialogue stays open while the
user navigates, and nothing is stored.
Two modes¶
- Pull / MMO (Mobile-originated) — the user dials
*123#. The network opens a session to the application, which returns a menu; the user replies, the app responds, until one side ends it. - Push / MTO (Mobile-terminated) — the network/app initiates a prompt to the handset ("Enter PIN to confirm payment"), the user responds.
Each response from the app is either:
USSD-Request— "here's a menu, I expect a reply" → session stays open.USSD-Notify— "here's a message, no reply needed" → session ends after the user dismisses it.
The message flow (pull, GSM/UMTS)¶
Handset MSC/VLR HLR / gsmSCF USSD Gateway / App
| *123# (RIL) | | |
|--------------->| MAP PROCESS_UNSTRUCTURED_SS_REQUEST |
| |------------------------------------------->| (routed by the
| | | | service code)
| | | app builds menu |
| |<-------------------------------------------| MAP USSD-Request
| menu shown | (RIL) | "1 Balance\n2 Buy" |
|<--------------| | |
| user: "1" | | |
|-------------->| MAP UNSTRUCTURED_SS_REQUEST (the reply) |
| |------------------------------------------->|
| |<-------------------------------------------| USSD-Request or
| result shown | | "Balance: $4.20" | USSD-Notify (end)
|<--------------| | |
- The service code (
*123#,*100#) determines routing. Codes are allocated by the operator; some are standardised (*#06#= IMEI, handled locally by the phone, never hits the network). - On the SS7 side it's MAP operations over TCAP:
processUnstructuredSS-Request(first),unstructuredSS-Request(app→user prompt),unstructuredSS-Notify(app→user, no reply). Modern gateways speak these over SIGTRAN and expose an HTTP/XML or SMPP-like API to the application. dcs(data coding scheme) — usually GSM 7-bit;0x0Fis common.
Session characteristics¶
- Stateful, short-lived. The MSC/VLR holds the session. There's a network timeout (often ~30–180s of inactivity) after which the session is torn down and the user sees "session expired".
- No delivery receipts, no store-and-forward. If the user has no signal, it just fails.
- One session per subscriber at a time on most networks.
- Payload limit ~182 bytes (GSM 7-bit ~160 chars) per message — design menus to fit.
Integrating an application¶
Aggregators/operators expose USSD to apps as an HTTP callback:
POST /ussd (from the gateway)
sessionId=abc123
msisdn=94771234567
serviceCode=*123#
text= <- empty on first request; "1" then "1*2" as the user drills in
Response body:
CON Welcome
1. Balance
2. Buy data <- "CON" = expect more input (session continues)
...later...
END Your balance is $4.20 <- "END" = terminate the session
text accumulates the user's path (1*2*100), so the app is effectively
stateless per request — parse text to know where the user is. Keep a
server-side session keyed by sessionId only if you need more than the path.
Verification and troubleshooting¶
# On the SS7/SIGTRAN side
tshark -i any -O tcap,gsm_ss -d sctp.port==2905,m3ua
*123#returns "connection problem or invalid MMI code" — no route for that service code, the gateway/app is down, or the SCCP GT for the USSD gateway isn't reachable. Also thrown for a genuinely malformed code.- Session expires mid-menu — user took too long (network inactivity timer),
or the app's response exceeded the size limit and was rejected, or the app
replied with
CON/USSD-Requestbut the transport dropped. - Menu shows but selections do nothing — the app isn't receiving the
follow-up (routing only set up for the first
processUnstructuredSS), or it's not parsing the accumulatedtext. - Works on-net, fails for roamers — inbound roamers' USSD may be handled by the home network (USSD is anchored at the VLR); "USSD when roaming" needs the home gsmSCF reachable via SS7 from the visited MSC.
- Non-Latin characters broken —
dcs/ encoding mismatch; USSD UCS-2 support is spotty on older handsets. - App gets duplicate callbacks — the gateway retried on a slow response.
Respond within ~1–2s; make handlers idempotent on
sessionId+text.
Related tools and reading¶
- On-site: Port Checker.
- Related posts: SMPP: bind types and message flow, SS7 vs SIGTRAN.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Telecom Systems
SMSC Basics for Sysadmins
The SMSC is the store-and-forward hub for text messages. Here's the message paths (MO, MT, AO, AT), how retries work, and a Kannel config to get started.
October 24, 2026eSIM and Remote SIM Provisioning
An eSIM is a reprogrammable chip (eUICC) that holds downloadable operator profiles. Here's the GSMA RSP architecture — SM-DP+, SM-DS, LPA — and the profile lifecycle.
October 24, 2026SIP Trunk Basics for Sysadmins
A sysadmin's view of SIP trunking — signalling vs media, the ports involved, and why one-way audio is almost always NAT.
October 24, 2026