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

chat-otp

v0.1.0

Published

Send and verify OTP codes via WhatsApp (unofficial, via Baileys) and Telegram (official API).

Readme

chat-otp

This package helps you send verification codes (OTPs) easily. You can send them via WhatsApp (unofficial, using Baileys) and Telegram (using the official Bot API).

Important: This package only sends the codes. Generating the code, storing it, setting an expiration time, and checking if it's correct is entirely up to you, on your backend. This gives you the freedom to use your own methods (like Redis, SQL database, custom timers) without being limited by this library.


Table of Contents


Installation

Install the package using npm:

npm install chat-otp

Important Warning

  • WhatsApp: We use an unofficial library that acts like WhatsApp Web. Meta (the company behind WhatsApp) does not provide or endorse this. Sending too many messages or using it for spam could get your phone number banned. It's best for smaller projects. For high volume, consider the official WhatsApp Business API.
  • Telegram: We use the official Bot API. It's reliable, but be mindful of Telegram's rate limits.
  • No Data Storage: This package does not store any data like codes, expiration times, or verification attempts. The security of your authentication system completely depends on how you manage this logic on your server.

Quick Start

Here's a simple example to get you started:

import { OtpSender, WhatsAppProvider } from 'chat-otp';

const sender = new OtpSender({
  providers: [
    new WhatsAppProvider({ authFolder: '.wa-auth' }), // Stores your WhatsApp session
  ],
});

await sender.connectAll(); // You'll need to scan a QR code the first time for WhatsApp

// YOU generate and manage the code!
const code = Math.floor(100000 + Math.random() * 900000).toString();

await sender.send('whatsapp', '+1234567890', code); // Send the code via WhatsApp

For Telegram, please see the Telegram - Link Flow (Deep Link) section below, as it's the only supported way for this channel.


WhatsApp

To use WhatsApp, you need to configure the WhatsAppProvider:

new WhatsAppProvider({
  authFolder: '.wa-auth',        // Folder to save your login session (default: '.wa-auth')
  printQrInTerminal: true,       // Show the QR code in your terminal (default: true)
  suppressSignalLogs: true,      // Hide internal logs that might show sensitive info (default: true)
});

First Time Login: A QR code will appear in your terminal. Scan it using your WhatsApp app (Settings → Linked Devices). The session will be saved in the authFolder, so you won't need to scan again next time.

Target Format: You can use the phone number with or without the country code (e.g., +1234567890 or 1234567890), or a raw WhatsApp JID (e.g., [email protected]).

Session Revoked: If your WhatsApp session gets disconnected (e.g., you log out on your phone), connect() will throw an error. You'll need to delete the authFolder and scan the QR code again.

suppressSignalLogs

The underlying library (Baileys) uses libsignal-node for encryption. Sometimes, it logs raw session data. By default, chat-otp filters these logs. Only turn off suppressSignalLogs if you need to see these logs for debugging during development.


Telegram - Link Flow (Deep Link)

This is useful when you don't know the user's chatId yet. The user needs to click a link that opens your Telegram bot first. This is a separate tool from OtpSender because its two-step process doesn't fit the send(channel, target, code) pattern.

import { TelegramLinkClient } from 'chat-otp';

const telegramLink = new TelegramLinkClient({
  botToken: process.env.TELEGRAM_BOT_TOKEN!, // Your Telegram Bot Token
  botUsername: process.env.TELEGRAM_BOT_USERNAME!, // Your Bot's username (without the @)
});

Full Flow

  1. Generate a unique link when the user requests verification:

    // 1. Generate a unique link when the user requests verification
    const { token, url } = telegramLink.createLink();
    // -> Show this `url` to the user (e.g., as a "Verify via Telegram" button)
  2. Store the link between the token and the pending request (this is your responsibility, with your own expiration time):

    // 2. Store the token <-> pending request mapping (YOUR job, with your own expiration)
    myPendingRequests.set(token, { userId: currentUser.id, createdAt: Date.now() });
  3. Listen for the event that triggers when the user clicks the link and starts your bot:

    // 3. Listen for the event triggered when the user clicks and starts the bot
    telegramLink.on('link', async ({ token, chatId }) => {
      const pending = myPendingRequests.get(token);
      if (!pending) return; // Token not found or expired (handled by you)
       
      myPendingRequests.delete(token);
       
      const code = generateOtpCode();       // Your logic
      await saveCodeSomewhere(pending.userId, code); // Your logic
       
      await telegramLink.sendCode(chatId, code); // Send the code to the user's chat
    });
  4. The user pastes the code received on Telegram into your UI. You then verify it as usual.

What this library does: Creates the token and link, listens for incoming /start commands from the bot link, and sends the message. What it doesn't do: Validate tokens, handle expiration, generate or compare codes – that's all on your end.


Error Handling

OtpSender.send() provides clear, typed errors to help you manage issues:

| Error Type | Reason | | --- | --- | | ProviderNotFoundError | The requested channel doesn't have a provider set up. | | ProviderNotReadyError | The provider isn't connected (e.g., WhatsApp not scanned, or disconnected). | | SendFailedError | The message failed to send on the provider's end (network issue, invalid recipient, etc.). |

try {
  await sender.send('whatsapp', target, code);
} catch (err) {
  if (err instanceof ProviderNotReadyError) {
    // Example: Try reconnecting or use a different channel as a fallback
    console.error('Provider not ready, maybe try reconnecting?');
  }
  // Re-throw other errors
  throw err;
}

API Reference

OtpSender

| Method | Description | | --- | --- | | connectAll() | Connects all providers that have a connect() method. | | send(channel, target, code, options?) | Sends the code through the specified channel. Returns SendResult. |

WhatsAppProvider

| Option | Type | Default | Description | | --- | --- | --- | --- | | authFolder | string | .wa-auth | Folder to save the session. | | printQrInTerminal | boolean | true | Displays the QR code in the terminal. | | suppressSignalLogs | boolean | true | Filters sensitive internal logs. |

TelegramLinkClient

| Method | Description | | --- | --- | | createLink() | Generates { token, url } for the deep link. | | sendCode(chatId, code, template?) | Sends the code to the resolved chatId. | | on('link', listener) | Listens for link clicks and bot starts ({ token, chatId }). |

| Option | Type | Default | Description | | --- | --- | --- | --- | | botToken | string | — | Your Telegram Bot Token (required). | | botUsername | string | — | Your Bot's username, without the @ (required). | | defaultTemplate | string | 'Your verification code is: {code}' | The default message template. |


License

MIT