Deliverability

SMS delivery receipts vs HLR lookup: before or after you send

A delivery receipt reports what happened after you sent an SMS. An HLR lookup asks the network before you send. What each can see, miss and cost.

By Published 7 min read

On this page

A delivery receipt (DLR) tells you what happened to a message after you sent it. An HLR lookup asks the recipient's home network, before you send, whether the number is assigned and reachable. The receipt is free with most sends but arrives late. The lookup costs a query but saves wasted sends. Many teams use both.

What does each one answer?

Both come from the same mobile network machinery, at different moments. The comparison in one table:

Delivery receipt (DLR)HLR lookup
WhenAfter the send, seconds to days laterBefore the send
QuestionWhat happened to this message?Is this number assigned and reachable now?
SourceThe message centre, based on the delivery attemptThe number's home network register
CostUsually included with the messageA paid query per number
Works forEvery message you sendMobile numbers only
Can't seeAnything before you paid; readsThe handset's inbox, filters, content blocks
Typical useReporting, retries, support ticketsOTP pre-checks, list cleaning, routing

The short version: a DLR is an outcome, an HLR lookup is a forecast. Our glossary has short entries on the delivery receipt and the HLR lookup.

A phone with chat bubbles; one messaging-app check says registered, another is unknown.A phone with chat bubbles; one messaging-app check says registered, another is unknown.
Messaging-app checks answer registered, not registered or unknown, with the time we checked.

How does a delivery receipt work?

When you submit a message, your provider (or you, if you connect directly) can request a receipt. In SMPP, the protocol most message centres speak, you set a flag on the submission, and the message centre later sends back a receipt as a separate message. The SMPP 3.4 specification is blunt about it: "To determine the eventual outcome of the SMS delivery, the ESME must request an SMSC Delivery Receipt" (SMPP Developers Forum).

The specification lists the final message states a receipt can carry:

StateReceipt textMeaning
DELIVEREDDELIVRDDelivered to the destination
EXPIREDEXPIREDThe validity period ran out before delivery
DELETEDDELETEDThe message was deleted
UNDELIVERABLEUNDELIVThe message can't be delivered
ACCEPTEDACCEPTDAccepted on the subscriber's behalf
UNKNOWNUNKNOWNInvalid state
REJECTEDREJECTDRejected

Two details matter in practice. First, the spec gives only a "typical example" of the receipt text and leaves the exact format to each message-centre implementation. Second, the err field "may hold a Network specific error code or an SMSC error code", and those codes are not standardized in SMPP (SMPP Developers Forum). Your provider translates them, or passes them through.

Inside the mobile network, the handset's acknowledgement travels back as an SMS status report, defined in 3GPP TS 23.040 (3GPP). That is where a real DELIVRD comes from.

Is a DLR proof of delivery?

It is strong evidence, with caveats:

  • Some routes answer early. An intermediary can report delivery when it hands the message on, not when the phone confirms. The result looks like a delivered message that nobody received.
  • Receipts can be slow. Amazon notes that "depending on the destination phone number's carrier, it can take up to 72 hours for delivery logs to appear" (AWS).
  • Delivered isn't read. The handset may file the message as spam or hide it.
  • No receipt isn't failure. Missing receipts are common on some routes.

For OTP, the verification rate (codes entered ÷ codes sent) is a more honest delivery metric than receipts. For marketing and notices with consent, receipts are what you have. Watch them per route and per country, not only in total.

How does an HLR lookup work?

Before an SMS can reach a mobile phone on another network, the sending side asks the recipient's home network where to deliver it. That routing query, part of the MAP protocol in 3GPP TS 29.002 (3GPP), is what an HLR lookup performs, without sending a message. The reply shows whether the number is assigned, whether the subscriber can be reached, and which network currently holds the subscription, so it also reveals porting.

It has limits. It works only for mobile numbers. Some operators block or mask external queries. And the raw reply contains identifiers, such as the IMSI and the serving switch address, that should never leave the telecom side. The HLR vs MNP vs number validation guide covers the wider comparison.

What do the network errors mean?

Whether you meet them in a receipt's error field or in an HLR reply, the same MAP errors keep coming up. The names come from 3GPP TS 29.002. The codes are the MAP local error values in its error module (3GPP).

MAP error (code)Plain meaningWhat to do
unknownSubscriber (1)The number isn't assigned on the home networkRemove it; re-confirm the contact
absentSubscriberSM (6)The phone couldn't take a text right nowRetry later, or offer another channel for OTP
teleserviceNotProvisioned (11)The subscription doesn't include SMSUse another channel
callBarred (13)Barred by the operator or subscriberStop; don't retry in a loop
absentSubscriber (27)The subscriber couldn't be reachedSame as absent for SMS
subscriberBusyForMT-SMS (31)The phone is busy with another deliveryRetry shortly
sm-DeliveryFailure (32)Delivery to the handset failed (for example, memory full)Retry later
systemFailure (34)A network problem, not the numberRetry; don't blame the number

Your provider may show these under its own labels. The point is the category: not assigned (stop), temporarily unreachable (retry or switch channel), not allowed (stop), network trouble (retry).

Should you run the lookup before or after sending?

It depends on what a failed send costs you. A decision table:

