@dongdev/fca-unofficial
v4.0.3
Published
Unofficial Facebook Chat API for Node.js - Interact with Facebook Messenger programmatically
Maintainers
Readme
@dongdev/fca-unofficial
An unofficial Node.js library for interacting with Facebook Messenger through user-session emulation. It speaks the same HTTP/GraphQL and MQTT protocols the browser client uses, giving you programmatic access to messages, threads, reactions, typing indicators, and more — all in TypeScript with full type definitions.
Disclaimer: This library operates by emulating a logged-in browser session. Using it may violate Facebook / Meta's Terms of Service and could result in account restrictions or bans. The author assumes no responsibility for how you use this software. Use it only for lawful purposes and at your own risk.
Table of Contents
- Installation
- Quick Start
- Authentication
- API Styles
- MessengerBot (Event-Driven)
- Configuration
- Features Overview
- Project Documentation
- Requirements
- License
- Links
Installation
npm install @dongdev/fca-unofficial@latestIf you clone the repository and want to work with the source directly:
git clone https://github.com/dongp06/fca-unofficial.git
cd fca-unofficial
npm install
npm run buildThe build produces these artifacts in dist/:
| File | Format / role |
|-------------------|----------------------------------------------------|
| dist/cjs.cjs | CommonJS entry — require() resolves here; the export is the login function (Mirai / classic FCA). |
| dist/index.js | Internal CJS bundle (required by cjs.cjs) |
| dist/index.mjs | ES Modules (ESM) |
| dist/index.d.ts | TypeScript typings |
Quick Start
Event-driven bot (recommended)
const { createMessengerBot } = require("@dongdev/fca-unofficial");
async function main() {
const bot = await createMessengerBot(
{ appState: require("./appstate.json") },
{
listenEvents: true,
stopOnSignals: true,
commandPrefix: "/"
}
);
bot.on("error", (err) => console.error("Bot error:", err));
bot.on("messageCreate", (event) => {
if (event.body) {
console.log(`[${event.threadID}] ${event.body}`);
}
});
bot.command("ping", async (ctx) => {
await ctx.replyAsync("pong");
});
}
main();Classic require (default export = login)
Same pattern as older FCA forks: the required module is login. Callback gets api, not ctx.
const login = require("@dongdev/fca-unofficial");
login({ appState: require("./appstate.json") }, (err, api) => {
if (err) return console.error(err);
api.setOptions({ listenEvents: true });
api.listenMqtt((e, ev) => {
if (e) return console.error(e);
if (ev.type === "message") api.sendMessage(ev.body, ev.threadID);
});
});Optional FCA options before the callback: login(credentials, { listenEvents: true }, (err, api) => { ... }).
Async / Promise style
const { login } = require("@dongdev/fca-unofficial");
async function main() {
const ctx = await login({ appState: require("./appstate.json") });
const api = ctx.api;
api.listenMqtt((err, event) => {
if (err) return console.error(err);
if (event.type === "message") {
api.sendMessage(`Echo: ${event.body}`, event.threadID);
}
});
}
main();Authentication
With require("@dongdev/fca-unofficial"), you get the login function directly (see Quick Start). With named imports / ESM, use import { login } from "..." or import login from "...".
The library supports multiple credential strategies. Pass one of the following to login() or createMessengerBot():
| Credential | Description |
|----------------|-------------------------------------------------------------------------------------------------------------|
| appState | An array of cookie objects ({ key, value, domain, path, ... }) exported from a browser extension or tool. Recommended for bots. |
| Cookie | A raw cookie header string, e.g. "c_user=...; xs=...; ...". |
| email + password | Web login credentials. Prone to checkpoints and CAPTCHAs; not recommended for long-running bots. |
You can also use loginViaAPI / tokensViaAPI for token-based authentication through an external API server (see fca-config.json → apiServer).
API Styles
After authentication, you get an FcaContext object. The library offers two ways to call Messenger functions:
1. Flat API (legacy-compatible)
Every method lives directly on ctx.api:
api.sendMessage("Hello!", threadID);
api.getThreadInfo(threadID, (err, info) => { ... });
api.setMessageReaction(":heart:", messageID);2. Namespaced client facade
Group related methods under domain namespaces for cleaner code:
import { createFcaClient } from "@dongdev/fca-unofficial";
const client = createFcaClient(ctx.api);
await client.messages.send("Hello!", threadID);
await client.threads.getInfo(threadID);
await client.users.getInfo(userID);Available namespaces: messages, threads, users, account, realtime, http, scheduler.
MessengerBot (Event-Driven)
MessengerBot provides a high-level, event-driven interface inspired by Discord.js and Telegraf.
Creating a bot
import { createMessengerBot } from "@dongdev/fca-unofficial";
const bot = await createMessengerBot(
{ appState: require("./appstate.json") },
{
listenEvents: true,
stopOnSignals: true,
commandPrefix: "/",
maxEventListeners: 64,
enableComposer: true
}
);Events
| Event | Trigger |
|----------------------|----------------------------------------------|
| message | Any incoming message (including replies) |
| messageCreate | Alias for message |
| message_reply | A reply to an existing message |
| messageReactionAdd | A reaction is added to a message |
| messageDelete | A message is unsent/deleted |
| typingStart | A user starts typing |
| typingStop | A user stops typing |
| threadUpdate | Thread metadata changes (title, participants) |
| ready | MQTT connection established |
| raw / update | Every MQTT delta (unfiltered) |
| error | Any error during listening |
Composer middleware
The composer pipeline processes message and message_reply events through a chain of middleware functions:
// Global middleware
bot.use(async (ctx, next) => {
console.log(`[${ctx.threadID}] ${ctx.text}`);
await next();
});
// Command handler — matches "/ping" at the start of a message
bot.command("ping", async (ctx) => {
await ctx.replyAsync("pong");
});
// Pattern matching — regex or substring
bot.hears(/hello/i, async (ctx) => {
await ctx.replyAsync("Hi there!");
});
bot.hears("goodbye", async (ctx) => {
ctx.reply("See you later!");
});
// Error handler for the composer chain
bot.catch((err, ctx) => {
console.error("Composer error:", err);
});MessengerContext
Each composer handler receives a MessengerContext with:
| Property / Method | Description |
|-----------------------|-----------------------------------------------|
| ctx.text | Trimmed message body |
| ctx.body | Raw message body |
| ctx.threadID | Thread the message belongs to |
| ctx.senderID | User who sent the message |
| ctx.messageID | Unique message identifier |
| ctx.event | Full MessageEvent object |
| ctx.reply(payload) | Send a reply (callback-style) |
| ctx.replyAsync(payload) | Send a reply (returns a Promise) |
Lifecycle
await bot.launch({ stopOnSignals: true });
// Graceful shutdown
await bot.stop();When stopOnSignals is true, the bot automatically calls stop() on SIGINT / SIGTERM.
Configuration
If fca-config.json is missing in the process working directory, it is created automatically with defaults on first load (or in-memory defaults only if the file cannot be written).
You can also copy the example and edit it:
cp fca-config.example.json fca-config.jsonConfiguration blocks
| Block | Purpose |
|-----------------|-------------------------------------------------------------------------------|
| checkUpdate | Automatic npm version check on startup |
| mqtt | MQTT reconnect interval, enable/disable realtime |
| autoLogin | Re-authenticate automatically when the session expires |
| credentials | Email / password / 2FA secret for auto-login |
| antiGetInfo | Toggle SQLite-backed caching for getThreadInfo / getUserInfo |
| remoteControl | WebSocket-based remote control for external dashboards |
| apiServer | External API server URL for token-based login |
Login options (FcaOptions)
| Option | Type | Default | Description |
|-------------------|-----------|-----------|--------------------------------------------------|
| listenEvents | boolean | false | Receive thread events (not just messages) |
| selfListen | boolean | false | Receive your own messages |
| selfListenEvent | boolean | false | Receive your own thread events |
| listenTyping | boolean | false | Receive typing indicators |
| updatePresence | boolean | false | Receive presence/online status updates |
| forceLogin | boolean | false | Force login even if already logged in |
| autoMarkRead | boolean | false | Automatically mark messages as read |
| autoReconnect | boolean | false | Reconnect MQTT automatically on disconnect |
| online | boolean | false | Appear online to other users |
| emitReady | boolean | false | Emit a ready event when MQTT connects |
| userAgent | string | Chrome UA | Custom User-Agent header |
| proxy | string | — | HTTP/SOCKS proxy URL |
| pageID | string | — | Act as a Facebook Page instead of a user |
| logLevel | string | "info" | Logging verbosity (silly, info, warn, error, silent) |
Features Overview
Messaging
Send text, attachments, stickers; edit, unsend, delete messages; forward attachments; upload files; set reactions; share contacts; send typing indicators; mark as read/delivered/seen.
Threads
Get thread info and history; list threads; search threads; create groups; add/remove participants; change admin status; change group name, image, color, emoji; create polls; archive/mute/delete threads; handle message requests.
Users
Look up user info (single and batch); resolve user IDs from vanity URLs; get friends list.
Account
Change avatar, bio, blocked status; handle friend requests; unfriend; set post reactions; refresh fb_dtsg; logout; manage external modules; auto-save app state.
Realtime (MQTT)
Persistent WebSocket connection to Facebook's MQTT broker. Receives messages, reactions, typing indicators, presence, thread events, read receipts, and more in real time. Automatic reconnection with debounce and jitter.
Database (optional)
SQLite-backed caching via Sequelize. Thread and user data are cached locally to reduce API calls. Thread cache is kept in sync with realtime events through attachThreadInfoRealtimeSync.
Scheduler
Built-in scheduling domain for deferred or periodic tasks.
Project Documentation
| Document | Contents | |------------------------------------------------|---------------------------------------------------------| | docs/DOCS.md | Full API reference: login, facade, MessengerBot, MQTT, caching | | docs/ARCHITECTURE.md | Source tree layout, bootstrap flow, module design | | CHANGELOG | Version history (repository only; not in the npm package) | | fca-config.example.json | Sample configuration file |
Requirements
- Node.js >= 14.0.0 (LTS recommended)
- npm or any compatible package manager
License
This project is licensed under the Apache License, Version 2.0. See the LICENSE file for the full text.
Links
- npm: @dongdev/fca-unofficial
- GitHub: dongp06/fca-unofficial
- Issues: GitHub Issues
- Author: DongDev — GitHub
