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

prince-convo

v2.0.0

Published

A Facebook Messenger bot library for Node.js. Developed by Prince Malhotra.

Readme

🚀 prince-convo version 2 is here!

Disclaimer: Use responsibly. We are not liable for account bans due to spammy activities, such as sending excessive messages, rapid logins/logouts, or sharing suspicious URLs. Be a responsible Facebook user.

🤔 What is the purpose of this package?

prince-convo is a Node.js package for automating Facebook Messenger bot. Developed by Prince Malhotra.

📖 Table of Contents

✨ Features

  • Automatic Re-login: Detects errors and automatically re-logs in using the cookie. If the cookie is logged out, it prompts for re-submission or refreshes automatically.
  • Account Lock/Suspension Detection: Stops the login process and displays details if an account is locked or suspended.
  • Token Refresh: Automatically refreshes fb_dtsg (Facebook's dynamic token) daily at 12:00 AM (GMT+8 PH time).
  • Random User Agent: Experimental feature to reduce logouts (setOptions).
  • Bypass Region: Choose regions like PRN, PNB, HKG, SYD, VLL, LLA, SIN (experimental).
  • AppState Auto-Save: Automatically saves session to file every 5 minutes (see autoSaveAppState option).
  • Smart MQTT Reconnect: Exponential backoff reconnection (up to 10 retries) when MQTT disconnects.
  • Thread Name Caching: getThreadName caches results for 60s to reduce API calls.
  • User Name Caching: getUserName caches results for 5 minutes to reduce API calls.
  • Robust Name Resolution: No more "Facebook User" or null thread names — multi-field fallback chain.
  • Type-filtered Thread List: Filter getThreadList by "GROUP", "DM", or "ALL".
  • Online Status: New getOnlineStatus API to check if users are active/idle/offline.
  • message_delivered Event: Listen for message delivery confirmations.
  • Typing Duration: sendTypingIndicator supports auto-stop after a duration.

🚀 Installation

Install the latest version of prince-convo via npm:

npm install prince-convo@latest

🛠 Usage

Below is an example of creating a simple echo bot:

const wiegine = require("prince-convo");

wiegine.login('Provide your cookie here',
  { /* setOptions here */ },
  (err, api) => {
    if (err) return console.error(err);
    api.listenMqtt((err, event) => {
      if (err) return console.error(err);
      api.sendMessage(event.body, event.threadID);
    });
  }
);

💡 Fun fact: You can also use header string based cookie.

🔧 Main Functionality

Sending Messages

api.sendMessage(message, threadID[, callback][, messageID])

Send various types of messages:

  • Regular: Use body for text messages.
  • Sticker: Set sticker to a sticker ID.
  • File/Image: Set attachment to a readable stream or array of streams.
  • URL: Set url to share a link.
  • Emoji: Set emoji and emojiSize ("small", "medium", "large").
  • Reply: Pass messageID as the 4th argument to reply.
  • Location: Set location: { latitude, longitude, current: true }.
  • Mention: Set mentions: [{ id, tag }] to @mention someone.

Saving Sessions

api.getAppState()

Returns the current session cookies. Save them to reuse without re-logging in.

fs.writeFileSync("appstate.json", JSON.stringify(api.getAppState()));

Auto-save option (saves every 5 minutes automatically):

wiegine.login(cookie, { autoSaveAppState: true, appStatePath: "appstate.json" }, (err, api) => {
  // Session is auto-saved every 5 minutes
});

Listening to Chats

api.listenMqtt(callback)

Listen for real-time events. Alias: api.listen.

api.listenMqtt((err, event) => {
  if (err) return console.error(err);
  console.log(event.type, event.body);
});

Thread Info

api.getThreadInfo(threadID[, callback])

Get detailed info about a thread. Returns thread name, participants, etc.

Fixed: threadName now uses a multi-field fallback chain and never returns null.

api.getThreadName(threadID[, callback])

Get just the display name of a thread. Results are cached for 60 seconds.

const name = await api.getThreadName("100012345678901");
console.log(name); // "My Cool Group"

User Info

api.getUserInfo(userID[, callback])

Get info about one or more users.

Fixed: No more "Facebook User" fallback — uses name → firstName → vanity → username → ID chain.

api.getUserName(userID[, callback])

Get just the display name of a user. Results are cached for 5 minutes.

const name = await api.getUserName("100012345678901");
console.log(name); // "John Doe"

Thread List

api.getThreadList(limit, timestamp, tags[, options][, callback])

Get list of inbox threads.

  • limit — number of threads
  • timestamp — pagination cursor (use null for first page, last thread's timestamp for next page)
  • tags — inbox folder, e.g. ["INBOX"], ["PENDING"], ["ARCHIVED"]
  • options.type"GROUP" | "DM" | "ALL" (default: "ALL")
// All threads
const threads = await api.getThreadList(10, null, ["INBOX"]);

// Groups only
const groups = await api.getThreadList(20, null, ["INBOX"], { type: "GROUP" });

// DMs only
const dms = await api.getThreadList(20, null, ["INBOX"], { type: "DM" });

// Paginate: next page
const page2 = await api.getThreadList(10, parseInt(threads.at(-1).timestamp), ["INBOX"]);

Typing Indicator

api.sendTypingIndicator(isTyping, threadID[, duration][, callback])

Send a typing indicator. Optionally auto-stops after duration milliseconds.

// Start typing indefinitely
await api.sendTypingIndicator(true, threadID);

// Show typing for 3 seconds, then stop automatically
await api.sendTypingIndicator(true, threadID, 3000);

// Stop typing
await api.sendTypingIndicator(false, threadID);

Online Status

api.getOnlineStatus(userIDs[, callback])

Check the online/presence status of one or more users.

Returns: { userID, isOnline, lastActiveTimestamp, status: "active"|"idle"|"offline" }

// Single user
const status = await api.getOnlineStatus("100012345678901");
console.log(status.isOnline);            // true
console.log(status.lastActiveTimestamp); // 1710000000000

// Multiple users
const statuses = await api.getOnlineStatus(["id1", "id2"]);
console.log(statuses["id1"].status); // "active"

⚙️ Options

Pass options as the second argument to login():

| Option | Type | Default | Description | |--------|------|---------|-------------| | selfListen | boolean | false | Receive your own messages | | listenEvents | boolean | true | Receive non-message events (reactions, unsend, etc.) | | autoMarkDelivery | boolean | false | Auto mark messages as delivered | | autoMarkRead | boolean | true | Auto mark messages as read | | autoReconnect | boolean | true | Auto reconnect on MQTT disconnect (max 10 retries, exponential backoff) | | online | boolean | true | Appear online | | userAgent | string | Facebook UA | Custom user agent | | randomUserAgent | boolean | false | Randomize user agent (experimental) | | bypassRegion | string | - | Force a region: "PRN", "PNB", "HKG", etc. | | updatePresence | boolean | false | Receive presence events | | emitReady | boolean | false | Emit a ready event when connected | | autoSaveAppState | boolean | false | Auto-save session to file every 5 minutes | | appStatePath | string | "appstate.json" | File path for auto-saved appstate |

📡 Events Reference

| Event type | Description | |-----------|-------------| | message | New message received | | message_reply | Reply to a message | | message_reaction | Reaction added/changed (requires listenEvents: true) | | message_unsend | Message unsent/deleted (requires listenEvents: true) | | message_delivered | Message delivery confirmed (requires listenEvents: true) | | typ | Typing indicator from another user | | presence | Online/offline status update (requires updatePresence: true) | | read_receipt | Message read by another user | | change_thread_image | Thread photo changed | | ready | Connected and ready (requires emitReady: true) | | stop_listen | MQTT stopped (all reconnect attempts failed) |

❓ FAQ

Q: How do I get my cookie/appstate?

A: Use a browser extension that can export cookies from Facebook, or use any Facebook AppState extractor tool. Save the exported JSON as appstate.json.

Q: My bot keeps getting logged out — what can I do?

A: Enable autoSaveAppState so your session is saved regularly. Also try randomUserAgent: true (experimental). Avoid sending too many messages in a short period.

Q: What is the "max reconnect attempts" error?

A: After 10 failed reconnects with exponential backoff (1s → 2s → 4s → ... → 30s max), the bot stops trying. You should reinitiate the login() call in your stop_listen handler.

api.listenMqtt((err, event) => {
  if (err && err.type === "stop_listen") {
    console.log("Connection lost. Retrying login in 60s...");
    setTimeout(() => startBot(), 60000);
  }
});

📋 Projects Using This API

  • MiraiBot
  • AutoBot

💬 Support

  • GitHub: https://github.com/PrinceMalhotra/prince-convo
  • Report bugs or request features via GitHub Issues.

📄 License

MIT License — see LICENSE for details.