Complete Instagram MQTT protocol with FULL Featured REALTIME And api Rest All in one project .
npm install nodejs-insta-private-api-mqttFull featured Java and nodejs Instagram api private with Mqtt full suport and api rest
Dear users The repository on github is currently unavailable will be available soon
If you Like This Project You Can Help Me with Donation revolut , My revolut revtag is @gvny22
This project implements a complete and production-ready MQTT protocol client for Instagram's real-time messaging infrastructure. Instagram uses MQTT natively for direct messages, notifications, and real-time presence updates. This library replicates that exact implementation, allowing developers to build high-performance bots and automation tools that communicate with Instagram's backend using the same protocol the official app uses.
By leveraging MQTT instead of Instagram's REST API, this library achieves sub-500ms message latency, bidirectional real-time communication, and native support for notifications, presence tracking, and thread management. The implementation is reverse-engineered from Instagram's mobile app protocol and tested extensively for reliability and compatibility.
This library is optimized for Direct Messages and implements the core MQTT protocols used by Instagram for:
- Real-time message delivery and reception
- Presence status tracking
- Typing indicators
- Notifications for follows, mentions, and calls
- Group thread management
For full MQTT coverage analysis, see MQTT_COVERAGE_ANALYSIS.md
``bash`
npm install nodejs-insta-private-api-mqtt
Requires Node.js 18 or higher.
---
Default Device: Samsung Galaxy S25 Ultra (Android 15) - used automatically if you don't set a custom device.
This feature allows you to choose which phone model Instagram sees when your bot connects. Instead of using a default device, you can emulate any Android phone like Samsung Galaxy S25 Ultra, Huawei P60 Pro, Google Pixel 9, and more.
- Avoid detection - Use realistic, modern device fingerprints
- Match your target audience - Emulate devices popular in specific regions
- Testing - Test how Instagram behaves with different devices
- Reduce bans - Modern devices are less likely to trigger security checks
`javascript
const { IgApiClient } = require('nodejs-insta-private-api');
const ig = new IgApiClient();
// Set device BEFORE login
ig.state.usePresetDevice('Samsung Galaxy S25 Ultra');
// Now login - Instagram will see a Samsung S25 Ultra
await ig.login({
username: 'your_username',
password: 'your_password'
});
console.log('Logged in with device:', ig.state.deviceString);
`
| Device Name | Manufacturer | Android Version |
|-------------|--------------|-----------------|
| Samsung Galaxy S25 Ultra | Samsung | Android 15 |
| Samsung Galaxy S24 Ultra | Samsung | Android 14 |
| Samsung Galaxy S23 Ultra | Samsung | Android 14 |
| Samsung Galaxy Z Fold 5 | Samsung | Android 14 |
| Huawei P60 Pro | Huawei | Android 12 |
| Huawei Mate 60 Pro | Huawei | Android 12 |
| Google Pixel 8 Pro | Google | Android 14 |
| Google Pixel 9 Pro | Google | Android 15 |
| OnePlus 12 | OnePlus | Android 14 |
| Xiaomi 14 Ultra | Xiaomi | Android 14 |
| Xiaomi Redmi Note 13 Pro | Xiaomi | Android 14 |
| OPPO Find X7 Ultra | OPPO | Android 14 |
For complete control, use setCustomDevice() with your own configuration:
`javascript
const ig = new IgApiClient();
ig.state.setCustomDevice({
manufacturer: 'samsung',
model: 'SM-S928B',
device: 'e3q',
androidVersion: '15',
androidApiLevel: 35,
resolution: '1440x3120',
dpi: '505dpi',
chipset: 'qcom',
build: 'UP1A.231005.007'
});
`
---
`javascript
const { IgApiClient, RealtimeClient, useMultiFileAuthState } = require('nodejs-insta-private-api-mqtt');
async function startBot() {
const ig = new IgApiClient();
const auth = await useMultiFileAuthState('./auth_info_ig');
ig.state.usePresetDevice('Samsung Galaxy S25 Ultra');
const realtime = new RealtimeClient(ig);
realtime.on('connected', () => {
console.log('Bot is online and MQTT is connected!');
});
realtime.on('message_live', async (msg) => {
console.log([${msg.username}]: ${msg.text});
if (msg.text.toLowerCase() === 'ping') {
await realtime.directCommands.sendText({
threadId: msg.thread_id,
text: 'pong!'
});
}
});
if (!auth.hasSession()) {
await ig.login({
username: 'your_username',
password: 'your_password'
});
await auth.saveCreds(ig);
await realtime.startRealTimeListener();
await auth.saveMqttSession(realtime);
}
}
startBot().catch(console.error);
`
---
All MQTT direct messaging functionality is available through realtime.directCommands. These methods use proper payload formatting that matches the instagram_mqtt library format.
#### Send Text Message
`javascript`
await realtime.directCommands.sendText({
threadId: '340282366841710300949128114477782749726',
text: 'Hello from MQTT!'
});
#### Send Text (Alternative Signature)
`javascript`
await realtime.directCommands.sendTextViaRealtime(threadId, 'Hello!');
#### Reply to Message (Quote Reply)
`javascript`
await realtime.directCommands.replyToMessage(threadId, messageId, 'This is my reply');
#### Edit Message
`javascript`
await realtime.directCommands.editMessage(threadId, itemId, 'Updated text here');
#### Delete Message
`javascript`
await realtime.directCommands.deleteMessage(threadId, itemId);
---
#### Send Hashtag
`javascript`
await realtime.directCommands.sendHashtag({
threadId: threadId,
hashtag: 'photography',
text: 'Check this out'
});
#### Send Like (Heart)
`javascript`
await realtime.directCommands.sendLike({
threadId: threadId
});
#### Send Location
`javascript`
await realtime.directCommands.sendLocation({
threadId: threadId,
locationId: '123456789',
text: 'Meet me here'
});
#### Send Media (Share Post)
`javascript`
await realtime.directCommands.sendMedia({
threadId: threadId,
mediaId: 'media_id_here',
text: 'Check this post'
});
#### Send Profile
`javascript`
await realtime.directCommands.sendProfile({
threadId: threadId,
userId: '12345678',
text: 'Follow this account'
});
#### Send User Story
`javascript`
await realtime.directCommands.sendUserStory({
threadId: threadId,
storyId: 'story_id_here',
text: 'Did you see this?'
});
#### Send Link
`javascript`
await realtime.directCommands.sendLink({
threadId: threadId,
link: 'https://example.com',
text: 'Check this link'
});
#### Send Animated Media (GIF/Sticker)
`javascript`
await realtime.directCommands.sendAnimatedMedia({
threadId: threadId,
id: 'giphy_id_here',
isSticker: false
});
#### Send Voice Message (after upload)
`javascript`
await realtime.directCommands.sendVoice({
threadId: threadId,
uploadId: 'your_upload_id',
waveform: [0.1, 0.5, 0.8, 0.3],
waveformSamplingFrequencyHz: 10
});
---
#### Send Reaction
`javascript`
await realtime.directCommands.sendReaction({
threadId: threadId,
itemId: messageId,
reactionType: 'like'
});
#### Send Emoji Reaction
`javascript`
await realtime.directCommands.sendReaction({
threadId: threadId,
itemId: messageId,
reactionType: 'emoji',
emoji: '🔥'
});
#### Remove Reaction
`javascript`
await realtime.directCommands.removeReaction({
threadId: threadId,
itemId: messageId
});
---
#### Mark Message as Seen
`javascript`
await realtime.directCommands.markAsSeen({
threadId: threadId,
itemId: messageId
});
#### Indicate Typing
`javascript
// Start typing
await realtime.directCommands.indicateActivity({
threadId: threadId,
isActive: true
});
// Stop typing
await realtime.directCommands.indicateActivity({
threadId: threadId,
isActive: false
});
`
#### Mark Visual Message as Seen (disappearing media)
`javascript`
await realtime.directCommands.markVisualMessageSeen({
threadId: threadId,
itemId: messageId
});
---
#### Add Member to Thread
`javascript
await realtime.directCommands.addMemberToThread(threadId, userId);
// Add multiple members
await realtime.directCommands.addMemberToThread(threadId, [userId1, userId2]);
`
#### Remove Member from Thread
`javascript`
await realtime.directCommands.removeMemberFromThread(threadId, userId);
#### Leave Thread
`javascript`
await realtime.directCommands.leaveThread(threadId);
#### Update Thread Title
`javascript`
await realtime.directCommands.updateThreadTitle(threadId, 'New Group Name');
#### Mute Thread
`javascript
await realtime.directCommands.muteThread(threadId);
// Mute until specific time
await realtime.directCommands.muteThread(threadId, Date.now() + 3600000);
`
#### Unmute Thread
`javascript`
await realtime.directCommands.unmuteThread(threadId);
---
#### Approve Pending Thread
`javascript`
await realtime.directCommands.approveThread(threadId);
#### Decline Pending Thread
`javascript`
await realtime.directCommands.declineThread(threadId);
---
#### Block User in Thread
`javascript`
await realtime.directCommands.blockUserInThread(threadId, userId);
#### Report Thread
`javascript`
await realtime.directCommands.reportThread(threadId, 'spam');
---
#### Send Disappearing Photo
`javascript`
await realtime.directCommands.sendDisappearingPhoto({
threadId: threadId,
uploadId: 'your_upload_id',
viewMode: 'once' // 'once' or 'replayable'
});
#### Send Disappearing Video
`javascript`
await realtime.directCommands.sendDisappearingVideo({
threadId: threadId,
uploadId: 'your_upload_id',
viewMode: 'once'
});
---
#### Send Screenshot Notification
`javascript`
await realtime.directCommands.sendScreenshotNotification({
threadId: threadId,
itemId: messageId
});
#### Send Replay Notification
`javascript`
await realtime.directCommands.sendReplayNotification({
threadId: threadId,
itemId: messageId
});
---
These methods handle the full flow: upload via HTTP rupload, then broadcast to thread.
#### Send Photo
`javascript
const fs = require('fs');
const photoBuffer = fs.readFileSync('./photo.jpg');
await realtime.directCommands.sendPhoto({
threadId: threadId,
photoBuffer: photoBuffer,
caption: 'Check this out',
mimeType: 'image/jpeg'
});
`
#### Send Video
`javascript
const fs = require('fs');
const videoBuffer = fs.readFileSync('./video.mp4');
await realtime.directCommands.sendVideo({
threadId: threadId,
videoBuffer: videoBuffer,
caption: 'Watch this',
duration: 15,
width: 720,
height: 1280
});
`
---
`javascript`
await realtime.directCommands.sendForegroundState({
inForegroundApp: true,
inForegroundDevice: true,
keepAliveTimeout: 60
});
---
| Method | Description |
|--------|-------------|
| sendText({ threadId, text }) | Send text message |sendTextViaRealtime(threadId, text)
| | Send text (alternative) |sendHashtag({ threadId, hashtag, text })
| | Send hashtag |sendLike({ threadId })
| | Send heart/like |sendLocation({ threadId, locationId, text })
| | Send location |sendMedia({ threadId, mediaId, text })
| | Share a post |sendProfile({ threadId, userId, text })
| | Share a profile |sendUserStory({ threadId, storyId, text })
| | Share a story |sendLink({ threadId, link, text })
| | Send a link |sendAnimatedMedia({ threadId, id, isSticker })
| | Send GIF/sticker |sendVoice({ threadId, uploadId, waveform })
| | Send voice message |sendReaction({ threadId, itemId, emoji })
| | React to message |removeReaction({ threadId, itemId })
| | Remove reaction |replyToMessage(threadId, messageId, text)
| | Quote reply |editMessage(threadId, itemId, newText)
| | Edit message |deleteMessage(threadId, itemId)
| | Delete message |markAsSeen({ threadId, itemId })
| | Mark as read |indicateActivity({ threadId, isActive })
| | Typing indicator |markVisualMessageSeen({ threadId, itemId })
| | Mark disappearing media seen |addMemberToThread(threadId, userId)
| | Add group member |removeMemberFromThread(threadId, userId)
| | Remove group member |leaveThread(threadId)
| | Leave group |updateThreadTitle(threadId, title)
| | Change group name |muteThread(threadId, muteUntil)
| | Mute thread |unmuteThread(threadId)
| | Unmute thread |approveThread(threadId)
| | Accept message request |declineThread(threadId)
| | Decline message request |blockUserInThread(threadId, userId)
| | Block user |reportThread(threadId, reason)
| | Report thread |sendDisappearingPhoto({ threadId, uploadId })
| | Send view-once photo |sendDisappearingVideo({ threadId, uploadId })
| | Send view-once video |sendScreenshotNotification({ threadId, itemId })
| | Screenshot alert |sendReplayNotification({ threadId, itemId })
| | Replay alert |sendPhoto({ threadId, photoBuffer, caption })
| | Upload & send photo |sendVideo({ threadId, videoBuffer, caption })
| | Upload & send video |sendForegroundState(state)
| | Connection keepalive |
---
This feature provides Baileys-style media download for Instagram DM messages.
`javascript
const {
downloadContentFromMessage,
isViewOnceMedia
} = require('nodejs-insta-private-api-mqtt');
const fs = require('fs');
realtime.on('message', async (data) => {
const msg = data.message;
if (isViewOnceMedia(msg)) {
const stream = await downloadContentFromMessage(msg);
let buffer = Buffer.from([]);
for await (const chunk of stream) {
buffer = Buffer.concat([buffer, chunk]);
}
const ext = stream.mediaInfo.type.includes('video') ? 'mp4' : 'jpg';
fs.writeFileSync(viewonce_${Date.now()}.${ext}, buffer);`
}
});
`javascript
const { downloadMediaBuffer, hasMedia } = require('nodejs-insta-private-api-mqtt');
realtime.on('message', async (data) => {
const msg = data.message;
if (hasMedia(msg)) {
const { buffer, mediaInfo } = await downloadMediaBuffer(msg);
fs.writeFileSync(media_${Date.now()}.jpg, buffer);`
}
});
| Function | Description |
|----------|-------------|
| downloadContentFromMessage(message) | Download as stream |downloadMediaBuffer(message)
| | Download as Buffer |extractMediaUrls(message)
| | Get CDN URLs |hasMedia(message)
| | Check if has media |getMediaType(message)
| | Get media type |isViewOnceMedia(message)
| | Check if disappearing |
---
`javascript
const { IgApiClient, RealtimeClient } = require('nodejs-insta-private-api-mqtt');
const fs = require('fs');
(async () => {
const ig = new IgApiClient();
const session = JSON.parse(fs.readFileSync('session.json'));
await ig.state.deserialize(session);
const realtime = new RealtimeClient(ig);
const inbox = await ig.direct.getInbox();
await realtime.connect({
graphQlSubs: ['ig_sub_direct', 'ig_sub_direct_v2_message_sync'],
irisData: inbox
});
console.log('Bot Active\n');
realtime.on('message', async (data) => {
const msg = data.message;
if (!msg?.text) return;
console.log([${msg.from_user_id}]: ${msg.text});
if (msg.text.toLowerCase().includes('hello')) {
await realtime.directCommands.sendText({
threadId: msg.thread_id,
text: 'Hey! Thanks for reaching out!'
});
}
});
await new Promise(() => {});
})();
`
`javascript
realtime.on('message', async (data) => {
const msg = data.message;
if (!msg?.text) return;
// Mark as seen
await realtime.directCommands.markAsSeen({
threadId: msg.thread_id,
itemId: msg.item_id
});
// Show typing
await realtime.directCommands.indicateActivity({
threadId: msg.thread_id,
isActive: true
});
await new Promise(r => setTimeout(r, 2000));
if (msg.text.toLowerCase().includes('hi')) {
await realtime.directCommands.sendText({
threadId: msg.thread_id,
text: 'Hello there!'
});
// React with emoji
await realtime.directCommands.sendReaction({
threadId: msg.thread_id,
itemId: msg.item_id,
emoji: '👋'
});
}
// Stop typing
await realtime.directCommands.indicateActivity({
threadId: msg.thread_id,
isActive: false
});
});
`
---
`javascript`
const authState = await useMultiFileAuthState('./auth_folder');
| Method | Description |
|--------|-------------|
| hasSession() | Check if credentials exist |hasMqttSession()
| | Check if MQTT session exists |loadCreds(ig)
| | Load saved credentials |saveCreds(ig)
| | Save current credentials |isSessionValid(ig)
| | Validate with Instagram |loadMqttSession()
| | Get saved MQTT session |saveMqttSession(realtime)
| | Save MQTT session |clearSession()
| | Delete all session files |
---
`javascript
// Login
await ig.login({
username: 'your_username',
password: 'your_password'
});
// Save session
const serialized = ig.state.serialize();
fs.writeFileSync('session.json', JSON.stringify(serialized));
// Load session
const session = JSON.parse(fs.readFileSync('session.json'));
await ig.state.deserialize(session);
`
`javascript
// Get inbox
const inbox = await ig.direct.getInbox();
// Get thread
const thread = await ig.direct.getThread(threadId);
// Send text (REST fallback)
await ig.direct.sendText({ thread_ids: [threadId], text: 'Hello' });
`
---
Everything below uses the REST HTTP endpoints, not MQTT. You don't need RealtimeClient for any of this — just IgApiClient and a valid session.
`javascript
const { IgApiClient } = require('nodejs-insta-private-api-mqtt');
const ig = new IgApiClient();
ig.state.usePresetDevice('Samsung Galaxy S25 Ultra');
await ig.login({ username: 'your_username', password: 'your_password' });
// you're ready to use any of the methods below
`
---
#### Basic Login
`javascript
await ig.login({ username: 'your_username', password: 'your_password' });
// or the shorter way
await ig.account.login('your_username', 'your_password');
`
#### Two-Factor Authentication (2FA)
When Instagram asks for a 2FA code, login() throws an error that contains the two_factor_identifier. Catch it and finish the flow:
`javascript`
try {
await ig.account.login('username', 'password');
} catch (err) {
if (err.response?.body?.two_factor_required) {
const twoFactorId = err.response.body.two_factor_info.two_factor_identifier;
// user enters the code from their authenticator app or SMS
const code = '123456';
await ig.account.twoFactorLogin('username', code, twoFactorId, '1');
// verificationMethod: '1' = SMS, '3' = TOTP app
console.log('2FA login successful');
}
}
#### TOTP Two-Factor Setup
Set up authenticator-app-based 2FA for your account. This generates a seed you can add to Google Authenticator, Authy, etc.
`javascript
// generate a TOTP seed (this is the secret key for your authenticator app)
const seed = await ig.totp.generateSeed();
console.log('Add this to your authenticator app:', seed.totp_seed);
// after adding it, verify with a code from the app to confirm
const code = '123456'; // from authenticator app
await ig.totp.enable(code);
console.log('TOTP 2FA is now enabled');
// get backup codes in case you lose your authenticator
const backupCodes = await ig.totp.getBackupCodes();
console.log('Save these somewhere safe:', backupCodes);
// disable TOTP 2FA
await ig.totp.disable();
`
#### SMS-Based 2FA
`javascript
// enable SMS 2FA
await ig.totp.smsTwoFactorEnable('+1234567890');
// confirm with the code you received
await ig.totp.smsTwoFactorConfirm('123456');
// disable it later
await ig.totp.disableSmsTwoFactor();
`
#### Challenge Resolver
When Instagram triggers a security checkpoint (suspicious login, new location, etc.), you need to resolve the challenge:
`javascript`
try {
await ig.account.login('username', 'password');
} catch (err) {
if (err.response?.body?.challenge) {
const challengeUrl = err.response.body.challenge.api_path;
// option 1: automatic resolution (tries to handle it for you)
const result = await ig.challenge.auto(challengeUrl);
console.log('Challenge result:', result);
// option 2: manual step-by-step
// first, see what verification methods are available
const page = await ig.challenge.getChallengePage(challengeUrl);
// choose SMS (0) or email (1)
await ig.challenge.selectVerifyMethod(challengeUrl, 1);
// enter the code you received
await ig.challenge.sendSecurityCode(challengeUrl, '123456');
}
}
---
#### Get Current User Info
`javascript`
const me = await ig.account.currentUser();
console.log('Username:', me.user.username);
console.log('Follower count:', me.user.follower_count);
#### Edit Profile
`javascript`
await ig.account.editProfile({
fullName: 'John Doe',
biography: 'building cool stuff',
externalUrl: 'https://example.com',
email: 'john@example.com',
phoneNumber: '+1234567890',
username: 'johndoe_new'
});
#### Set Biography
`javascript`
await ig.account.setBiography('i like building things that work');
#### Set External URL / Remove Bio Links
`javascript`
await ig.account.setExternalUrl('https://mywebsite.com');
await ig.account.removeBioLinks();
#### Change Password
`javascript`
await ig.account.changePassword('old_password_here', 'new_password_here');
#### Switch to Private / Public
`javascript`
await ig.account.setPrivate();
await ig.account.setPublic();
#### Set Gender
`javascript`
// 1 = male, 2 = female, 3 = prefer not to say, 4 = custom
await ig.account.setGender(1);
#### Profile Picture
`javascript`
// you need an upload_id from a previous photo upload
await ig.account.profilePictureChange(uploadId);
await ig.account.profilePictureRemove();
#### Password Encryption Keys
`javascript`
// get the public keys for Instagram's password encryption (needed for some flows)
const keys = await ig.account.passwordPublicKeys();
#### Account Recovery
`javascript
// send password recovery via email
await ig.account.sendRecoveryFlowEmail('user@example.com');
// or via SMS
await ig.account.sendRecoveryFlowSms('+1234567890');
`
---
#### Fetch User Info
`javascript
// by username
const user = await ig.user.infoByUsername('instagram');
console.log('User ID:', user.pk);
console.log('Followers:', user.follower_count);
// by user ID
const userById = await ig.user.info('25025320');
`
#### Resolve Username ↔ User ID
`javascript
const userId = await ig.user.userIdFromUsername('instagram');
// returns '25025320'
const username = await ig.user.usernameFromUserId('25025320');
// returns 'instagram'
`
#### Search Users
`javascript
const results = await ig.user.search('john', 20);
results.users.forEach(u => {
console.log(u.username, '-', u.full_name);
});
// exact match
const exact = await ig.user.searchExact('johndoe');
`
#### Follow / Unfollow
`javascript`
await ig.user.follow('25025320');
await ig.user.unfollow('25025320');
#### Block / Unblock
`javascript
await ig.user.block('25025320');
await ig.user.unblock('25025320');
// see all blocked users
const blocked = await ig.user.getBlockedUsers();
`
#### Mute / Unmute
`javascript`
// mute posts, stories, or both
await ig.user.mute('25025320', { mutePosts: true, muteStories: true });
await ig.user.unmute('25025320', { unmutePosts: true, unmuteStories: true });
#### Get Followers / Following (with pagination)
`javascript
// get up to 200 followers at a time
const followers = await ig.user.getFollowers('25025320', 200);
console.log('Got', followers.users.length, 'followers');
// pagination — pass the maxId from the previous response
const moreFollowers = await ig.user.getFollowers('25025320', 200, followers.next_max_id);
// same for following
const following = await ig.user.getFollowing('25025320', 200);
`
#### Get User's Posts (with pagination)
`javascript
// grab the latest 50 posts
const posts = await ig.user.getUserMedias('25025320', 50);
posts.items.forEach(item => {
console.log(item.pk, '-', item.caption?.text?.substring(0, 50));
});
// next page
const morePosts = await ig.user.getUserMedias('25025320', 50, posts.next_max_id);
`
#### Get User's Reels / Clips
`javascript`
const reels = await ig.user.getUserReels('25025320', 50);
const clips = await ig.user.getUserClips('25025320', 50);
#### Get User's Stories
`javascript`
const stories = await ig.user.getUserStories('25025320');
stories.reel?.items.forEach(story => {
console.log('Story:', story.pk, 'taken at:', story.taken_at);
});
#### Get Tagged Posts
`javascript`
const tagged = await ig.user.getUserTags('25025320');
#### Mutual Followers
`javascript`
const mutual = await ig.user.getMutualFollowers('25025320');
#### Remove a Follower
`javascript`
await ig.user.removeFollower('25025320');
#### Report a User
`javascript`
// reason: 1 = spam, 2 = inappropriate, etc.
await ig.user.report('25025320', 1);
#### Get Suggested Users
`javascript`
const suggestions = await ig.user.getSuggested();
#### Friendship Status (Bulk)
`javascript`
// check relationship status with multiple users at once
const statuses = await ig.user.getFriendshipStatuses(['12345', '67890', '11111']);
---
#### Get Media Info
`javascript`
const info = await ig.media.info('3193593212003331660');
console.log('Type:', info.items[0].media_type);
console.log('Likes:', info.items[0].like_count);
#### PK / Shortcode Conversion
These are super useful when you have a post URL and need the numeric ID, or the other way around.
`javascript
const { MediaRepository } = require('nodejs-insta-private-api-mqtt');
// convert shortcode to numeric PK
const pk = MediaRepository.mediaPkFromCode('CxR7Bsejq5M');
// '3193593212003331660'
// convert PK back to shortcode
const code = MediaRepository.mediaCodeFromPk('3193593212003331660');
// 'CxR7Bsejq5M'
// extract PK directly from a full URL
const pkFromUrl = MediaRepository.mediaPkFromUrl('https://www.instagram.com/p/CxR7Bsejq5M/');
// '3193593212003331660'
`
#### Like / Unlike
`javascript`
await ig.media.like('3193593212003331660');
await ig.media.unlike('3193593212003331660');
#### Comment
`javascript`
const comment = await ig.media.comment('3193593212003331660', 'great shot!');
console.log('Comment ID:', comment.comment.pk);
#### Reply to a Comment
`javascript`
await ig.media.replyToComment('3193593212003331660', '17858893269000001', '@user thanks!');
#### Like / Unlike Comments
`javascript`
await ig.media.likeComment('3193593212003331660', '17858893269000001');
await ig.media.unlikeComment('3193593212003331660', '17858893269000001');
#### Pin / Unpin Comments
`javascript`
await ig.media.pinComment('3193593212003331660', '17858893269000001');
await ig.media.unpinComment('3193593212003331660', '17858893269000001');
#### Delete Comments (Single or Bulk)
`javascript
// single
await ig.media.deleteComment('3193593212003331660', '17858893269000001');
// bulk delete
await ig.media.bulkDeleteComments('3193593212003331660', [
'17858893269000001',
'17858893269000002',
'17858893269000003'
]);
`
#### Get Comments (Paginated)
`javascript`
const comments = await ig.media.comments('3193593212003331660', null, 20);
// next page:
const moreComments = await ig.media.comments('3193593212003331660', comments.next_min_id, 20);
#### Get Comment Thread (Replies to a Comment)
`javascript`
const thread = await ig.media.commentThreadComments('3193593212003331660', '17858893269000001');
#### Get Likers
`javascript`
const likers = await ig.media.likers('3193593212003331660');
likers.users.forEach(u => console.log(u.username));
#### Save / Unsave
`javascript
await ig.media.save('3193593212003331660');
// save to a specific collection
await ig.media.save('3193593212003331660', 'collection_id_here');
await ig.media.unsave('3193593212003331660');
`
#### Archive / Unarchive
`javascript`
await ig.media.archive('3193593212003331660');
await ig.media.unarchive('3193593212003331660');
#### Delete Media
`javascript`
// mediaType: 'PHOTO', 'VIDEO', 'CAROUSEL'
await ig.media.delete('3193593212003331660', 'PHOTO');
#### Edit Caption
`javascript`
await ig.media.edit('3193593212003331660', 'new caption goes here', {
usertags: { in: [{ user_id: '12345', position: [0.5, 0.5] }] }
});
#### Enable / Disable Comments
`javascript`
await ig.media.disableComments('3193593212003331660');
await ig.media.enableComments('3193593212003331660');
#### Download Media
`javascript
// download by URL
const buffer = await ig.media.downloadByUrl('https://instagram.cdnurl.com/...');
// download by PK (photo or video)
const photo = await ig.media.downloadPhoto('3193593212003331660');
const video = await ig.media.downloadVideo('3193593212003331660');
`
#### oEmbed
`javascript`
const oembed = await ig.media.oembed('https://www.instagram.com/p/CxR7Bsejq5M/');
console.log(oembed.title, '-', oembed.author_name);
#### Get User Who Posted a Media
`javascript`
const user = await ig.media.getUser('3193593212003331660');
---
Upload and browse Reels through the REST API.
#### Upload a Reel
`javascript`
const result = await ig.clip.upload({
videoBuffer: fs.readFileSync('./reel.mp4'),
caption: 'check this out',
coverImage: fs.readFileSync('./cover.jpg'), // optional
duration: 15,
width: 1080,
height: 1920,
audisMuted: false,
});
console.log('Reel PK:', result.media?.pk);
#### Configure a Video as Reel (after uploading separately)
`javascript`
const configured = await ig.clip.configure({
upload_id: uploadId,
caption: 'my reel',
duration: 15,
width: 1080,
height: 1920,
});
#### Discover Reels / Connected Reels
`javascript
// the explore-style reels feed
const discover = await ig.clip.discoverReels(10);
discover.items.forEach(reel => {
console.log(reel.media.code, '-', reel.media.caption?.text?.substring(0, 40));
});
// paginate
const more = await ig.clip.discoverReels(10, discover.paging_info?.max_id);
// connected reels (similar reels after watching one)
const connected = await ig.clip.connectedReels(10);
`
#### Download a Reel
`javascript
const reelBuffer = await ig.clip.download('3193593212003331660');
// or from URL
const reelFromUrl = await ig.clip.downloadByUrl('https://instagram.cdnurl.com/...');
`
#### Get Music Info for Reels
`javascript`
const music = await ig.clip.musicInfo({ music_canonical_id: '12345' });
---
#### Get Your Story Feed (Tray)
`javascript`
const tray = await ig.story.getFeed();
tray.tray.forEach(reel => {
console.log(reel.user.username, '- stories:', reel.media_count);
});
#### Get Someone's Stories
`javascript`
const stories = await ig.story.getUserStories('25025320');
stories.reel?.items.forEach(item => {
console.log('Type:', item.media_type, 'Taken at:', item.taken_at);
});
#### Upload a Photo Story
`javascript`
const result = await ig.story.upload({
file: fs.readFileSync('./story.jpg'),
caption: 'hello world', // optional
});
console.log('Story ID:', result.media?.pk);
#### Upload a Video Story
`javascript`
const result = await ig.story.uploadVideo({
file: fs.readFileSync('./story.mp4'),
duration: 10,
width: 1080,
height: 1920,
});
#### Mark Stories as Seen
`javascript`
await ig.story.seen([
{ id: 'media_id_1', taken_at: 1700000000, user: { pk: '25025320' } }
]);
#### React to a Story
`javascript`
await ig.story.react({
mediaId: '3193593212003331660',
reelId: '25025320',
emoji: '🔥'
});
---
#### Get User's Highlights
`javascript`
const highlights = await ig.highlights.getHighlightsTray('25025320');
highlights.tray.forEach(h => {
console.log(h.id, '-', h.title);
});
#### Get a Specific Highlight
`javascript`
const highlight = await ig.highlights.getHighlight('highlight:12345678');
#### Create a Highlight
`javascript`
await ig.highlights.create('My Trip', ['story_id_1', 'story_id_2'], 'cover_media_id');
#### Edit a Highlight
`javascript`
await ig.highlights.edit('highlight_id', 'Updated Title', ['new_story_id']);
#### Add / Remove Stories from Highlight
`javascript`
await ig.highlights.addStories('highlight_id', ['story_id_3', 'story_id_4']);
await ig.highlights.removeStories('highlight_id', ['story_id_1']);
#### Update Highlight Cover
`javascript`
await ig.highlights.updateCover('highlight_id', 'cover_media_id');
#### Delete a Highlight
`javascript`
await ig.highlights.delete('highlight_id');
---
#### Upload a Photo Post
`javascript
const upload = await ig.upload.photo({
file: fs.readFileSync('./photo.jpg'),
});
const post = await ig.upload.configurePhoto({
upload_id: upload.upload_id,
caption: 'sunset vibes',
usertags: {
in: [{ user_id: '12345', position: [0.5, 0.5] }]
}
});
console.log('Posted! PK:', post.media?.pk);
`
#### Upload a Video Post
`javascript
const upload = await ig.upload.video({
file: fs.readFileSync('./video.mp4'),
duration: 30,
width: 1080,
height: 1920,
});
const post = await ig.upload.configureVideo({
upload_id: upload.upload_id,
caption: 'check this clip',
duration: 30,
width: 1080,
height: 1920,
});
`
#### Configure as Reel (Clips)
`javascript`
const reel = await ig.upload.configureToClips({
upload_id: upload.upload_id,
caption: 'my first reel',
duration: 15,
width: 1080,
height: 1920,
});
#### Configure as Story
`javascript`
const story = await ig.upload.configureToStory({
upload_id: upload.upload_id,
});
#### Upload a Carousel (Multiple Photos/Videos)
`javascript`
const carousel = await ig.feed.uploadCarousel({
caption: 'summer trip highlights',
children: [
{ type: 'photo', file: fs.readFileSync('./pic1.jpg') },
{ type: 'photo', file: fs.readFileSync('./pic2.jpg') },
{ type: 'video', file: fs.readFileSync('./vid1.mp4'), duration: 10, width: 1080, height: 1080 },
]
});
---
#### Home Timeline
`javascript`
const feed = await ig.timeline.getFeed();
feed.feed_items?.forEach(item => {
const media = item.media_or_ad;
if (media) console.log(media.user.username, '-', media.caption?.text?.substring(0, 40));
});
#### Hashtag Feed
`javascript`
const tagFeed = await ig.feed.getTag('photography');
#### Location Feed
`javascript`
const locFeed = await ig.feed.getLocation('213385402');
#### Liked Posts
`javascript`
const liked = await ig.feed.getLiked();
#### Saved Posts
`javascript`
const saved = await ig.feed.getSaved();
#### Reels Tray (Stories of People You Follow)
`javascript`
const tray = await ig.feed.reelsTray();
#### Explore Feed
`javascript`
const explore = await ig.feed.getExploreFeed();
#### Reels Feed
`javascript`
const reels = await ig.feed.getReelsFeed();
const userReels = await ig.feed.getUserReelsFeed('25025320');
#### Reels Media (Bulk)
`javascript`
// get stories for multiple users at once
const reelsMedia = await ig.feed.reelsMedia(['25025320', '12345678']);
---
`javascript
// get reels from your timeline
const reels = await ig.timeline.reels(10);
// explore reels
const exploreReels = await ig.timeline.exploreReels(10);
`
---
The REST-based DM methods. These work without MQTT — they're regular HTTP requests.
#### Get Inbox
`javascript
const inbox = await ig.direct.getInbox();
inbox.inbox.threads.forEach(t => {
console.log(t.thread_title || t.users[0]?.username, '- last:', t.last_permanent_item?.text);
});
// paginate
const page2 = await ig.direct.getInbox(inbox.inbox.oldest_cursor, 20);
`
#### Pending Inbox (Message Requests)
`javascript`
const pending = await ig.direct.getPendingInbox();
#### Get a Thread
`javascript[${msg.item_type}]
const thread = await ig.direct.getThread(threadId);
thread.thread.items.forEach(msg => {
console.log(msg.user_id, ':', msg.text || );`
});
#### Send Text / Photo / Video / Link via REST
`javascript
await ig.direct.sendText({ thread_ids: [threadId], text: 'hey there!' });
await ig.direct.sendPhoto({
thread_ids: [threadId],
file: fs.readFileSync('./photo.jpg'),
});
await ig.direct.sendVideo({
thread_ids: [threadId],
file: fs.readFileSync('./video.mp4'),
});
await ig.direct.sendLink({
thread_ids: [threadId],
link: 'https://example.com',
text: 'check this out'
});
`
#### Share Media / Profile / Hashtag / Location
`javascript`
await ig.direct.sendMediaShare({ thread_ids: [threadId], mediaId: '3193593212003331660' });
await ig.direct.sendProfile({ thread_ids: [threadId], userId: '25025320' });
await ig.direct.sendHashtag({ thread_ids: [threadId], hashtag: 'photography' });
await ig.direct.sendLocation({ thread_ids: [threadId], locationId: '213385402' });
#### Create a Group Thread
`javascript`
const group = await ig.direct.createGroupThread(['user_id_1', 'user_id_2'], 'Project Team');
console.log('Thread ID:', group.thread_id);
#### Ranked Recipients (Who to Message)
`javascript`
const recipients = await ig.direct.rankedRecipients('raven', 'john');
#### Get Presence
`javascript`
const presence = await ig.direct.getPresence();
#### Mark as Seen / Hide Thread
`javascript`
await ig.direct.markAsSeen(threadId, itemId);
await ig.direct.hideThread(threadId);
---
#### Follow / Unfollow
`javascript`
await ig.friendship.create('25025320'); // follow
await ig.friendship.destroy('25025320'); // unfollow
#### Check Friendship Status
`javascript
const status = await ig.friendship.show('25025320');
console.log('Following:', status.following);
console.log('Followed by:', status.followed_by);
console.log('Blocking:', status.blocking);
// bulk check
const many = await ig.friendship.showMany(['12345', '67890']);
`
#### Approve / Ignore Follow Requests
`javascript
await ig.friendship.approve('25025320');
await ig.friendship.ignore('25025320');
// list pending requests
const pending = await ig.friendship.getPendingRequests();
`
#### Block / Unblock
`javascript
await ig.friendship.block('25025320');
await ig.friendship.unblock('25025320');
const blocked = await ig.friendship.getBlockedUsers();
`
#### Restrict / Unrestrict
`javascript`
await ig.friendship.restrict('25025320');
await ig.friendship.unrestrict('25025320');
#### Mute / Unmute
`javascript`
await ig.friendship.mute('25025320', { muteStories: true, mutePosts: true });
await ig.friendship.unmute('25025320', { unmuteStories: true, unmutePosts: true });
#### Close Friends / Besties
`javascript
// add someone to close friends
await ig.friendship.setCloseFriend('25025320', true);
// remove
await ig.friendship.setCloseFriend('25025320', false);
// bulk update close friends list
await ig.friendship.setBesties(['user1', 'user2'], ['user3']); // add, remove
`
#### Favorites
`javascript
await ig.friendship.setFavorite('25025320');
await ig.friendship.unsetFavorite('25025320');
const favorites = await ig.friendship.getFavoriteFriends();
`
#### Remove Follower
`javascript`
await ig.friendship.removeFollower('25025320');
#### Get Followers / Following
`javascript`
const followers = await ig.friendship.getFollowers('25025320');
const following = await ig.friendship.getFollowing('25025320');
const mutual = await ig.friendship.getMutuafFollowers('25025320');
---
Instagram's unified search endpoint. Covers users, hashtags, places, and music.
#### Top Search (All Types)
`javascript
const results = await ig.fbsearch.topSearch('coffee shop');
console.log('Users:', results.users?.length);
console.log('Places:', results.places?.length);
console.log('Hashtags:', results.hashtags?.length);
// flat version (simpler output)
const flat = await ig.fbsearch.topSearchFlat('coffee', 30);
`
#### Search by Type
`javascript`
const users = await ig.fbsearch.searchUsers('johndoe', 20);
const hashtags = await ig.fbsearch.searchHashtags('photography', 20);
const places = await ig.fbsearch.searchPlaces('new york');
const music = await ig.fbsearch.searchMusic('trending');
#### Search History
`javascript
const recent = await ig.fbsearch.getRecentSearches();
// clear it
await ig.fbsearch.clearRecentSearches();
// manually add something to recent searches
await ig.fbsearch.registerRecentSearch('25025320', 'user');
`
#### Suggested Searches
`javascript`
const suggested = await ig.fbsearch.getSuggestedSearches('users');
#### Null State (Default Explore)
`javascript`
const nullState = await ig.fbsearch.nullStateDynamic();
---
#### Topical Explore
`javascript
const explore = await ig.explore.topicalExplore({
module: 'explore_popular',
cluster_id: 'explore_all:0',
});
// basic explore
const basic = await ig.explore.explore();
// paginate
const page2 = await ig.explore.explore(basic.next_max_id);
`
#### Report Explore Media
`javascript`
await ig.explore.reportExploreMedia('3193593212003331660', 1);
#### Mark Explore as Seen
`javascript`
await ig.explore.markAsSeen();
---
Instagram Notes — the little status messages that show up in the DM tab.
`javascript
// get all notes from people you follow
const notes = await ig.note.getNotes();
const followingNotes = await ig.note.getNotesFollowing();
// create a note (audience: 0 = followers, 1 = close friends)
await ig.note.createNote('currently building something cool', 0);
// delete your note
await ig.note.deleteNote('note_id_here');
// mark notes as seen
await ig.note.lastSeenUpdateNote();
`
---
Requires a business or creator account.
`javascript
// account-level insights
const accountInsights = await ig.insights.account({
ig_drop_table: 'is_feed',
follower_type: 'followers',
timeframe: 'one_week',
query_params: JSON.stringify({ access_token: '', id: '' })
});
// insights for a specific post
const mediaInsights = await ig.insights.media('3193593212003331660');
// reel insights
const reelInsights = await ig.insights.reelInsights('3193593212003331660');
// story insights
const storyInsights = await ig.insights.storyInsights('3193593212003331660');
// all media feed insights
const allMedia = await ig.insights.mediaFeedAll({ count: 20 });
`
---
Fine-grained control over push notification settings.
`javascript
// mute all notifications for 8 hours
await ig.notification.muteAll('8_hour');
// disable all notifications
await ig.notification.disableAll();
// control individual notification types
await ig.notification.likes('off');
await ig.notification.comments('off');
await ig.notification.newFollower('off');
await ig.notification.commentLikes('off');
await ig.notification.directShareActivity('off');
await ig.notification.login('off');
await ig.notification.reminders('off');
// and many more: userTagged, firstPost, followRequestAccepted,
// connection, taggedInBio, pendingDirectShare, directGroupRequests,
// fundraiserSupporter, announcements, reportUpdated...
`
---
`javascript
// search for music
const tracks = await ig.track.search('trending pop');
// get track info
const trackInfo = await ig.track.infoById('track_id_here');
const trackByCanonical = await ig.track.infoByCanonicalId('canonical_id');
// download audio
const audioBuffer = await ig.track.downloadByUrl('https://instagram.cdnurl.com/...');
`
---
Programmatic account creation flow.
`javascript
// check if email/username is available
const emailCheck = await ig.signup.checkEmail('user@example.com');
const usernameCheck = await ig.signup.checkUsername('desired_username');
// get signup config
const config = await ig.signup.getSignupConfig();
// check age eligibility
await ig.signup.checkAgeEligibility(1995, 6, 15);
// send verification email and confirm
await ig.signup.sendVerifyEmail('user@example.com');
await ig.signup.checkConfirmationCode('user@example.com', '123456');
// phone-based signup
await ig.signup.sendSignupSmsCode('+1234567890');
await ig.signup.validateSignupSmsCode('+1234567890', '123456');
// get username suggestions
const suggestions = await ig.signup.getSuggestedUsernames('John Doe', 'john@example.com');
// create the account
const newAccount = await ig.signup.accountsCreate({
username: 'johndoe_2026',
password: 'securepassword123',
email: 'john@example.com',
first_name: 'John',
});
`
---
`javascript
const family = await ig.multipleAccounts.getAccountFamily();
const featured = await ig.multipleAccounts.getFeaturedAccounts();
const info = await ig.multipleAccounts.getAccountInfo();
// switch to another logged-in account
await ig.multipleAccounts.switchAccount('other_user_id');
`
---
`javascript
// get fundraiser info
const info = await ig.fundraiser.standaloneFundraiserInfo('fundraiser_pk');
// create a charity fundraiser
const fundraiser = await ig.fundraiser.createCharityFundraiser({
title: 'Help Local School',
description: 'Raising funds for supplies',
charity_id: 'charity_pk',
goal_amount: 5000,
});
// donate
await ig.fundraiser.donateFundraiser('fundraiser_pk', 25);
`
---
`javascript
// get challenge form (when Instagram shows a captcha)
const form = await ig.captcha.getChallengeForm('/api/v1/challenge/1234/');
// submit reCAPTCHA or hCaptcha response
await ig.captcha.submitRecaptchaResponse('/api/v1/challenge/1234/', 'recaptcha_token');
await ig.captcha.submitHCaptchaResponse('/api/v1/challenge/1234/', 'hcaptcha_token');
`
---
`javascript
// decode a share code (from QR codes, NFC tags, etc.)
const info = ig.share.shareInfo('base64_encoded_code');
// returns { type: 'user', pk: '25025320' }
// parse from URL
const fromUrl = ig.share.shareInfoByUrl('https://www.instagram.com/share/abc123');
// extract share code from URL
const code = ig.share.shareCodeFromUrl('https://www.instagram.com/share/abc123');
`
---
Low-level access to Instagram's Bloks framework. Used internally by some flows.
`javascript
await ig.bloks.action({
action_name: 'some.action.name',
params: { key: 'value' }
});
const layout = await ig.bloks.getLayoutData({
layout_name: 'layout.name',
params: {}
});
// bloks-based password change
await ig.bloks.changePassword('old_pass', 'new_pass');
`
---
Here's every repository and what it covers at a glance.
| Repository | Access | What it does |
|------------|--------|--------------|
| ig.account | Account management | Login, 2FA, edit profile, change password, privacy |ig.user
| | User operations | Info, search, follow, block, mute, get medias/reels/stories |ig.media
| | Media operations | Like, comment, pin, delete, save, archive, download |ig.clip
| | Reels / Clips | Upload, discover, download reels |ig.story
| | Stories | Upload, view, react, highlights |ig.highlights
| | Highlights | Create, edit, delete, manage cover |ig.feed
| | Content feeds | Timeline, hashtag, location, saved, liked, explore |ig.timeline
| | Timeline reels | Reels feed, explore reels |ig.upload
| | Upload & configure | Photo/video upload, configure to feed/story/clips |ig.direct
| | Direct messages | Inbox, send text/media/links, group threads |ig.friendship
| | Relationships | Follow, block, restrict, close friends, favorites |ig.fbsearch
| | Search | Users, hashtags, places, music, search history |ig.explore
| | Explore page | Topical explore, report, mark seen |ig.insights
| | Analytics | Account, media, reel, story insights |ig.note
| | Notes | Create, delete, view notes |ig.notification
| | Notification settings | Enable/disable per-type notifications |ig.totp
| | 2FA management | TOTP setup, SMS 2FA, backup codes |ig.challenge
| | Challenge resolver | Auto-resolve, verify methods, security codes |ig.signup
| | Account creation | Email/phone verification, username check, create account |ig.track
| | Music / Audio | Search tracks, get info, download |ig.share
| | Share codes | Decode QR/NFC share codes, parse URLs |ig.bloks
| | Bloks engine | Low-level Instagram UI actions |ig.fundraiser
| | Fundraisers | Create, donate, get info |ig.multipleAccounts
| | Multi-account | Switch accounts, account family |ig.captcha
| | Captcha handling | reCAPTCHA / hCaptcha submission |ig.location
| | Locations | Location search and info |ig.hashtag
| | Hashtags | Hashtag info and feed |ig.news
| | Activity feed | Activity inbox |ig.collection
| | Collections | Saved collections management |ig.closeFriends
| | Close friends | Close friends list management |
---
| Event | Description |
|-------|-------------|
| connected | MQTT connected |disconnected
| | MQTT disconnected |message
| | New message received |message_live
| | Live message with parsed data |typing
| | Typing indicator |presence
| | User presence update |error
| | Connection error |warning
| | Non-fatal issue (payload errors, etc.) |reconnected
| | Successfully reconnected after a drop |reconnect_failed
| | All reconnect attempts exhausted |auth_failure
| | 3+ consecutive authentication errors (credentials likely expired) |
These events provide deeper access to Instagram's MQTT protocol. They were added for full compatibility with the instagram_mqtt library.
| Event | Description |
|-------|-------------|
| realtimeSub | Raw realtime subscription data (all MQTT messages) |direct
| | Direct message events with parsed data |subscription
| | Legacy subscription event (backwards compatible) |directTyping
| | When someone is typing in a DM thread |appPresence
| | User online/offline status updates |directStatus
| | DM thread status changes |liveWave
| | Instagram Live wave notifications |liveRealtimeComments
| | Real-time comments on Instagram Live |liveTypingIndicator
| | Typing indicator in Live comments |mediaFeedback
| | Media engagement feedback |clientConfigUpdate
| | Client configuration updates |
#### Using the realtimeSub Event
The realtimeSub event gives you access to all raw MQTT messages. This is useful for debugging or implementing custom message handling:
`javascript`
realtime.on('realtimeSub', ({ data, topic }) => {
console.log('Raw MQTT data received:', data);
console.log('Topic:', topic);
});
#### Using the direct Event
The direct event provides parsed direct message updates with automatic JSON parsing of nested values:
`javascript`
realtime.on('direct', (data) => {
console.log('Direct update:', data);
// data.op contains the operation type (e.g., 'add', 'replace', 'remove')
// data.path contains the affected path
// data.value contains the parsed message data
if (data.op === 'add' && data.value) {
console.log('New message:', data.value.text);
}
});
#### Using QueryID-based Events
These events are automatically emitted when Instagram sends specific subscription updates:
`javascript
// Listen for typing indicators
realtime.on('directTyping', (data) => {
console.log('User is typing:', data);
});
// Listen for presence updates (online/offline status)
realtime.on('appPresence', (data) => {
console.log('Presence update:', data);
});
// Listen for DM status changes
realtime.on('directStatus', (data) => {
console.log('Direct status changed:', data);
});
// Listen for Instagram Live comments
realtime.on('liveRealtimeComments', (data) => {
console.log('Live comment:', data);
});
`
#### Complete Example: Multi-Event Listener
Here's a complete example showing how to listen to multiple events:
`javascript
const { IgApiClient, RealtimeClient, useMultiFileAuthState } = require('nodejs-insta-private-api-mqtt');
async function startAdvancedBot() {
const ig = new IgApiClient();
const auth = await useMultiFileAuthState('./auth_info_ig');
ig.state.usePresetDevice('Samsung Galaxy S25 Ultra');
const realtime = new RealtimeClient(ig);
// Standard message handling
realtime.on('message_live', (msg) => {
console.log([${msg.username}]: ${msg.text});
});
// Advanced: Raw MQTT data (useful for debugging)
realtime.on('realtimeSub', ({ data }) => {
console.log('[Debug] Raw MQTT:', JSON.stringify(data).substring(0, 200));
});
// Direct message updates with parsed data
realtime.on('direct', (data) => {
if (data.op === 'add') {
console.log('[Direct] New item added');
}
});
// Typing indicators
realtime.on('directTyping', (data) => {
console.log('[Typing] Someone is typing...');
});
// User presence (online/offline)
realtime.on('appPresence', (data) => {
console.log('[Presence] User status changed');
});
// Login and connect
if (!auth.hasSession()) {
await ig.login({
username: 'your_username',
password: 'your_password'
});
await auth.saveCreds(ig);
} else {
await auth.loadCreds(ig);
}
await realtime.startRealTimeListener();
console.log('Advanced bot with full MQTT events is running!');
}
startAdvancedBot().catch(console.error);
`
---
Media files (photos, videos) are always uploaded via HTTP rupload first. MQTT only sends metadata/references, never the raw bytes. The sendPhoto() and sendVideo() methods handle this automatically.
Instagram has strict rate limits. Add delays between rapid-fire messages to avoid temporary bans.
Always save your session after login to avoid repeated logins which can trigger verification.
---
This update focuses on long-term MQTT stability. If you've been getting random disconnections or rate limit bans, most of that should be gone now. Here's what changed and how to use the new stuff.
- Smart error handling - errors are now classified (rate limit, auth, network, etc.) and each type gets its own backoff strategy
- Reconnect manager - smarter reconnection that knows why it disconnected and adjusts accordingly
- Session persistence helpers - IgApiClientExt with exportState() / importState() for dead-simple session save/restorewithRealtime()
- Convenience wrappers - , withFbns(), withFbnsAndRealtime() to set up clients in one lineGraphQLSubscriptions
- Message ordering - automatic per-thread message queue so multi-message sends always arrive in order
- Subscription exports - , SkywalkerSubscriptions, QueryIDs now exported for custom subscription setupslisten()
- Topic listener cleanup - now returns an unsubscribe functionFbnsClient
- FBNS push notifications - fully working out of the box (no extra packages needed)MQTToTClient
- Low-level MQTT access - , MQTToTConnection, mqttotConnectFlow exported for advanced use415.0.0.36.76
- Updated fingerprint - Instagram version , Samsung Galaxy S24 device profile
- Keepalive rewrite - from 4 overlapping timers down to 2 + a watchdog, way less suspicious traffic
---
The old error handler just retried everything with the same delay. The new one actually looks at what went wrong and reacts differently depending on the error type.
| Type | Triggers On | Base Delay | Max Delay | Multiplier |
|------|-------------|------------|-----------|------------|
| rate_limit | "too many requests", "action blocked", 429 | 60s | 10 min | 1.5x |auth_failure
| | "login_required", "checkpoint", 401, 403 | 10s | 2 min | 2x |network
| | ECONNRESET, ETIMEDOUT, DNS failures | 2s | 1 min | 2x |server
| | 500, 502, 503 | 5s | 2 min | 2x |protocol
| | Thrift parse errors, CONNACK issues | 5s | 1 min | 2x |
All delays include random jitter (0-2s) to prevent multiple bots from hammering the server at the same time.
`javascript
const { IgApiClient, RealtimeClient } = require('nodejs-insta-private-api-mqtt');
const ig = new IgApiClient();
const realtime = new RealtimeClient(ig);
// fires after 3 consecutive auth failures - probably time to re-login
realtime.on('auth_failure', ({ count, error }) => {
console.log(Auth failed ${count} times: ${error});
console.log('Session is probably expired, need to login again');
// your re-login logic here
});
// fires when all 15 retry attempts are used up
realtime.on('error', (err) => {
if (err.message.includes('Max retries')) {
console.log('Gave up reconnecting. Maybe restart the process.');
}
});
// non-fatal stuff - good to log but usually not actionable
realtime.on('warning', ({ type, topic, error }) => {
console.log(Warning [${type}] on ${topic}: ${error});`
});
The error handler keeps a rolling history of the last 50 errors. Handy for dashboards or diagnostics:
`javascript`
// after connecting...
const stats = realtime.errorHandler.getErrorStats();
console.log('Total errors:', stats.errorCount);
console.log('Can still retry:', stats.canRetry);
console.log('Currently rate limited:', stats.isRateLimited);
console.log('Rate limit expires in:', stats.rateLimitRemainingMs, 'ms');
console.log('Breakdown by type:', stats.typeBreakdown);
// e.g. { network: 2, rate_limit: 1 }
---
The ReconnectManager works together with the error handler. When the connection drops, it doesn't just blindly retry - it checks what kind of error caused the disconnect and adjusts the backoff.
- Rate limit errors: 3x multiplier (backs off aggressively to avoid making things worse)
- Auth failures: 2.5x multiplier (slower, gives time for token refresh)
- Everything else: 2x multiplier (standard exponential backoff)
All delays include up to 30% jitter so if you're running multiple bots they don't all reconnect at the exact same second.
`javascript
realtime.on('reconnected', () => {
console.log('Back online after a disconnect');
});
realtime.on('reconnect_failed', () => {
console.log('Could not reconnect after all attempts');
// maybe send yourself a notification, restart the process, etc.
});
`
You don't need to configure any of this - it's all automatic. The RealtimeClient uses the ErrorHandler + ReconnectManager for high-level reconnection, while MQTToTClient has its own low-level reconnect loop for transport-level drops. They work independently but cover different failure scenarios.
---
If you're coming from instagram_mqtt, you might be used to withRealtime() and exportState(). We've got those now.
`javascript
const { IgApiClientExt } = require('nodejs-insta-private-api-mqtt');
const fs = require('fs');
const ig = new IgApiClientExt();
// first run - login and save
await ig.login({ username: 'myuser', password: 'mypass' });
const state = await ig.exportState();
fs.writeFileSync('saved_state.json', state);
// next run - restore from file
const ig2 = new IgApiClientExt();
const saved = fs.readFileSync('saved_state.json', 'utf8');
await ig2.importState(saved);
// ig2 is now logged in, no need to call login() again
`
exportState() serializes the entire client state (cookies, tokens, device info) through a hook system. You can add your own hooks if you need to persist additional data:
`javascript`
ig.addStateHook({
name: 'myCustomData',
onExport: async (client) => {
return { lastSyncTime: Date.now(), someConfig: 'value' };
},
onImport: async (data, client) => {
console.log('Restoring custom data:', data);
// do whatever you need with the restored data
}
});
`javascript
const { IgApiClient, withRealtime } = require('nodejs-insta-private-api-mqtt');
const ig = new IgApiClient();
// this upgrades ig to IgApiClientExt and adds a lazy .realtime property
const client = withRealtime(ig);
await client.login({ username: 'myuser', password: 'mypass' });
// .realtime is created lazily - only when you first access it
client.realtime.on('message_live', (msg) => {
console.log(${msg.username}: ${msg.text});
});
await client.realtime.startRealTimeListener();
// and since it's an IgApiClientExt, you can export the full state
const state = await client.exportState();
`
Note: withRealtime() doesn't create the RealtimeClient immediately. It sets up a lazy getter, so the client is only instantiated when you first access client.realtime. No surprise connections.
Attach FBNS (Facebook Notification Service) for push notifications. The FBNS auth state is automatically included when you call exportState(), so you don't need to re-authenticate every time you restart:
`javascript
const { IgApiClient, withFbns } = require('nodejs-insta-private-api-mqtt');
const ig = new IgApiClient();
const client = withFbns(ig);
// client.fbns is now available
// FBNS auth state is automatically included in exportState()
`
``javascript
const { IgApiClient, withFbnsAndRealtime } = require('nodejs-insta-private-api-mqtt');