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

@anbuinfosec/fca-unofficial

v2.0.0

Published

@anbuinfosec/fca-unofficial 2.0 – stable, low-risk Facebook Messenger automation API with integrated secure login (ID / Password / 2FA), adaptive MQTT core, safety orchestration, metrics, and TypeScript support.

Readme

Unofficial Facebook Chat API

code style: prettier

📦 Install & Usage (Fork)

This is a maintained fork of the original @anbuinfosec/fca-unofficial Messenger API, adapted for my Chika Shirogane bot and compatible with GoatBot-V2 (with modified source).

Install directly from GitHub

npm install @anbuinfosec/fca-unofficial

Or add to your package.json:

"dependencies": {
    "@anbuinfosec/fca-unofficial": "^1.4.0"
}

Usage

Import and use as you would the main module:

const login = require('@anbuinfosec/fca-unofficial');
(async () => {
  const api = await login({ appState: require('./appstate.json') });
  // ...
})();

About this fork

  • Based on the main @anbuinfosec/fca-unofficial source
  • Adapted for Chika Shirogane bot and GoatBot-V2 integration
  • Includes enhancements, async/await support, and compatibility fixes


@anbuinfosec/fca-unofficial v3.0.0 – Advanced Core Release

Modern, safe, production‑ready Messenger (Facebook Chat) API layer with integrated secure login (credentials + 2FA), adaptive session & connection resilience, delivery reliability safeguards, memory protection, and rich runtime metrics. Promise + callback compatible, TypeScript typed, minimal friction.


✅ Core Value

| Pillar | What You Get | |--------|--------------| | Integrated Secure Login | Username / Password / TOTP 2FA → stable appstate generation & reuse | | Session Resilience | Anchored User‑Agent continuity, adaptive safe refresh, lightweight token poke, periodic recycle | | Connection Stability | Adaptive MQTT backoff, idle & ghost detection, layered post-refresh health probes, synthetic keepalives | | Delivery Reliability | Multi-path message send fallback (MQTT → HTTP → direct) + delivery receipt timeout suppression | | Memory Guard | Bounded queues, edit TTL sweeps, controlled resend limits | | Observability | Health + memory + delivery metrics (api.getHealthMetrics(), api.getMemoryMetrics()) | | Edit Safety | Pending edit buffer, ACK watchdog, p95 ACK latency tracking | | Type Definitions | First-class index.d.ts with modern Promise signatures |


🔄 What Changed in 3.0.0

Major version signals maturity & consolidation. No breaking public API changes versus late 2.1.x – upgrade is drop‑in. Temporary diagnostic harness removed; internal instrumentation formalized. Delivery receipt timeouts now intelligently retried & optionally auto-suppressed to protect outbound responsiveness.


🚀 Quick Start (Appstate Preferred)

const login = require('@anbuinfosec/fca-unofficial');

(async () => {
  const api = await login({ appState: require('./appstate.json') });
  console.log('Logged in as', api.getCurrentUserID());
  api.listen((err, evt) => {
    if (err) return console.error('Listen error:', err);
    if (evt.body) api.sendMessage('Echo: ' + evt.body, evt.threadID);
  });
})();

Credentials + 2FA Flow

const login = require('@anbuinfosec/fca-unofficial');
(async () => {
  const api = await login({
    email: process.env.FB_EMAIL,
    password: process.env.FB_PASS,
    twofactor: process.env.FB_2FA_SECRET // optional TOTP secret
  });
  api.listen((err, msg) => {
    if (err) return console.error(err);
    if (msg.body === 'ping') api.sendMessage('pong', msg.threadID);
  });
})();

🧪 Key Runtime APIs

api.setEditOptions({ maxPendingEdits, editTTLms, ackTimeoutMs, maxResendAttempts });
api.setBackoffOptions({ base, factor, max, jitter });
api.enableLazyPreflight(true);       // Skip heavy validation if recent success
api.getHealthMetrics();              // uptime, reconnects, ack latency, delivery stats
api.getMemoryMetrics();              // queue sizes & guard counters

Monitoring Snippet