SituationUseWhy
OTP by SMSValidation + line type before; live status before where availableA code that can't arrive costs a user. Switch channel at once
Transactional notices to active customersDelivery receipts afterNumbers recently worked; retries handle short outages
First campaign to an old consented listLive status beforeRemoves unassigned numbers before you pay for each message
Routing by current networkCarrier or live status beforePrefix-based routing is wrong for ported numbers
Support ticket "I never got it"Receipt first, then a lookupThe receipt shows the outcome; the lookup shows the number's state now
Landlines or VoIPLine type beforeHLR queries don't apply

A rough rule: if you'd act differently depending on the answer, and you'd have to act before a receipt arrives, check before sending.

What does MobileValidate offer today?

Today, validation and normalization run free on every request, and the carrier lookup returns line type, current carrier, country and, when a number was ported, the original carrier. The HLR lookup is coming soon. It is switched off for everyone, including test keys:

Shell
curl https://api.mobilevalidate.com/v1/lookup \
  -H "Authorization: Bearer $MOBILEVALIDATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"numbers": ["+447700900001"], "checks": ["hlr"]}'
JSON
{"error": {"code": "service_disabled", "message": "The check 'number.hlr' is currently unavailable.",
  "status": 403, "retryable": false, "param": "checks[0]",
  "doc_url": "https://mobilevalidate.com/docs/errors#service_disabled"}}

When it launches, number.hlr will return status (reachable, unreachable, invalid or unknown), ported, roaming as true or false only, network, mcc_mnc and country. It will never return the IMSI, the serving switch, cell or location. The test numbers are already defined on the test mode page, so you can write the handling code now.

On billing: reachable, unreachable and invalid will be conclusive and billed. You're not charged for inconclusive results (unknown, unsupported country, timeout, invalid, duplicate). Delivery receipts come from your messaging provider, not from us.

How do you use both together?

The two signals complement each other, and the combination catches things neither sees alone:

  1. Before sending: normalize, check line type, and (once available) check live status for high-stakes sends.
  2. At send time: request delivery receipts and store the message ID with the number's checked_at.
  3. After sending: classify receipt errors into stop, retry or switch channel.
  4. Feed back: numbers with unknownSubscriber receipts go to a re-check or removal list. Numbers absent for weeks get re-confirmed.
  5. Measure: track delivered-receipt rate and, for OTP, verification rate per country and route.

How should you store and act on receipts?

Receipts are only useful if you can join them back to a number and a decision. A few habits make that easy:

  • Store the message ID your provider returns, with the masked number, the country, the route or sender ID and the time of sending.
  • Keep the raw status and error next to your own category (delivered, retry, stop, switch channel). Provider labels change. Your categories shouldn't.
  • Set a deadline. If no final receipt arrives within your window (minutes for OTP, a day or more for notices), record "no receipt" as its own state instead of assuming success.
  • Count per number over time. One failure is noise. Three unknownSubscriber answers in a row are a pattern worth acting on.
  • Don't keep more than you need. Delivery logs contain phone numbers, so apply the same retention rules as for the rest of your customer data.

What are the key takeaways?

  • A delivery receipt reports the outcome after you paid. An HLR lookup forecasts reachability before you send.
  • SMPP defines receipt states such as DELIVRD, EXPIRED and UNDELIV, but leaves the text format and error codes to each implementation.
  • Receipts can be early, late or missing, so use verification rates for OTP.
  • MAP errors fall into four groups: not assigned, temporarily unreachable, not allowed and network trouble. Act on the group.
  • MobileValidate's carrier lookup is available now. The HLR lookup is coming soon and will never expose SIM or location identifiers.

For the full list of reasons a text doesn't arrive, read why SMS messages aren't delivered. For checking whether a number is in use at all, see how to check if a phone number is active.

Sources

  1. Short Message Peer to Peer Protocol Specification v3.4, Issue 1.2 — SMPP Developers Forum, 1999
  2. 3GPP TS 29.002: Mobile Application Part (MAP) specification — 3GPP
  3. 3GPP TS 23.040: Technical realization of the Short Message Service (SMS) — 3GPP
  4. Amazon SNS SMS delivery monitoring with Amazon CloudWatch metrics and logs — Amazon Web Services

Frequently asked questions

Is a delivery receipt proof that the message was delivered?

It is the best evidence you get, but not proof. A final DELIVRD status normally means the network reports delivery to the handset. Receipt formats vary between message centres, some routes send receipts before the handset confirms, and delivered doesn't mean read.

Should I run an HLR lookup before or after sending?

Before, when a failed send is expensive or time-critical, such as OTP or large campaigns to old lists. After, a delivery receipt is enough for everyday transactional messages to numbers that recently worked.

What does absent subscriber code 27 mean?

In the MAP protocol, error 27 is absentSubscriber: the subscriber couldn't be reached. For text messages the network usually reports absentSubscriberSM (error 6). Both mean the phone was off or out of reach at that moment, not that the number is invalid.

Does MobileValidate offer HLR lookups?

The HLR lookup is coming soon. Requests are refused with 403 service_disabled today. The carrier lookup is available now and returns line type, current carrier and a porting hint.

All articles

Know before you send.

Tell us about your use case. We review every request and set you up with test and live keys.