Get to know MDN better
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Experimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.
Secure context: This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.
The WebOTP API provides a streamlined user experience for web apps to verify that a phone number belongs to a user when using it as a sign-in factor. WebOTP is an extension of the Credential Management API.
The verification is done via a two-step process:
Phone numbers are often used as a way to identify the user of an app. An SMS is frequently deployed to verify that the number belongs to the user. The SMS typically contains an OTP that the user is required to copy and paste into a form in the app to verify that they own the number. This is a somewhat clunky user experience.
OTP use cases include:
The WebOTP API allows web apps to expedite this validation process by copying the OTP from the SMS and passing it to the app automatically after the user has provided consent (most native platforms have an equivalent API).
Note that an OTP is bound to the sending domain. This is a useful security constraint for verifying that the OTP is coming from the right source, which can mitigate the risk of phishing attacks during day-to-day reauthentication.
SMS OTPs are useful for verifying phone numbers, and using SMS for a second factor is certainly better than having no second factor. In some regions, other identifiers such as email addresses and authenticators are not widely-used, so SMS OTPs are very common.
However, SMSes aren't that secure. Attackers can spoof an SMS and hijack a person's phone number. Carriers can recycle phone numbers to new users after an account is closed.
You are, therefore, recommended to use a stronger form of authentication if possible, such as a Web Authentication API-based solution involving a password and security key or a passkey.
The process works like so:
A typical SMS message looks like so:
Your verification code is 123456. @www.example.com #123456Note: The provided domain value must not include a URL scheme, port, or other URL features not shown above.
If the get() method is invoked by a third-party site embedded in an <iframe>, the SMS structure should be:
Your verification code is 123456. @top-level.example.com #123456 @embedded.comIn this case, the last line must consist of:
The availability of WebOTP can be controlled using a Permissions Policy specifying an otp-credentials directive. This directive has a default allowlist value of "self", meaning that by default, these methods can be used in top-level document contexts.
You could specify a directive allowing the use of WebOTP in a specific cross-origin domain (i.e., inside an <iframe>) like this:
Or you could specify it directly on the <iframe> like this:
Note: Where a policy forbids use of WebOTP get(), promises returned by it will reject with a SecurityError DOMException.
Returned when a WebOTP get() call fulfills; includes a code property that contains the retrieved OTP.
Calling get() with an otp option instructs the user agent to attempt to retrieve an OTP from the underlying system's SMS app.
In this example, when an SMS message arrives and the user grants permission, an OTPCredential object is returned with an OTP. This password is then prefilled into the verification form field, and the form is submitted.
The form field includes an autocomplete attribute with the value of one-time-code. This is not needed for the WebOTP API to work, but it is worth including. As a result, Safari will prompt the user to autofill this field with the OTP when a correctly-formatted SMS is received, even though the WebOTP API isn't fully supported in Safari.
The JavaScript is as follows:
Another good use for the AbortController is to cancel the get() request after a certain amount of time:
If the user becomes distracted or navigates somewhere else, it is good to cancel the request so that they don't get presented with a permission prompt that is no longer relevant to them.
| WebOTP API |
Enable JavaScript to view this browser compatibility table.
This page was last modified on Oct 30, 2025 by MDN contributors.
Your blueprint for a better internet.
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.