setInterval(() => {
  const h = api.getHealthMetrics();
  const m = api.getMemoryMetrics();
  console.log('[HEALTH]', h?.status, 'acks', h?.ackCount, 'p95Ack', h?.p95AckLatencyMs);
  console.log('[DELIVERY]', {
    attempts: h?.deliveryAttempts,
    success: h?.deliverySuccess,
    failed: h?.deliveryFailed,
    timeouts: h?.deliveryTimeouts,
    disabledSince: h?.deliveryDisabledSince
  });
  console.log('[MEM]', m);
}, 60000);

🛡️ Safety & Stability Architecture

| Layer | Mechanism | Purpose | |-------|-----------|---------| | UA Continuity | Single anchored fingerprint | Avoid heuristic expiry & drift | | Adaptive Refresh | Risk-aware timing bands | Token longevity without bursts | | Lightweight Poke | Subtle fb_dtsg renewal | Keeps session warm quietly | | Collision Guard | 45m spacing window | Prevent clustered maintenance events | | Idle / Ghost Probe | Timed silent detection | Force reconnect on stale sockets | | Periodic Recycle | Randomized (~6h ±30m) | Pre-empt silent degradation | | Backoff Strategy | Exponential + jitter | Graceful network recovery | | Delivery Suppression | Disable after repeated timeouts | Preserve send latency |

Disable heavy preflight if embedding inside a framework already doing checks:

await login({ appState }, { disablePreflight: true });

🛰️ MQTT Enhancements (Since 2.1.x)

  • Adaptive reconnect curve (caps 5m)
  • Layered post-refresh probes (1s / 10s / 30s)
  • Synthetic randomized keepalives (55–75s)
  • Structured error classification feeding metrics

✉️ Delivery Reliability

  • Multi-path send fallback (MQTT publish → HTTP send → direct fallback)
  • Per-attempt timeout & retry for message delivery receipts
  • Automatic classification of transient timeouts (ETIMEDOUT / ECONNRESET / EAI_AGAIN)
  • Adaptive suppression of delivery receipt calls when environment unstable (protects primary send throughput)

🧠 Long Session Best Practices

  1. Prefer appstate reuse (minimal credential logins).
  2. Preserve persistent-device.json (only delete if forced challenge).
  3. Don’t manually rotate User-Agent – built-in continuity handles it.
  4. Inspect metrics before forcing reconnect; let backoff work.
  5. Keep dependencies updated; review CHANGELOG for operational notes.

🐐 Using with GoatBot V2 (Summary)

| Goal | Steps | |------|-------| | Generate appstate | Run credential login script → save appstate.json → configure GoatBot | | Full replacement | Install @anbuinfosec/fca-unofficial → shim fb-chat-api/index.js exporting module | | Direct require swap | Replace require('fb-chat-api') with require('@anbuinfosec/fca-unofficial') |

Minimal example:

const login = require('@anbuinfosec/fca-unofficial');
(async () => {
  const api = await login({ appState: require('./appstate.json') });
  api.listen((err, event) => {
    if (err) return console.error(err);
    if (event.body === '!ping') api.sendMessage('pong', event.threadID);
  });
})();

📚 Documentation Map

