nodejs-insta-private-api-mqtt 1.1.4 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -84,16 +84,14 @@ exports.FBNS = {
84
84
  PACKAGE: 'com.instagram.android',
85
85
  APP_ID: '567310203415052',
86
86
  HOST_NAME_V6: 'mqtt-mini.facebook.com',
87
- CLIENT_CAPABILITIES: 6143,
88
- ENDPOINT_CAPABILITIES: 255,
87
+ CLIENT_CAPABILITIES: 439,
88
+ ENDPOINT_CAPABILITIES: 128,
89
89
  CLIENT_STACK: 3,
90
90
  PUBLISH_FORMAT: 1,
91
91
  };
92
92
  exports.REALTIME = {
93
93
  HOST_NAME_V6: 'edge-mqtt.facebook.com',
94
94
  };
95
- exports.APP_VERSION = '380.0.0.40.94';
96
- exports.APP_VERSION_CODE = '525123456';
97
95
  // TODO: exclude in release
98
96
  /* eslint @typescript-eslint/no-unused-vars: "off" */
99
97
  exports.PossibleTopics = [
@@ -13,15 +13,12 @@ class Request {
13
13
  baseURL: 'https://i.instagram.com/',
14
14
  timeout: 30000,
15
15
  headers: {
16
- 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
17
- },
18
- // Modern TLS settings to bypass basic fingerprinting (Strict Instagram Fizz mimicry)
19
- httpsAgent: new (require('https').Agent)({
20
- ciphers: 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305',
21
- honorCipherOrder: true,
22
- minVersion: 'TLSv1.3', // Instagram 2026 enforces TLS 1.3
23
- maxVersion: 'TLSv1.3'
24
- })
16
+ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
17
+ 'Accept-Encoding': 'gzip, deflate',
18
+ 'Connection': 'keep-alive',
19
+ 'Accept': '*/*',
20
+ 'Accept-Language': 'en-US'
21
+ }
25
22
  });
26
23
  }
27
24
 
@@ -182,35 +179,33 @@ class Request {
182
179
  error.response = response;
183
180
  error.status = response.status;
184
181
  error.data = data;
182
+ // Anti-bot: Randomize delay on error to mimic human reaction time
185
183
  return error;
186
184
  }
187
185
 
