Test your app's SMS OTP flow with real numbers from other countries
Testing an SMS OTP flow from Nigeria? Why test numbers miss carrier behaviour, and what a real foreign number can and can't test in your sign-up flow.
5 min read

Your OTP flow passes in CI. The fictional numbers you set up in Firebase return the code you configured, and Twilio's test credentials report success without sending anything. Then the first real user in Toronto gets the code after your verify screen has timed out, and the one in Mumbai never gets it at all.
Those tools exercise your code path and stop at your SMS provider's API. Everything after that, the route across carriers into another country and onto a handset, only shows up when a real message goes to a real number.
What test numbers skip
Firebase's test phone numbers never send an SMS. Twilio's test credentials accept the request and send nothing. The Android emulator will take a fake SMS you type into its extended controls, and the iOS Simulator can't receive one at all. All of them are good for checking that your screens and your verify endpoint behave.
None of them tells you how long a message takes to reach a Kenyan or Canadian handset, whether your sender name survives the trip, whether a carrier filters it, or what your template looks like once it's split into segments. For that you need a real number in the country you care about.
Carrier behaviour worth a real SMS
| What to check | What goes wrong |
|---|---|
| Delivery time on international routes | The code lands after your verify screen has given up. The user taps resend, and two codes arrive with only the newer one valid |
| Sender ID | The US and Canada don't support alphanumeric sender IDs, so messages there come from a number instead of your brand name. India blocks messages whose sender ID and template aren't registered on its DLT platform |
| Encoding | One character outside the GSM-7 set, the naira sign included, switches the whole message to UCS-2 and drops a single message's limit from 160 characters to 70 |
| Filtering | Spam filters on carriers and handsets can drop messages that look promotional. In Nigeria, a message sent on a promotional route won't reach a line registered for Do Not Disturb through 2442, so ask your SMS provider which route your OTPs use |
Phone number input belongs on the same list, though it breaks on your side. A Nigerian types 0803 and a Briton types 07, both with a leading zero your backend has to drop before it adds the country code. Parse with Google's libphonenumber and store E.164. A hand-written regex that works for +234 tends to fail on the first country you didn't think about.
Running a sign-up from another country
The Awbit catalogue is organised by the app being verified, and your own app won't be in it by name. Buy one number first and confirm your own SMS shows on the order page before you plan a test run around it. Have your SMS provider's log open while you test, so you can see when each message left.
- Buy a number for the country you're testing. The naira price for that country shows before you confirm, and the number appears with a countdown.
- Enter it in your app the way a local user would, once with the leading zero and once with the full country code. Your backend should store the same E.164 number both times.
- Trigger the code. Note when your provider logged the send and when the SMS appeared on the order page.
- Read the message as it arrived, and check that the code and any special characters came through intact.
- Test resend while the window is open. Every SMS the number receives during the window is listed on the order page, so you can confirm the old code stops working once a new one is issued.
- Enter a wrong code, then an expired one, and check your lockout rules and error messages.
Each run costs the price of one number in that country, and prices differ between countries. If your SMS never shows, the order expires and the charge goes back to your wallet, except when the carrier rejects our cancel, in which case someone here settles the order by hand and emails you. Cancel before a code arrives and the full amount goes back, unless the supplier refuses to release the number, in which case the order runs to the end of its countdown. Using a number to test your own systems is fine with us. If a test touches someone else's platform, its terms are yours to check.
A single-use number can't test long-lived accounts
Each number lasts one short window and then goes back to the carrier. We don't rent numbers by the day or week. That rules out a set of tests you still need to run somewhere.
- Logging back in months later needs a number that is still yours by then, and so does any session-expiry flow that ends in a fresh code.
- Carriers reassign numbers that people abandon. Testing what happens when a new owner signs up on a number that already has an account in your system needs a number you control over time.
- The code shows on a web page instead of on your test handset, so iOS one-time-code autofill and Android's SMS Retriever API never see it. Test those with a SIM inside the device.
- Awbit numbers are sold for SMS verification. If your flow falls back to a voice call, test that on a phone you own.
- Delivery on MTN, Glo, Airtel and 9mobile, Do Not Disturb lines included, is best tested on real SIMs from each network, registered to your team. A Nigerian virtual number tells you about one line on one day.
Before you open sign-ups to every country
Once your OTP works in twenty countries, it will send an SMS to twenty countries for anyone who asks. SMS pumping fraud lives on that. Bots fill your sign-up form with numbers on premium ranges. Your provider sends a code to each one, and someone along the route takes a cut of what you pay per message.
Allow sending only to the countries you serve, and rate-limit codes per number and per IP address. Then watch the ratio of codes sent to sign-ups completed, country by country. A country where that ratio jumps overnight is a country to switch off in your SMS provider's geographic permissions until you know why.