| Resource | Location | |----------|----------| | Full API Reference | DOCS.md | | Feature Guides | docs/*.md | | Configuration Reference | docs/configuration-reference.md | | Safety Details | docs/account-safety.md | | Examples | examples/ |


� Migrating 2.1.x → 3.0.0

| Area | Action Needed | |------|---------------| | Public API | None (fully compatible) | | Diagnostics Harness | Removed (no action) | | Delivery Metrics | Optionally surface in dashboards | | Safety Manager (legacy) | Keep removed / unused |


🗂 Previous 2.1.x Highlights (Condensed)

| Version | Focus | Key Additions | |---------|-------|---------------| | 2.1.10 | Stabilization | Final 2.1.x meta adjustments | | 2.1.8 | Safety Consolidation | Unified orchestrator, collision spacing, recycle suppression | | 2.1.7 | Session Longevity | UA continuity, lightweight poke | | 2.1.6 | Memory Guard | Queue pruning, edit TTL sweeps | | 2.1.5 | Edit Reliability | PendingEdits buffer, ACK watchdog |

Full details remain in CHANGELOG.md.


⚠️ Disclaimer

Not affiliated with Facebook. Use responsibly and comply with platform terms & local laws.


🤝 Contributing

Focused PRs improving stability, safety heuristics, protocol coverage, or typings are welcome.


📋 API Methods Quick Reference & Code Examples

Login Methods

| Method | Description | Example | |--------|-------------|---------| | fcaLogin() | Advanced login with ID/pass/2FA | await fcaLogin({username, password, twofactor}) | | login() | Traditional login | login({email, password}, callback) |

// Login with appstate
const login = require('@anbuinfosec/fca-unofficial');
(async () => {
  const api = await login({ appState: require('./appstate.json') });
  api.listen((err, evt) => {
    if (err) return console.error(err);
    if (evt.body) api.sendMessage('Echo: ' + evt.body, evt.threadID);
  });
})();

Message Methods

| Method | Description | Example | |--------|-------------|---------| | sendMessage() | Send text/media message | api.sendMessage('Hello!', threadID) | | sendMessageMqtt() | Send message via MQTT (faster) | api.sendMessageMqtt('Hello!', threadID) | | editMessage() | Edit existing message | api.editMessage('New text', messageID) | | unsendMessage() | Delete/unsend message | api.unsendMessage(messageID) | | markAsRead() | Mark messages as read | api.markAsRead(threadID) | | markAsDelivered() | Mark as delivered | api.markAsDelivered(threadID) | | markAsReadAll() | Mark all threads as read | api.markAsReadAll() | | markAsSeen() | Mark as seen | api.markAsSeen() | | setMessageReaction() | React to message | api.setMessageReaction('😍', messageID) | | setMessageReactionMqtt() | React via MQTT | api.setMessageReactionMqtt('👍', messageID) | | pinMessage() | Pin message in chat | api.pinMessage(messageID) |

// Send a message
api.sendMessage('Hello World!', threadID);

// Send with attachment
const fs = require('fs');
api.sendMessage({
  body: 'Check this image!',
  attachment: fs.createReadStream('./image.jpg')
}, threadID);

Thread/Chat Methods

| Method | Description | Example | |--------|-------------|---------| | getThreadList() | Get list of chats | api.getThreadList(20, null, [], callback) | | getThreadInfo() | Get chat information | api.getThreadInfo(threadID, callback) | | getThreadHistory() | Get message history | api.getThreadHistory(threadID, 50, null, callback) | | getThreadPictures() | Get shared pictures | api.getThreadPictures(threadID, 0, 10, callback) | | searchForThread() | Search for chats | api.searchForThread('name', callback) | | setTitle() | Change chat name | api.setTitle('New Name', threadID) | | changeThreadColor() | Change chat color | api.changeThreadColor('#ff0000', threadID) | | changeThreadEmoji() | Change chat emoji | api.changeThreadEmoji('🎉', threadID) | | changeArchivedStatus() | Archive/unarchive chat | api.changeArchivedStatus(threadID, true) | | muteThread() | Mute/unmute chat | api.muteThread(threadID, 3600) | | deleteThread() | Delete chat | api.deleteThread(threadID) |

// Get thread list
api.getThreadList(20, null, [], (err, list) => {
  if (err) return console.error(err);
  list.forEach(thread => {
    console.log(`${thread.name}: ${thread.threadID}`);
  });
});

Group Management

| Method | Description | Example | |--------|-------------|---------| | createNewGroup() | Create new group | api.createNewGroup([userID1, userID2], 'Name', callback) | | addUserToGroup() | Add user to group | api.addUserToGroup(userID, threadID) | | removeUserFromGroup() | Remove user from group | api.removeUserFromGroup(userID, threadID) | | changeAdminStatus() | Make/remove admin | api.changeAdminStatus(threadID, userID, true) | | changeGroupImage() | Change group picture | api.changeGroupImage(stream, threadID) |

User Methods

| Method | Description | Example | |--------|-------------|---------| | getUserInfo() | Get user information | api.getUserInfo(userID, callback) | | getCurrentUserID() | Get bot's user ID | const myID = api.getCurrentUserID() | | getUserID() | Get user ID by username | api.getUserID('username', callback) | | getAvatarUser() | Get user avatar URL | api.getAvatarUser(userID, callback) | | changeUsername() | Change username | api.changeUsername('new_username') | | changeBio() | Change bio | api.changeBio('New bio') | | changeAvatar() | Change profile picture | api.changeAvatar(stream) | | changeAvatarV2() | Change avatar (enhanced) | api.changeAvatarV2(stream) | | changeCover() | Change cover photo | api.changeCover(stream) | | changeName() | Change display name | api.changeName('New Name') | | changeNickname() | Change nickname in chat | api.changeNickname('Nick', threadID, userID) | | setProfileGuard() | Enable/disable profile guard | api.setProfileGuard(true) |

Friends & Social

| Method | Description | Example | |--------|-------------|---------| | getFriendsList() | Get friends list | api.getFriendsList(callback) | | handleFriendRequest() | Accept/decline friend request | api.handleFriendRequest(userID, true) | | follow() | Send friend request/follow | api.follow(userID) | | unfriend() | Remove friend | api.unfriend(userID) | | handleMessageRequest() | Accept/decline message request | api.handleMessageRequest(threadID, true) | | changeBlockedStatus() | Block/unblock user | api.changeBlockedStatus(userID, true) | | changeBlockedStatusMqtt() | Block/unblock via MQTT | api.changeBlockedStatusMqtt(userID, true) |

Posts & Social Media

| Method | Description | Example | |--------|-------------|---------| | createPost() | Create Facebook post | api.createPost('Hello Facebook!', callback) | | createPoll() | Create poll in group | api.createPoll('Question?', ['A', 'B'], threadID) | | setPostReaction() | React to post | api.setPostReaction(postID, 'LOVE') | | setStoryReaction() | React to story | api.setStoryReaction(storyID, 'LOVE') | | sendComment() | Comment on post | api.sendComment('Great!', postID) | | createCommentPost() | Create comment post | api.createCommentPost('Comment', postID) |

File & Media Methods

| Method | Description | Example | |--------|-------------|---------| | uploadAttachment() | Upload file | api.uploadAttachment(stream, callback) | | forwardAttachment() | Forward attachment | api.forwardAttachment(attachmentID, threadID) | | shareContact() | Share contact | api.shareContact('Message', userID, threadID) | | shareLink() | Share link | api.shareLink('https://example.com', threadID) | | resolvePhotoUrl() | Get photo URL | api.resolvePhotoUrl(photoID, callback) |

Search Methods

| Method | Description | Example | |--------|-------------|---------| | searchStickers() | Search stickers | api.searchStickers('happy', callback) | | getEmojiUrl() | Get emoji image URL | api.getEmojiUrl('😍', 'large', callback) |

HTTP Methods

| Method | Description | Example | |--------|-------------|---------| | httpGet() | HTTP GET request | api.httpGet(url, {}, {}, callback) | | httpPost() | HTTP POST request | api.httpPost(url, data, {}, callback) | | httpPostFormData() | POST form data | api.httpPostFormData(url, formData, {}, callback) |

Advanced Features

| Method | Description | Example | |--------|-------------|---------| | listenMqtt() | Listen via MQTT | api.listenMqtt(callback) | | stopListenMqtt() | Stop MQTT listening | api.stopListenMqtt() | | listenNotification() | Listen to notifications | api.listenNotification(callback) | | sendTypingIndicator() | Show typing indicator | api.sendTypingIndicator(threadID) | | listen() | Listen to all events | api.listen(callback) |

Configuration

| Method | Description | Example | |--------|-------------|---------| | setOptions() | Set API options | api.setOptions({listenEvents: true}) | | getOptions() | Get current options | const opts = api.getOptions() | | getCtx() | Get bot context | const ctx = api.getCtx() | | getAccess() | Get access info | const access = api.getAccess() | | getBotInitialData() | Get initial data | const data = api.getBotInitialData() | | getRegion() | Get current region | api.getRegion(callback) | | refreshFb_dtsg() | Refresh security token | api.refreshFb_dtsg(callback) |

Security & Session

| Method | Description | Example | |--------|-------------|---------| | logout() | Logout properly | api.logout(callback) | | getAppState() | Get session appstate | const appstate = api.getAppState() |

UI Customization

| Method | Description | Example | |--------|-------------|---------| | threadColors() | Get available colors | api.threadColors(callback) |


For more code examples and advanced usage, see COMPLETE-API-DOCS.md and DOCS.md.