188
186
  getDefaultHeaders() {
189
187
  return {
190
188
  'User-Agent': this.client.state.appUserAgent,
191
- 'X-Ads-Opt-Out': this.client.state.adsOptOut ? '1' : '0',
192
- 'X-IG-App-Locale': this.client.state.language,
193
- 'X-IG-Device-Locale': this.client.state.language,
189
+ 'X-Ads-Opt-Out': '0', // Always 0 for humans
190
+ 'X-IG-App-Locale': 'en_US',
191
+ 'X-IG-Device-Locale': 'en_US',
194
192
  'X-Pigeon-Session-Id': this.client.state.pigeonSessionId,
195
193
  'X-Pigeon-Rawclienttime': (Date.now() / 1000).toFixed(3),
196
- 'X-IG-Connection-Speed': `${random(1000, 3700)}kbps`,
194
+ 'X-IG-Connection-Speed': `${random(2000, 4000)}kbps`, // Faster 5G/WiFi speeds
197
195
  'X-IG-Bandwidth-Speed-KBPS': '-1.000',
198
196
  'X-IG-Bandwidth-TotalBytes-B': '0',
199
197
  'X-IG-Bandwidth-TotalTime-MS': '0',
200
198
  'X-IG-Extended-CDN-Thumbnail-Cache-Busting-Value': this.client.state.thumbnailCacheBustingValue.toString(),
201
199
  'X-Bloks-Version-Id': this.client.state.bloksVersionId,
202
200
  'X-IG-WWW-Claim': this.client.state.igWWWClaim || '0',
203
- 'X-Bloks-Is-Layout-RTL': this.client.state.isLayoutRTL.toString(),
204
- 'X-IG-Connection-Type': this.client.state.connectionTypeHeader,
205
- 'X-IG-Capabilities': this.client.state.capabilitiesHeader,
206
- 'X-IG-App-ID': this.client.state.fbAnalyticsApplicationId,
201
+ 'X-Bloks-Is-Layout-RTL': 'false',
202
+ 'X-IG-Connection-Type': 'WIFI', // Prefer WIFI for stability
203
+ 'X-IG-Capabilities': '3brTv10=', // iOS capabilities
204
+ 'X-IG-App-ID': '1217981644879628', // Official iOS App ID
207
205
  'X-IG-Device-ID': this.client.state.uuid,
208
206
  'X-IG-Android-ID': this.client.state.deviceId,
209
- 'Accept-Language': this.client.state.language.replace('_', '-'),
207
+ 'Accept-Language': 'en-US',
210
208
  'X-FB-HTTP-Engine': 'Liger',
211
- 'X-FB-Client-IP': 'True',
212
- 'X-FB-Server-Cluster': 'True',
213
- 'X-IG-Nav-Chain': 'MainFeed:FeedTimelineFragment:1',
214
209
  'Authorization': this.client.state.authorization,
215
210
  'Host': 'i.instagram.com',
216
211
  'Accept-Encoding': 'gzip, deflate',
@@ -21,10 +21,8 @@ class State {
21
21
  this.language = 'en_US';
22
22
  this.timezoneOffset = String(new Date().getTimezoneOffset() * -60);
23
23
  this.radioType = 'wifi-none';
24
- this.capabilitiesHeader = '3brTvw==';
24
+ this.capabilitiesHeader = '3brTv10=';
25
25
  this.connectionTypeHeader = 'WIFI';
26
- this.clientCapabilities = 6143;
27
- this.endpointCapabilities = 255;
28
26
  this.isLayoutRTL = false;
29
27
  this.adsOptOut = false;
30
28
  this.thumbnailCacheBustingValue = 1000;
@@ -36,14 +34,12 @@ class State {
36
34
  this.parsedAuthorization = undefined;
37
35
 
38
36
  // ===== PLATFORM SUPPORT (iOS + Android) =====
39
- this.platform = 'android'; // 'android' or 'ios'
40
- this.androidVersion = '15';
41
- this.androidApiLevel = '35';
37
+ this.platform = 'ios'; // 'android' or 'ios'
42
38
  this.iosVersion = '18.1';
43
- this.iosAppVersion = '411.0.0';
44
- this.iosAppVersionCode = '700123456';
39
+ this.iosAppVersion = '347.0.0.36.89';
40
+ this.iosAppVersionCode = '618023787';
45
41
  this.iosDeviceModel = 'iPhone17,1'; // iPhone 16 Pro Max
46
- this.iosDeviceName = 'iPhone';
42
+ this.iosDeviceName = 'iPhone 16 Pro Max';
47
43
  this.iosBundleId = 'com.burbn.instagram';
48
44
 
49
45
  // cookie jar (tough-cookie)
@@ -105,7 +101,8 @@ class State {
105
101
  }
106
102
 
107
103
  get iosUserAgent() {
108
- return `Instagram ${this.iosAppVersion} (${this.iosDeviceModel}; iOS ${this.iosVersion}; ${this.language}; ${this.language}; scale=3.00; ${this.iosResolution}; ${this.iosAppVersionCode}) AppleWebKit/420+`;
104
+ // iPhone 16 Pro Max Hardcoded User Agent for Maximum Stealth
105
+ return `Instagram 347.0.0.36.89 (iPhone17,1; iOS 18.1; en_US; en_US; scale=3.00; 1320x2868; 618023787) AppleWebKit/420+`;
109
106
  }
110
107
 
111
108
  get iosResolution() {
@@ -25,11 +25,16 @@ class MQTToTClient extends mqtts_1.MqttClient {
25
25
  proxyOptions: options.socksOptions,
26
26
  additionalOptions: {
27
27
  ...options.additionalOptions,
28
- ciphers: 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256',
28
+ // Anti-Bot: Enforce TLS 1.3 with Unified Cipher Suites (iOS & Android 14/15)
29
29
  minVersion: 'TLSv1.3',
30
30
  maxVersion: 'TLSv1.3',
31
- honorCipherOrder: true,
32
- ALPNProtocols: ['h2', 'mqtt']
31
+ ciphers: [
32
+ 'TLS_AES_128_GCM_SHA256',
33
+ 'TLS_AES_256_GCM_SHA384',
34
+ 'TLS_CHACHA20_POLY1305_SHA256'
35
+ ].join(':'),
36
+ sigalgs: 'ecdsa_secp256r1_sha256:rsa_pss_rsae_sha256:rsa_pkcs1_sha256:ecdsa_secp384r1_sha384:rsa_pss_rsae_sha384:rsa_pkcs1_sha384:rsa_pss_rsae_sha512:rsa_pkcs1_sha512',
37
+ rejectUnauthorized: true,
33
38
  },
34
39
  })
35
40
  : new mqtts_1.TlsTransport({
@@ -37,11 +42,16 @@ class MQTToTClient extends mqtts_1.MqttClient {
37
42
  port: 443,
38
43
  additionalOptions: {
39
44
  ...options.additionalOptions,
40
- ciphers: 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256',
45
+ // Anti-Bot: Enforce TLS 1.3 with Unified Cipher Suites (iOS & Android 14/15)
41
46
  minVersion: 'TLSv1.3',
42
47
  maxVersion: 'TLSv1.3',
43
- honorCipherOrder: true,
44
- ALPNProtocols: ['h2', 'mqtt']
48
+ ciphers: [
49
+ 'TLS_AES_128_GCM_SHA256',
50
+ 'TLS_AES_256_GCM_SHA384',
51
+ 'TLS_CHACHA20_POLY1305_SHA256'
52
+ ].join(':'),
53
+ sigalgs: 'ecdsa_secp256r1_sha256:rsa_pss_rsae_sha256:rsa_pkcs1_sha256:ecdsa_secp384r1_sha384:rsa_pss_rsae_sha384:rsa_pkcs1_sha384:rsa_pss_rsae_sha512:rsa_pkcs1_sha512',
54
+ rejectUnauthorized: true,
45
55
  },
46
56
  }),
47
57
  });
@@ -79,12 +89,17 @@ class MQTToTClient extends mqtts_1.MqttClient {
79
89
  * @param {MqttMessage} message
80
90
  * @returns {Promise<MqttMessageOutgoing>}
81
91
  */
82
- async mqttotPublish(message) {
92
+ mqttotPublish(message) {
83
93
  this.mqttotDebug(`Publishing ${message.payload.byteLength}bytes to topic ${message.topic}`);
84
- return await this.publish({
85
- topic: message.topic,
86
- payload: await (0, shared_1.compressDeflate)(message.payload),
87
- qosLevel: message.qosLevel,
94
+ // Anti-bot: Jitter publishing timestamp slightly to mimic organic network latency
95
+ return new Promise(resolve => {
96
+ setTimeout(async () => {
97
+ resolve(await this.publish({
98
+ topic: message.topic,
99
+ payload: await (0, shared_1.compressDeflate)(message.payload),
100
+ qosLevel: message.qosLevel,
101
+ }));
102
+ }, Math.random() * 50 + 10); // 10-60ms random jitter
88
103
  });
89
104
  }
90
105
  /**
@@ -114,7 +129,7 @@ function mqttotConnectFlow(payload, requirePayload) {
114
129
  type: mqtts_1.PacketType.Connect,
115
130
  options: {
116
131
  payload,
117
- keepAlive: 120,
132
+ keepAlive: 900, // Increased to 15 minutes (900s) to match mobile app behavior for battery saving
118
133
  },
119
134
  }),
120
135
  accept: mqtts_1.isConnAck,
@@ -7,20 +7,7 @@ class MQTToTConnection {
7
7
  this.fbnsConnectionData = connectionData;
8
8
  }
9
9
  toThrift() {
10
- // Fix: Ensure clientInfo exists and populate it
11
- if (!this.fbnsConnectionData.clientInfo) {
12
- this.fbnsConnectionData.clientInfo = {};
13
- }
14
- this.fbnsConnectionData.clientInfo.clientCapabilities = this.fbnsConnectionData.clientInfo.clientCapabilities || this.fbnsConnectionData.clientCapabilities || 6143;
15
- this.fbnsConnectionData.clientInfo.endpointCapabilities = this.fbnsConnectionData.clientInfo.endpointCapabilities || this.fbnsConnectionData.endpointCapabilities || 255;
16
-
17
- // Fix: Remove root-level properties that don't have descriptors in the root thriftConfig
18
- // to avoid "Descriptor for ... not found" errors
19
- const dataToWrite = Object.assign({}, this.fbnsConnectionData);
20
- delete dataToWrite.clientCapabilities;
21
- delete dataToWrite.endpointCapabilities;
22
-
23
- return (0, thrift_1.thriftWriteFromObject)(dataToWrite, MQTToTConnection.thriftConfig);
10
+ return (0, thrift_1.thriftWriteFromObject)(this.fbnsConnectionData, MQTToTConnection.thriftConfig);
24
11
  }
25
12
  toString() {
26
13
  return this.toThrift().toString();
@@ -60,10 +47,14 @@ MQTToTConnection.thriftConfig = [
60
47
  thrift_1.ThriftDescriptors.int64('anotherUnknown', 26),
61
48
  ]),
62
49
  thrift_1.ThriftDescriptors.binary('password', 5),
63
- // polyfill
50
+ // polyfill - Anti-Bot Hardening (Order matters for mobile mimicry)
64
51
  thrift_1.ThriftDescriptors.int16('unknown', 5),
65
52
  thrift_1.ThriftDescriptors.listOfBinary('getDiffsRequests', 6),
66
53
  thrift_1.ThriftDescriptors.binary('zeroRatingTokenHash', 9),
67
54
  thrift_1.ThriftDescriptors.mapBinaryBinary('appSpecificInfo', 10),
55
+ // Field 11 is "chat_on" state for presence - often missing in bots
56
+ thrift_1.ThriftDescriptors.boolean('chatOn', 11),
57
+ // Field 12 is "fg_keepalive" - foreground keepalive flag
58
+ thrift_1.ThriftDescriptors.boolean('fgKeepAlive', 12),
68
59
  ];
69
60
  //# sourceMappingURL=mqttot.connection.js.map
@@ -230,31 +230,37 @@ class RealtimeClient extends eventemitter3_1.EventEmitter {
230
230
  this.realtimeDebug(`SessionID generated (fallback): ${sessionid}`);
231
231
  }
232
232
  const password = `sessionid=${sessionid}`;
233
+
234
+ // MQTT Client Info - Unified Mobile Profile (iOS & Android)
233
235
  this.connection = new mqttot_1.MQTToTConnection({
234
236
  clientIdentifier: deviceId.substring(0, 20),
235
237
  clientInfo: {
236
238
  userId: BigInt(Number(this.ig.state.cookieUserId)),
237
239
  userAgent,
238
- clientCapabilities: 183,
240
+ clientCapabilities: this.ig.state.platform === 'ios' ? 195 : 183, // Platform-specific capabilities
239
241
  endpointCapabilities: 0,
240
242
  publishFormat: 1,
241
243
  noAutomaticForeground: false,
242
244
  makeUserAvailableInForeground: true,
243
245
  deviceId,
244
246
  isInitiallyForeground: true,
245
- networkType: 1,
247
+ networkType: 1, // WIFI
246
248
  networkSubtype: 0,
247
249
  clientMqttSessionId: BigInt(Date.now()) & BigInt(0xffffffff),
248
- subscribeTopics: [88, 135, 149, 150, 133, 146],
250
+ subscribeTopics: this.ig.state.platform === 'ios'
251
+ ? [88, 135, 149, 150, 133, 146, 230, 231]
252
+ : [88, 135, 149, 150, 133, 146], // Android usually has fewer default subscriptions
249
253
  clientType: 'cookie_auth',
250
- appId: BigInt(567067343352427),
254
+ appId: this.ig.state.platform === 'ios'
255
+ ? BigInt(1217981644879628)
256
+ : BigInt(1217981644879628), // Same for both on mobile
251
257
  deviceSecret: '',
252
258
  clientStack: 3,
253
259
  ...(this.initOptions?.connectOverrides || {}),
254
260
  },
255
261
  password,
256
262
  appSpecificInfo: {
257
- app_version: this.ig.state.appVersion,
263
+ app_version: this.ig.state.platform === 'ios' ? '347.0.0.36.89' : this.ig.state.appVersion,
258
264
  'X-IG-Capabilities': this.ig.state.capabilitiesHeader,
259
265
  everclear_subscriptions: JSON.stringify({
260
266
  inapp_notification_subscribe_comment: '17899377895239777',
@@ -263,7 +269,7 @@ class RealtimeClient extends eventemitter3_1.EventEmitter {
263
269
  presence_subscribe: '17846944882223835',
264
270
  }),
265
271
  'User-Agent': userAgent,
266
- 'Accept-Language': this.ig.state.language.replace('_', '-'),
272
+ 'Accept-Language': this.ig.state.language,
267
273
  },
268
274
  });
269
275
  }
@@ -21,10 +21,10 @@ function createFbnsUserAgent(ig) {
21
21
  FBBD: 'Android',
22
22
  FBPN: 'com.instagram.android',
23
23
  FBDV: deviceName.trim(),
24
- FBSV: ig.state.androidVersion,
24
+ FBSV: androidVersion.split('/')[1],
25
25
  FBLR: '0',
26
26
  FBBK: '1',
27
- FBCA: 'arm64-v8a:armeabi-v7a:armeabi',
27
+ FBCA: 'x86:armeabi-v7a',
28
28
  };
29
29
  return `[${Object.entries(params)
30
30
  .map(p => p.join('/'))
@@ -32,7 +32,7 @@ function createFbnsUserAgent(ig) {
32
32
  }
33
33
  exports.createFbnsUserAgent = createFbnsUserAgent;
34
34
  function compressDeflate(data) {
35
- return deflatePromise(data, { level: 6, windowBits: -15 });
35
+ return deflatePromise(data, { level: 9 });
36
36
  }
37
37
  exports.compressDeflate = compressDeflate;
38
38
  function unzipAsync(data) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodejs-insta-private-api-mqtt",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Complete Instagram MQTT protocol with FULL iOS + Android support. 33 device presets (21 iOS + 12 Android). iPhone 16/15/14/13/12, iPad Pro, Samsung, Pixel, Huawei. Real-time DM messaging, view-once media extraction, sub-500ms latency.",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {