npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

expo-otp-autofill

v1.0.7

Published

Expo OTP Autofill

Downloads

766

Readme

expo-otp-autofill

A native Expo wrapper for Android's official Google SMS Retriever API. This library allows your React Native / Expo application to automatically detect and auto-fill incoming OTP SMS messages with ZERO Android permissions requested from the user.

npm version Platform License: MIT


🚀 Features

| Feature | Description | |---|---| | Zero Permissions | No need to ask the user for dangerous RECEIVE_SMS or READ_SMS permissions. Google Play Store natively approves this exact implementation. | | Silent Intercept | Google Play Services natively intercepts only the SMS meant for your app based on the unique 11-char App Hash. | | useOtpAutoFill Hook | Simple plug-and-play React hook with auto-parsing logic. | | Continuous Listening | Uniquely allows intercepting multiple consecutive OTP messages by instantly resetting the background listener after every read. | | App Hash Generator | Instantly generate the exact 11-character app hash Google requires (getAppHashAsync()) programmatically. |

Note: Because this library uses the official Google SMS Retriever API, the server transmitting your OTP messages must append your 11-character App Hash at the very end of the SMS content. Example:

Your verification code is 123456. AB12cd3Efgh


📦 Installation

npx expo install expo-otp-autofill

After installation, ensure you rebuild your Android codebase, as this includes native Google Play Services dependencies:

npx expo prebuild --clean
npx expo run:android

📖 Hook Usage: useOtpAutoFill()

This is the main API you will use inside your components. It will trigger Android to listen for the OTP SMS targeting your app for up to 5 minutes.

import React, { useEffect } from 'react';
import { View, TextInput, Button, Text } from 'react-native';
import { useOtpAutoFill, getAppHashAsync } from 'expo-otp-autofill';

export default function MyLoginScreen() {
  // 1. Hook begins listening automatically on mount and seamlessly resets after an OTP is intercepted
  const { otp, message, clear } = useOtpAutoFill({
    length: 6,         // Optional: Number of digits to extract (default is [4, 8])
    timeout: 30000,    // Optional: How long to keep the `otp` state visible horizontally before clearing (default 30000ms. 0 disables)
  });

  useEffect(() => {
    // Optional: Print your 11-character App Hash so you can configure it on your server!
    getAppHashAsync().then((hash) => console.log('My App Hash is:', hash));
  }, []);

  return (
    <View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
      {message && <Text style={{ color: 'gray' }}>Captured exact SMS: {message}</Text>}
      
      <TextInput
        value={otp ?? ''}
        placeholder="Waiting for OTP without permissions..."
        style={{ borderWidth: 1, padding: 10, marginVertical: 10, fontSize: 20 }}
      />
      
      <Button title="Manually Clear OTP" onPress={clear} />
    </View>
  );
}

Options

| Option | Type | Default | Description | |---|---|---|---| | length | number or [min, max] | [4, 8] | Forces regex to only extract digits matching this length constraint. | | timeout | number | 30000 | Once an OTP is parsed, automatically clear the state variable to null after this many milliseconds. Pass 0 to disable auto-clearing. |

Return Value

| Property | Type | Description | |---|---|---| | otp | string \| null | The purely extracted numeric code (e.g. "123456") | | message | string \| null | The raw complete SMS message including your app hash. | | clear | () => void | Removes the otp and message states from the screen, without killing the background listener. The API will immediately capture the next OTP sent. |


📖 Under-the-Hood APIs

If you prefer imperative control instead of Hooks, you can use the core functions explicitly:

startSmsRetrieverAsync()

Initiates 5-minute listening window inside Google Play Services. Returns boolean.

const started = await startSmsRetrieverAsync();

stopSmsRetrieverAsync()

Stops listening and unregisters native Broadcast Receiver. (No-op if already stopped).

stopSmsRetrieverAsync();

getAppHashAsync()

Computes the 11-char hash from your current Keystore. Returns String.

const hash = await getAppHashAsync();

extractOtp(text, options?)

Pure JS function to extract OTP digits out of a larger SMS phrase.

const extracted = extractOtp('Your code is 6451. df3Wz2qP', { length: 4 });
// "6451"

🤝 Need to read ALL messages without a hash?

If you are building an offline app, a budget tracker, or an app that does not control the server sending the SMS, the SMS Retriever API will not work for you.

Instead, use its sister library: expo-sms-listener. It requires the RECEIVE_SMS user permission, but allows you to capture any SMS from any sender, even when your app is completely closed.


License

MIT © MULERx