Technical
Implementing the WebOTP API in Android TWAs
October 3, 2026 · 6 min read
When converting a Progressive Web App (PWA) to an Android application using a Trusted Web Activity (TWA), delivering a seamless user experience is the primary goal. One of the most common friction points in any mobile application is the user authentication flow, particularly when verifying phone numbers via SMS. In native Android apps, developers use the SMS Retriever API to read verification codes automatically. For web developers deploying to Google Play via a TWA, the WebOTP API provides an identical, native-grade autofill experience without requiring complex native Java or Kotlin wrappers.
By leveraging the WebOTP API, your application can detect when a verification SMS is received by the device, extract the one-time password (OTP), and populate the input field automatically. Because a TWA is powered directly by the system browser engine, it gains full access to this modern web API. This guide details how to implement, format, and test the WebOTP API inside an Android TWA.
Why Use WebOTP API in an Android TWA?
Manual verification processes introduce drop-off risks. When a user has to leave your application, open their default text messaging client, copy a six-digit code, return to your app, and paste the code, there is a high likelihood of distraction or input errors. Automating this step improves conversion rates and creates a professional feel.
Using the WebOTP API offers several advantages over traditional methods:
- No Native Permissions Required: Unlike legacy methods that required the invasive SMS read permission, WebOTP does not require you to request access to the user's personal text messages.
- Seamless Browser Integration: The API is handled directly by Chrome or other supporting Custom Tab providers, ensuring security and compliance with platform standards.
- Single Codebase: The same JavaScript code handles verification for both standard web browsers and your compiled Google Play application.
| Verification Method | User Effort | Security Profile | Implementation Location |
|---|---|---|---|
| Manual Input | High (Switch apps, copy, paste) | Low (Prone to phishing) | Frontend Web |
| Native SMS Retriever | None (Automatic) | High (App-bound) | Native Android Code |
| WebOTP API (TWA) | None (Single-tap approval) | High (Origin-bound verification) | Frontend Web |
How the WebOTP API Operates on Android
The WebOTP API relies on a secure handshake between the incoming SMS message, Google Play Services, the Android operating system, and the underlying browser engine powering your TWA. When your web application invokes the API, it registers a listener with the browser. When an SMS arrives that matches the specific cryptographic formatting requirements, the Android OS prompts the user with an overlay asking for permission to share the code with the application.
Once the user taps the approval button, the browser extracts the code from the message body and passes it directly to your JavaScript application. This origin-bound verification ensures that a malicious website or app cannot intercept codes meant for your specific domain, making it highly secure against phishing attempts.
Structuring the SMS Message
For Google Play Services to recognise and route the SMS to your TWA, the text message must be formatted precisely. If the message deviates from this structure, the Android system will ignore it, and the user will be forced to enter the code manually.
The SMS must adhere to the following rules:
- The message must begin with some user-readable text, such as the verification code.
- The final line of the message must contain the target web origin, preceded by the boundary character.
- The web origin must be prefixed with the custom characters to designate the target domain.
- The message must contain a hash matching the target origin or be bound specifically to the domain.
An example of a correctly formatted SMS message is as follows:
Your verification code is 482019.
@app.example.com #482019
In this structure, the first line is user-readable. The final line starts with the boundary marker, followed by the exact domain name of your PWA, followed by a space, and finally the code prefixed by a hash symbol. Because your TWA shares its origin with your web application, the domain listed in the SMS must be the exact domain loaded inside your Trusted Web Activity.
Implementing the JavaScript WebOTP Flow
To integrate WebOTP into your PWA, you must write JavaScript that initiates the credential request helper when the user reaches the verification step. This involves using the feature-detection pattern to verify support before invoking the credential mediator API.
Below is a robust implementation pattern that you can incorporate into your web application:
if ('OTPCredential' in window) {
window.addEventListener('DOMContentLoaded', () => {
const input = document.querySelector('input[autocomplete="one-time-code"]');
if (!input) return;
const ac = new AbortController();
const form = input.form;
if (form) {
form.addEventListener('submit', () => {
ac.abort();
});
}
navigator.credentials.get({
otp: { transport: ['sms'] },
signal: ac.signal
}).then(otp => {
input.value = otp.code;
if (form) form.submit();
}).catch(err => {
console.log('WebOTP error or abort:', err);
});
});
}
In this code, we first check for the presence of the OTPCredential object in the window scope. We then look for an input element that has its autocomplete attribute set to one-time-code. We set up an AbortController so that we can cancel the listener if the user decides to submit the form manually or navigates away. Finally, we invoke navigator.credentials.get, requesting the SMS transport mechanism. When the promise resolves, we retrieve the code, populate the input field, and programmatically submit the form.
Troubleshooting and Testing WebOTP in TWAs
Testing SMS-dependent workflows can be challenging. To test your WebOTP implementation within an Android TWA without sending actual SMS messages, you can utilise the Android Emulator or a physical device connected via USB debugging.
You can send mock SMS messages to your testing environment using the Android Debug Bridge (ADB). Run the following command from your terminal to simulate an incoming verification text:
adb shell am broadcast -a android.provider.Telephony.SMS_RECEIVED
Alternatively, you can use the emulator extended controls panel to send a text message to the virtual device. Ensure that the text matches the exact formatting rules discussed above. If the prompt does not appear, verify that your Digital Asset Links are configured correctly and that the URL bar is completely hidden in your TWA. A visible URL bar indicates that the system does not recognise the deep-linking validation, which can block browser-level platform integrations such as WebOTP. For publishing on Google Play, also remember that Google charges a 25 USD developer registration fee, which is a one-off requirement before you can distribute your verified application to users.
Ready to ship your Android app?
Paste your PWA URL, get a signed APK and a Google Play ready AAB in minutes.
Build my app