advanced-tls-client 3.0.2 → 3.0.3

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.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { EventEmitter } from 'events';
1
2
  import { Readable, PassThrough } from 'stream';
2
3
  interface TLSFingerprint {
3
4
  cipherSuites: number[];
@@ -119,13 +120,36 @@ interface RequestOptions {
119
120
  content_type?: string;
120
121
  uri_modifier?: Function;
121
122
  }
123
+ interface Response extends EventEmitter {
124
+ statusCode: number;
125
+ headers: Record<string, string | string[]>;
126
+ body: Buffer | Readable | any;
127
+ text?: string;
128
+ json?: any;
129
+ timing: {
130
+ socket: number;
131
+ lookup: number;
132
+ connect: number;
133
+ secureConnect: number;
134
+ response: number;
135
+ end: number;
136
+ total: number;
137
+ };
138
+ fingerprints: {
139
+ ja3: string;
140
+ ja3Hash: string;
141
+ akamai: string;
142
+ };
143
+ bytes?: number;
144
+ raw?: Buffer;
145
+ cookies?: Record<string, string>;
146
+ parser?: string;
147
+ }
122
148
  declare class ProfileRegistry {
123
149
  private static getGrease;
124
150
  static chromeMobile143Android(): ChromeProfile;
125
151
  static chrome133PSK(): ChromeProfile;
126
152
  static chrome133(): ChromeProfile;
127
- static firefox117(): ChromeProfile;
128
- static safariIOS18(): ChromeProfile;
129
153
  static get(name: string): ChromeProfile;
130
154
  static get latest(): ChromeProfile;
131
155
  static get latestMobile(): ChromeProfile;
@@ -140,7 +164,7 @@ declare class AdvancedTLSClient {
140
164
  private defaults;
141
165
  constructor(profileName?: string);
142
166
  private setup;
143
- request(uri: string, data?: any, options?: RequestOptions, callback?: Function): Promise<FullResponse | PassThrough>;
167
+ request(uri: string, data?: any, options?: RequestOptions, callback?: (err: any, res?: Response) => void): Promise<FullResponse | PassThrough>;
144
168
  private generateJA3;
145
169
  private buildMultipart;
146
170
  private generateMultipart;
package/dist/index.js CHANGED
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.ProfileRegistry = exports.AdvancedTLSClient = void 0;
37
37
  const tls = __importStar(require("tls"));
38
38
  const net = __importStar(require("net"));
39
+ const https = __importStar(require("https"));
39
40
  const http2 = __importStar(require("http2"));
40
41
  const crypto = __importStar(require("crypto"));
41
42
  const events_1 = require("events");
@@ -413,202 +414,16 @@ class ProfileRegistry {
413
414
  secFetchDest: 'document'
414
415
  };
415
416
  }
416
- static firefox117() {
417
- return {
418
- name: 'firefox_117',
419
- version: '117.0',
420
- tls: {
421
- cipherSuites: [
422
- 4865,
423
- 4867,
424
- 4866,
425
- 49195,
426
- 49199,
427
- 52393,
428
- 52392,
429
- 49196,
430
- 49200,
431
- 159,
432
- 158,
433
- 49161,
434
- 49162,
435
- 156,
436
- 157,
437
- 47,
438
- 53
439
- ],
440
- extensions: [0, 23, 65281, 10, 11, 35, 16, 5, 34, 51, 43, 13, 45, 28, 21],
441
- supportedGroups: [
442
- 29,
443
- 23,
444
- 24,
445
- 25,
446
- 256,
447
- 257
448
- ],
449
- signatureAlgorithms: [
450
- 1027,
451
- 1283,
452
- 1539,
453
- 2052,
454
- 2053,
455
- 2054,
456
- 1025,
457
- 1281,
458
- 1537,
459
- 513,
460
- 515
461
- ],
462
- supportedVersions: [
463
- 772,
464
- 771
465
- ],
466
- ecPointFormats: [0],
467
- alpnProtocols: ['h2', 'http/1.1'],
468
- pskKeyExchangeModes: [1],
469
- compressionMethods: [0],
470
- grease: false
471
- },
472
- http2: {
473
- windowUpdate: 12517377,
474
- headerTableSize: 65536,
475
- enablePush: 0,
476
- initialWindowSize: 131072,
477
- maxFrameSize: 16384,
478
- settingsOrder: [1, 4, 5],
479
- connectionPreface: Buffer.from('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'),
480
- priorityFrames: [
481
- { streamId: 3, weight: 200, dependency: 0, exclusive: false },
482
- { streamId: 5, weight: 100, dependency: 0, exclusive: false },
483
- { streamId: 7, weight: 0, dependency: 0, exclusive: false },
484
- { streamId: 9, weight: 0, dependency: 7, exclusive: false },
485
- { streamId: 11, weight: 0, dependency: 3, exclusive: false },
486
- { streamId: 13, weight: 240, dependency: 0, exclusive: false }
487
- ],
488
- pseudoHeaderOrder: [':method', ':path', ':authority', ':scheme'],
489
- headerPriority: { streamDep: 13, exclusive: false, weight: 41 },
490
- headerOrder: []
491
- },
492
- userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:117.0) Gecko/20100101 Firefox/117.0',
493
- secChUa: '',
494
- secChUaPlatform: '',
495
- secChUaMobile: '',
496
- secFetchSite: 'none',
497
- secFetchMode: 'navigate',
498
- secFetchDest: 'document'
499
- };
500
- }
501
- static safariIOS18() {
502
- const grease1 = this.getGrease();
503
- const grease2 = this.getGrease();
504
- return {
505
- name: 'safari_ios_18_0',
506
- version: '18.0',
507
- tls: {
508
- cipherSuites: [
509
- grease1,
510
- 4865,
511
- 4866,
512
- 4867,
513
- 49196,
514
- 49195,
515
- 52393,
516
- 49200,
517
- 49199,
518
- 52392,
519
- 159,
520
- 158,
521
- 49162,
522
- 49161,
523
- 157,
524
- 156,
525
- 53,
526
- 47,
527
- 49188,
528
- 49187,
529
- 60
530
- ],
531
- extensions: [
532
- grease2,
533
- 0,
534
- 23,
535
- 65281,
536
- 10,
537
- 11,
538
- 16,
539
- 5,
540
- 13,
541
- 18,
542
- 51,
543
- 45,
544
- 43,
545
- 21
546
- ],
547
- supportedGroups: [
548
- 29,
549
- 23,
550
- 24,
551
- 25
552
- ],
553
- signatureAlgorithms: [
554
- 1027,
555
- 2052,
556
- 1025,
557
- 1283,
558
- 513,
559
- 2053,
560
- 2053,
561
- 1281,
562
- 2054,
563
- 1537,
564
- 515
565
- ],
566
- supportedVersions: [
567
- 772,
568
- 771,
569
- 770,
570
- 769
571
- ],
572
- ecPointFormats: [0],
573
- alpnProtocols: ['h2', 'http/1.1'],
574
- pskKeyExchangeModes: [1],
575
- compressionMethods: [0],
576
- grease: true
577
- },
578
- http2: {
579
- windowUpdate: 10420225,
580
- headerTableSize: 4096,
581
- enablePush: 0,
582
- maxConcurrentStreams: 100,
583
- initialWindowSize: 2097152,
584
- maxFrameSize: 16384,
585
- settingsOrder: [2, 3, 4, 8, 9],
586
- connectionPreface: Buffer.from('PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'),
587
- priorityFrames: [],
588
- pseudoHeaderOrder: [':method', ':scheme', ':authority', ':path'],
589
- headerOrder: []
590
- },
591
- userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1',
592
- secChUa: '',
593
- secChUaPlatform: '',
594
- secChUaMobile: '?1',
595
- secFetchSite: 'none',
596
- secFetchMode: 'navigate',
597
- secFetchDest: 'document'
598
- };
599
- }
600
417
  static get(name) {
601
418
  switch (name.toLowerCase()) {
602
419
  case 'chrome_mobile_143_android': return this.chromeMobile143Android();
603
420
  case 'chrome_133_psk': return this.chrome133PSK();
604
421
  case 'chrome_133': return this.chrome133();
605
- case 'firefox_117': return this.firefox117();
606
- case 'safari_ios_18_0': return this.safariIOS18();
607
- default: return this.chrome133();
422
+ default: return this.chromeMobile143Android();
608
423
  }
609
424
  }
610
425
  static get latest() {
611
- return this.chrome133();
426
+ return this.chromeMobile143Android();
612
427
  }
613
428
  static get latestMobile() {
614
429
  return this.chromeMobile143Android();
@@ -747,11 +562,12 @@ class UnifiedClientManager extends events_1.EventEmitter {
747
562
  }
748
563
  }
749
564
  async requestHttp2(path, options, timingStart, headers, post_data, out, callback) {
565
+ const normalizedPath = path.startsWith('/') ? path : `/${path}`;
750
566
  const reqHeaders = {
751
567
  ':method': options.method?.toUpperCase() || 'GET',
752
568
  ':authority': this.hostname,
753
569
  ':scheme': 'https',
754
- ':path': path,
570
+ ':path': normalizedPath,
755
571
  ...headers
756
572
  };
757
573
  const stream = this.http2Client.request(reqHeaders);
@@ -765,6 +581,7 @@ class UnifiedClientManager extends events_1.EventEmitter {
765
581
  const chunks = [];
766
582
  const rawChunks = [];
767
583
  let finished = false;
584
+ let hasHeaders = false;
768
585
  const finish = async (error) => {
769
586
  if (finished)
770
587
  return;
@@ -805,10 +622,9 @@ class UnifiedClientManager extends events_1.EventEmitter {
805
622
  response.timing.total = response.timing.end;
806
623
  if (!out.writableEnded && !out.destroyed)
807
624
  out.end();
808
- if (callback)
809
- setImmediate(() => callback(null, response, response.body));
810
625
  };
811
626
  stream.once('response', (hdrs) => {
627
+ hasHeaders = true;
812
628
  response.statusCode = hdrs[':status'];
813
629
  response.headers = hdrs;
814
630
  if (hdrs['set-cookie'])
@@ -816,6 +632,8 @@ class UnifiedClientManager extends events_1.EventEmitter {
816
632
  response.timing.response = Date.now() - timingStart;
817
633
  out.emit('header', response.statusCode, hdrs);
818
634
  out.emit('headers', hdrs);
635
+ if (callback)
636
+ setImmediate(() => callback(null, response));
819
637
  });
820
638
  stream.on('data', (chunk) => {
821
639
  if (finished || out.destroyed || out.writableEnded)
@@ -868,7 +686,7 @@ class UnifiedClientManager extends events_1.EventEmitter {
868
686
  headers: { host: this.hostname, ...headers },
869
687
  createConnection: () => this.tlsSocket
870
688
  };
871
- const req = require('https').request(reqOptions);
689
+ const req = https.request(reqOptions);
872
690
  const response = new events_1.EventEmitter();
873
691
  response.timing = { socket: timingStart, lookup: 0, connect: 0, secureConnect: 0, response: 0, end: 0, total: 0 };
874
692
  response.fingerprints = {
@@ -879,6 +697,7 @@ class UnifiedClientManager extends events_1.EventEmitter {
879
697
  const chunks = [];
880
698
  const rawChunks = [];
881
699
  let finished = false;
700
+ let hasHeaders = false;
882
701
  const finish = async (error, res) => {
883
702
  if (finished)
884
703
  return;
@@ -921,10 +740,9 @@ class UnifiedClientManager extends events_1.EventEmitter {
921
740
  response.timing.total = response.timing.end;
922
741
  if (!out.writableEnded && !out.destroyed)
923
742
  out.end();
924
- if (callback)
925
- setImmediate(() => callback(null, response, response.body));
926
743
  };
927
744
  req.once('response', (res) => {
745
+ hasHeaders = true;
928
746
  response.statusCode = res.statusCode;
929
747
  response.headers = res.headers;
930
748
  if (res.headers['set-cookie'])
@@ -932,6 +750,8 @@ class UnifiedClientManager extends events_1.EventEmitter {
932
750
  response.timing.response = Date.now() - timingStart;
933
751
  out.emit('header', response.statusCode, res.headers);
934
752
  out.emit('headers', res.headers);
753
+ if (callback)
754
+ setImmediate(() => callback(null, response));
935
755
  res.on('data', (chunk) => {
936
756
  if (finished || out.destroyed || out.writableEnded)
937
757
  return;
@@ -1133,7 +953,7 @@ class AdvancedTLSClient {
1133
953
  follow_if_same_location: false,
1134
954
  use_proxy_from_env_var: true
1135
955
  };
1136
- this.profile = ProfileRegistry.get(profileName || 'chrome_133');
956
+ this.profile = ProfileRegistry.get(profileName || 'chrome_mobile_143_android');
1137
957
  this.cleanupInterval = setInterval(() => {
1138
958
  const now = Date.now();
1139
959
  for (const [key, session] of this.sessionCache) {
@@ -1147,7 +967,7 @@ class AdvancedTLSClient {
1147
967
  }
1148
968
  setup(uri, options) {
1149
969
  const config = {
1150
- headers: { ...options.headers },
970
+ headers: {},
1151
971
  proxy: options.proxy || this.defaults.proxy,
1152
972
  decompress: options.decompress !== undefined ? options.decompress : true
1153
973
  };
@@ -1165,6 +985,10 @@ class AdvancedTLSClient {
1165
985
  config.headers['upgrade-insecure-requests'] = this.profile.upgradeInsecureRequests;
1166
986
  if (this.profile.priority)
1167
987
  config.headers['priority'] = this.profile.priority;
988
+ // Override with user headers
989
+ if (options.headers) {
990
+ Object.assign(config.headers, options.headers);
991
+ }
1168
992
  return config;
1169
993
  }
1170
994
  async request(uri, data, options = {}, callback) {
@@ -1172,6 +996,9 @@ class AdvancedTLSClient {
1172
996
  callback = options;
1173
997
  options = {};
1174
998
  }
999
+ if (data && typeof data !== 'object' && !Buffer.isBuffer(data) && !(data instanceof stream_1.Readable)) {
1000
+ throw new Error('Invalid data type');
1001
+ }
1175
1002
  const parsed = new url.URL(uri);
1176
1003
  const hostname = parsed.hostname;
1177
1004
  const port = parsed.port ? +parsed.port : 443;
@@ -1197,7 +1024,10 @@ class AdvancedTLSClient {
1197
1024
  session.lastUsed = Date.now();
1198
1025
  const config = this.setup(uri, options);
1199
1026
  let post_data = null;
1200
- let json = options.json || (options.json !== false && config.headers['content-type']?.includes('application/json'));
1027
+ let json = options.json !== undefined ? options.json : false;
1028
+ if (json === undefined && config.headers['content-type']?.includes('application/json')) {
1029
+ json = true;
1030
+ }
1201
1031
  if (data) {
1202
1032
  if (options.multipart) {
1203
1033
  const boundary = options.boundary || this.defaults.boundary;
@@ -1233,10 +1063,9 @@ class AdvancedTLSClient {
1233
1063
  return out;
1234
1064
  }
1235
1065
  if (callback) {
1236
- const typedCallback = callback;
1237
- session.clientManager.request(path, options, startTime, config.headers, post_data, out, typedCallback).catch(err => {
1238
- if (typedCallback)
1239
- typedCallback(err);
1066
+ session.clientManager.request(path, options, startTime, config.headers, post_data, out, callback).catch(err => {
1067
+ if (callback)
1068
+ callback(err);
1240
1069
  });
1241
1070
  return out;
1242
1071
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "advanced-tls-client",
3
- "version": "3.0.2",
3
+ "version": "3.0.3",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {