nodejs-insta-private-api-mqt 1.3.88 → 1.3.89

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.
@@ -586,6 +586,462 @@ class AccountRepository extends Repository {
586
586
  }
587
587
  }
588
588
 
589
+ /**
590
+ * Step 1: launcher/mobileconfig to fetch mobile config + encryption keys.
591
+ * Best effort – errors are ignored.
592
+ */
593
+ async _launcherMobileConfig(preLogin = true) {
594
+ const nowSec = Math.floor(Date.now() / 1000);
595
+ const state = this.client.state || {};
596
+
597
+ const androidDeviceId =
598
+ state.androidDeviceId ||
599
+ state.deviceId ||
600
+ `android-${crypto.randomBytes(8).toString('hex')}`;
601
+
602
+ const familyDeviceId =
603
+ state.phoneId ||
604
+ state.familyDeviceId ||
605
+ (crypto.randomUUID
606
+ ? crypto.randomUUID()
607
+ : require('uuid').v4());
608
+
609
+ const qeDeviceId =
610
+ state.deviceId ||
611
+ state.qeDeviceId ||
612
+ (crypto.randomUUID
613
+ ? crypto.randomUUID()
614
+ : require('uuid').v4());
615
+
616
+ const deviceUUID = state.uuid || qeDeviceId;
617
+ const userId = state.cookieUserId || '0';
618
+
619
+ const bloksVersionId =
620
+ state.bloksVersionId ||
621
+ '5e47baf35c5a270b44c8906c8b99063564b30ef69779f3dee0b828bee2e4ef5b';
622
+
623
+ const lang = state.language || 'ro_RO';
624
+ const acceptLanguage = `${lang.replace('_', '-')}, en-US`;
625
+ const userAgent = this._resolveUserAgent();
626
+
627
+ const timezoneOffset =
628
+ typeof state.timezoneOffset === 'number'
629
+ ? state.timezoneOffset
630
+ : 7200;
631
+
632
+ const params = {
633
+ bool_opt_policy: '0',
634
+ mobileconfig: '',
635
+ api_version: '9',
636
+ client_context: '["opt,value_hash"]',
637
+ unit_type: '2',
638
+ use_case: 'STANDARD',
639
+ query_hash:
640
+ 'f00b9d0869db3969378d8d06bfccb24b5ef078012c8e199cba961cd5dfedaa88',
641
+ ts: String(nowSec),
642
+ _uid: userId,
643
+ device_id: deviceUUID,
644
+ _uuid: deviceUUID,
645
+ fetch_mode: 'CONFIG_SYNC_ONLY',
646
+ fetch_type: 'ASYNC_FULL',
647
+ };
648
+
649
+ const headers = {
650
+ 'accept-language': acceptLanguage,
651
+ 'content-type':
652
+ 'application/x-www-form-urlencoded; charset=UTF-8',
653
+ priority: 'u=3',
654
+
655
+ 'x-bloks-is-layout-rtl': 'false',
656
+ 'x-bloks-prism-ax-base-colors-enabled': 'false',
657
+ 'x-bloks-prism-button-version': 'CONTROL',
658
+ 'x-bloks-prism-colors-enabled': 'true',
659
+ 'x-bloks-prism-font-enabled': 'false',
660
+ 'x-bloks-prism-indigo-link-version': '0',
661
+ 'x-bloks-version-id': bloksVersionId,
662
+
663
+ 'x-fb-client-ip': 'True',
664
+ 'x-fb-connection-type': 'WIFI',
665
+ 'x-fb-server-cluster': 'True',
666
+ 'x-fb-network-properties':
667
+ 'VPN;Validated;LocalAddrs=/10.0.0.2,;',
668
+ 'x-fb-http-engine': 'MNS/TCP',
669
+ 'x-fb-rmd': 'state=URL_ELIGIBLE',
670
+
671
+ 'x-ig-android-id': androidDeviceId,
672
+ 'x-ig-app-id': String(
673
+ state.fbAnalyticsApplicationId || '567067343352427'
674
+ ),
675
+ 'x-ig-app-locale': lang,
676
+ 'x-ig-bandwidth-speed-kbps': (
677
+ Math.random() * 1500 +
678
+ 800
679
+ ).toFixed(3),
680
+ 'x-ig-bandwidth-totalbytes-b': '0',
681
+ 'x-ig-bandwidth-totaltime-ms': '0',
682
+ 'x-ig-client-endpoint':
683
+ 'LockoutFragment:dogfooding_lockout',
684
+ 'x-ig-capabilities': '3brTv10=',
685
+ 'x-ig-connection-type': 'WIFI',
686
+ 'x-ig-device-id': deviceUUID,
687
+ 'x-ig-device-languages': '{"system_languages":"ro-RO"}',
688
+ 'x-ig-device-locale': lang,
689
+ 'x-ig-family-device-id': familyDeviceId,
690
+ 'x-ig-mapped-locale': lang,
691
+ 'x-ig-nav-chain':
692
+ 'LockoutFragment:dogfooding_lockout:1:cold_start',
693
+ 'x-ig-salt-ids':
694
+ '220140399,332020310,974466465,974460658',
695
+ 'x-ig-timezone-offset': String(timezoneOffset),
696
+ 'x-ig-www-claim': state.igWWWClaim || '0',
697
+ 'x-mid':
698
+ state.mid ||
699
+ state.machineId ||
700
+ `aZ${crypto.randomBytes(8).toString('hex')}`,
701
+ 'x-pigeon-rawclienttime': `${nowSec}.${Math.floor(
702
+ Math.random() * 1000
703
+ )
704
+ .toString()
705
+ .padStart(3, '0')}`,
706
+ 'x-pigeon-session-id':
707
+ state.pigeonSessionId ||
708
+ `UFS-${crypto.randomBytes(16).toString('hex')}-M`,
709
+ 'x-tigon-is-retry': 'False',
710
+
711
+ 'accept-encoding': 'gzip, deflate, br',
712
+ 'user-agent': userAgent,
713
+ };
714
+
715
+ if (state.cookieUserId) {
716
+ headers['ig-intended-user-id'] = String(state.cookieUserId);
717
+ headers['ig-u-ds-user-id'] = String(state.cookieUserId);
718
+ }
719
+ if (state.igURur) {
720
+ headers['ig-u-rur'] = state.igURur;
721
+ }
722
+ if (state.authorization) {
723
+ headers['authorization'] = state.authorization;
724
+ }
725
+
726
+ try {
727
+ const response = await this.client.request.send({
728
+ method: 'POST',
729
+ url: '/api/v1/launcher/mobileconfig/',
730
+ form: this.client.request.sign(params),
731
+ headers,
732
+ });
733
+
734
+ try {
735
+ const fs = require('fs');
736
+ const path = require('path');
737
+ const debugDir = path.join(
738
+ process.cwd(),
739
+ 'authinfo_instagram'
740
+ );
741
+ const debugFile = path.join(
742
+ debugDir,
743
+ 'launcher-mobileconfig-debug.json'
744
+ );
745
+ try {
746
+ fs.mkdirSync(debugDir, { recursive: true });
747
+ } catch (e) {}
748
+ const debugPayload = {
749
+ at: new Date().toISOString(),
750
+ statusCode:
751
+ response.statusCode || response.status || null,
752
+ headers: response.headers || null,
753
+ body: response.body || null,
754
+ };
755
+ fs.writeFileSync(
756
+ debugFile,
757
+ JSON.stringify(debugPayload, null, 2),
758
+ 'utf8'
759
+ );
760
+ } catch (e) {}
761
+
762
+ return response.body;
763
+ } catch (e) {
764
+ return null;
765
+ }
766
+ }
767
+
768
+ /**
769
+ * Step 2: Android Keystore attestation – moves x-ig-attest-params
770
+ * payload to dedicated endpoint /api/v1/attestation/create_android_keystore/.
771
+ */
772
+ async _createAndroidKeystoreAttestation() {
773
+ const state = this.client.state || {};
774
+ const nowSec = Math.floor(Date.now() / 1000);
775
+
776
+ const androidDeviceId =
777
+ state.androidDeviceId ||
778
+ state.deviceId ||
779
+ `android-${crypto.randomBytes(8).toString('hex')}`;
780
+
781
+ const familyDeviceId =
782
+ state.phoneId ||
783
+ state.familyDeviceId ||
784
+ (crypto.randomUUID
785
+ ? crypto.randomUUID()
786
+ : require('uuid').v4());
787
+
788
+ const qeDeviceId =
789
+ state.deviceId ||
790
+ state.qeDeviceId ||
791
+ (crypto.randomUUID
792
+ ? crypto.randomUUID()
793
+ : require('uuid').v4());
794
+
795
+ const deviceUUID = state.uuid || qeDeviceId;
796
+ const userId = state.cookieUserId || '0';
797
+
798
+ const attestParams =
799
+ AccountRepository.generateAttestParams(state);
800
+
801
+ const lang = state.language || 'ro_RO';
802
+ const acceptLanguage = `${lang.replace('_', '-')}, en-US`;
803
+ const userAgent = this._resolveUserAgent();
804
+ const timezoneOffset =
805
+ typeof state.timezoneOffset === 'number'
806
+ ? state.timezoneOffset
807
+ : 7200;
808
+
809
+ const params = {
810
+ _uid: userId,
811
+ _uuid: deviceUUID,
812
+ device_id: androidDeviceId,
813
+ family_device_id: familyDeviceId,
814
+ ts: String(nowSec),
815
+ ...attestParams,
816
+ };
817
+
818
+ const headers = {
819
+ 'accept-language': acceptLanguage,
820
+ 'content-type':
821
+ 'application/x-www-form-urlencoded; charset=UTF-8',
822
+ priority: 'u=3',
823
+
824
+ 'x-ig-android-id': androidDeviceId,
825
+ 'x-ig-device-id': qeDeviceId,
826
+ 'x-ig-family-device-id': familyDeviceId,
827
+ 'x-ig-timezone-offset': String(timezoneOffset),
828
+ 'x-ig-app-id': String(
829
+ state.fbAnalyticsApplicationId || '567067343352427'
830
+ ),
831
+ 'x-ig-app-locale': lang,
832
+ 'x-ig-device-locale': lang,
833
+ 'x-ig-mapped-locale': lang,
834
+ 'x-ig-connection-type': 'WIFI',
835
+ 'x-ig-capabilities': '3brTv10=',
836
+ 'x-ig-www-claim': state.igWWWClaim || '0',
837
+
838
+ 'x-pigeon-rawclienttime': `${nowSec}.${Math.floor(
839
+ Math.random() * 1000
840
+ )
841
+ .toString()
842
+ .padStart(3, '0')}`,
843
+ 'x-pigeon-session-id':
844
+ state.pigeonSessionId ||
845
+ `UFS-${crypto.randomBytes(16).toString('hex')}-A`,
846
+ 'x-mid':
847
+ state.mid ||
848
+ state.machineId ||
849
+ `aZ${crypto.randomBytes(8).toString('hex')}`,
850
+
851
+ 'x-fb-client-ip': 'True',
852
+ 'x-fb-connection-type': 'WIFI',
853
+ 'x-fb-server-cluster': 'True',
854
+ 'x-fb-http-engine': 'MNS/TCP',
855
+ 'x-fb-network-properties':
856
+ 'VPN;Validated;LocalAddrs=/10.0.0.2,;',
857
+ 'x-fb-rmd': 'state=URL_ELIGIBLE',
858
+
859
+ 'accept-encoding': 'gzip, deflate, br',
860
+ 'user-agent': userAgent,
861
+ };
862
+
863
+ if (state.cookieUserId) {
864
+ headers['ig-intended-user-id'] = String(state.cookieUserId);
865
+ }
866
+ if (state.authorization) {
867
+ headers['authorization'] = state.authorization;
868
+ }
869
+ if (state.igURur) {
870
+ headers['ig-u-rur'] = state.igURur;
871
+ }
872
+
873
+ try {
874
+ const response = await this.client.request.send({
875
+ method: 'POST',
876
+ url: '/api/v1/attestation/create_android_keystore/',
877
+ form: this.client.request.sign(params),
878
+ headers,
879
+ });
880
+
881
+ try {
882
+ const fs = require('fs');
883
+ const path = require('path');
884
+ const debugDir = path.join(
885
+ process.cwd(),
886
+ 'authinfo_instagram'
887
+ );
888
+ const debugFile = path.join(
889
+ debugDir,
890
+ 'attestation-debug.json'
891
+ );
892
+ try {
893
+ fs.mkdirSync(debugDir, { recursive: true });
894
+ } catch (e) {}
895
+ const debugPayload = {
896
+ at: new Date().toISOString(),
897
+ statusCode:
898
+ response.statusCode || response.status || null,
899
+ headers: response.headers || null,
900
+ body: response.body || null,
901
+ };
902
+ fs.writeFileSync(
903
+ debugFile,
904
+ JSON.stringify(debugPayload, null, 2),
905
+ 'utf8'
906
+ );
907
+ } catch (e) {}
908
+
909
+ return response.body;
910
+ } catch (e) {
911
+ return null;
912
+ }
913
+ }
914
+
915
+ /**
916
+ * Step 3 & 4 & 5 helpers: Terms of service preload, process client data,
917
+ * and (optional) phone number prefill.
918
+ * These are best-effort calls; failures are ignored.
919
+ */
920
+ async _preloadTermsOfService() {
921
+ const state = this.client.state || {};
922
+ const lang = state.language || 'ro_RO';
923
+ const acceptLanguage = `${lang.replace('_', '-')}, en-US`;
924
+ const userAgent = this._resolveUserAgent();
925
+ const bloksVersionId =
926
+ state.bloksVersionId ||
927
+ '5e47baf35c5a270b44c8906c8b99063564b30ef69779f3dee0b828bee2e4ef5b';
928
+
929
+ const paramsJson = JSON.stringify({});
930
+ const bkClientContext = JSON.stringify({
931
+ bloks_version: bloksVersionId,
932
+ styles_id: 'instagram',
933
+ });
934
+
935
+ const headers = {
936
+ 'accept-language': acceptLanguage,
937
+ 'content-type':
938
+ 'application/x-www-form-urlencoded; charset=UTF-8',
939
+ priority: 'u=3',
940
+ 'x-bloks-version-id': bloksVersionId,
941
+ 'user-agent': userAgent,
942
+ };
943
+
944
+ try {
945
+ const response = await this.client.request.send({
946
+ method: 'POST',
947
+ url: '/api/v1/bloks/apps/com.bloks.www.caa.login.oxygen_preloads_terms_of_service/',
948
+ form: {
949
+ params: paramsJson,
950
+ bk_client_context: bkClientContext,
951
+ bloks_versioning_id: bloksVersionId,
952
+ },
953
+ headers,
954
+ });
955
+ return response.body;
956
+ } catch (e) {
957
+ return null;
958
+ }
959
+ }
960
+
961
+ async _processClientDataAndRedirect(username) {
962
+ const state = this.client.state || {};
963
+ const lang = state.language || 'ro_RO';
964
+ const acceptLanguage = `${lang.replace('_', '-')}, en-US`;
965
+ const userAgent = this._resolveUserAgent();
966
+ const bloksVersionId =
967
+ state.bloksVersionId ||
968
+ '5e47baf35c5a270b44c8906c8b99063564b30ef69779f3dee0b828bee2e4ef5b';
969
+
970
+ const paramsJson = JSON.stringify({
971
+ username_input: username || '',
972
+ });
973
+ const bkClientContext = JSON.stringify({
974
+ bloks_version: bloksVersionId,
975
+ styles_id: 'instagram',
976
+ });
977
+
978
+ const headers = {
979
+ 'accept-language': acceptLanguage,
980
+ 'content-type':
981
+ 'application/x-www-form-urlencoded; charset=UTF-8',
982
+ priority: 'u=3',
983
+ 'x-bloks-version-id': bloksVersionId,
984
+ 'user-agent': userAgent,
985
+ };
986
+
987
+ try {
988
+ const response = await this.client.request.send({
989
+ method: 'POST',
990
+ url: '/api/v1/bloks/async_action/com.bloks.www.bloks.caa.login.process_client_data_and_redirect/',
991
+ form: {
992
+ params: paramsJson,
993
+ bk_client_context: bkClientContext,
994
+ bloks_versioning_id: bloksVersionId,
995
+ },
996
+ headers,
997
+ });
998
+ return response.body;
999
+ } catch (e) {
1000
+ return null;
1001
+ }
1002
+ }
1003
+
1004
+ async _phoneNumberPrefill() {
1005
+ const state = this.client.state || {};
1006
+ const lang = state.language || 'ro_RO';
1007
+ const acceptLanguage = `${lang.replace('_', '-')}, en-US`;
1008
+ const userAgent = this._resolveUserAgent();
1009
+ const bloksVersionId =
1010
+ state.bloksVersionId ||
1011
+ '5e47baf35c5a270b44c8906c8b99063564b30ef69779f3dee0b828bee2e4ef5b';
1012
+
1013
+ const paramsJson = JSON.stringify({});
1014
+ const bkClientContext = JSON.stringify({
1015
+ bloks_version: bloksVersionId,
1016
+ styles_id: 'instagram',
1017
+ });
1018
+
1019
+ const headers = {
1020
+ 'accept-language': acceptLanguage,
1021
+ 'content-type':
1022
+ 'application/x-www-form-urlencoded; charset=UTF-8',
1023
+ priority: 'u=3',
1024
+ 'x-bloks-version-id': bloksVersionId,
1025
+ 'user-agent': userAgent,
1026
+ };
1027
+
1028
+ try {
1029
+ const response = await this.client.request.send({
1030
+ method: 'POST',
1031
+ url: '/api/v1/bloks/async_action/com.bloks.www.bloks.caa.phone.number.prefill.async.controller/',
1032
+ form: {
1033
+ params: paramsJson,
1034
+ bk_client_context: bkClientContext,
1035
+ bloks_versioning_id: bloksVersionId,
1036
+ },
1037
+ headers,
1038
+ });
1039
+ return response.body;
1040
+ } catch (e) {
1041
+ return null;
1042
+ }
1043
+ }
1044
+
589
1045
  async login(credentialsOrUsername, passwordArg) {
590
1046
  let username, password;
591
1047
  if (
@@ -611,10 +1067,29 @@ class AccountRepository extends Repository {
611
1067
 
612
1068
  await this.ensureCsrfToken();
613
1069
 
1070
+ // Step 1–5: mobileconfig, keystore attestation, TOS preload, process client data, phone prefill
1071
+ try {
1072
+ await this._launcherMobileConfig(true);
1073
+ } catch (e) {}
1074
+ try {
1075
+ await this._createAndroidKeystoreAttestation();
1076
+ } catch (e) {}
1077
+ try {
1078
+ await this._preloadTermsOfService();
1079
+ } catch (e) {}
1080
+ try {
1081
+ await this._processClientDataAndRedirect(username);
1082
+ } catch (e) {}
1083
+ try {
1084
+ await this._phoneNumberPrefill();
1085
+ } catch (e) {}
1086
+
1087
+ // Step 6: OAuth token fetch
614
1088
  try {
615
1089
  await this._prefetchOauthTokenForLogin(username);
616
1090
  } catch (e) {}
617
1091
 
1092
+ // Step 7: real login
618
1093
  return this.requestWithRetry(async () => {
619
1094
  const nowSec = Math.floor(Date.now() / 1000);
620
1095
  const aacInitTimestamp =
@@ -754,10 +1229,6 @@ class AccountRepository extends Repository {
754
1229
  server_params: serverParams,
755
1230
  });
756
1231
 
757
- const attestParams =
758
- AccountRepository.generateAttestParams(
759
- this.client.state
760
- );
761
1232
  const bloksVersionId =
762
1233
  this.client.state.bloksVersionId ||
763
1234
  '5e47baf35c5a270b44c8906c8b99063564b30ef69779f3dee0b828bee2e4ef5b';
@@ -812,7 +1283,6 @@ class AccountRepository extends Repository {
812
1283
  '567067343352427'
813
1284
  ),
814
1285
  'x-ig-app-locale': lang,
815
- 'x-ig-attest-params': JSON.stringify(attestParams),
816
1286
  'x-ig-bandwidth-speed-kbps': (
817
1287
  Math.random() * 1500 +
818
1288
  800
@@ -1827,6 +2297,4 @@ class AccountRepository extends Repository {
1827
2297
  return response.body;
1828
2298
  });
1829
2299
  }
1830
- }
1831
-
1832
- module.exports = AccountRepository;
2300
+ }module.exports = AccountRepository;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodejs-insta-private-api-mqt",
3
- "version": "1.3.88",
3
+ "version": "1.3.89",
4
4
  "description": "Complete Instagram MQTT protocol with full-featured REALTIME and REST API — all in one project.",
5
5
 
6
6
  "main": "dist/dist/index.js",