@tiktool/live 2.4.5 → 2.4.7

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.mts CHANGED
@@ -203,6 +203,17 @@ interface TikTokLiveOptions {
203
203
  heartbeatInterval?: number;
204
204
  debug?: boolean;
205
205
  webSocketImpl?: any;
206
+ /**
207
+ * TikTok browser session ID cookie for authenticated connections.
208
+ * Enables ranklist API access and authenticated WebSocket features.
209
+ * Obtain from the user's tiktok.com browser cookies.
210
+ */
211
+ sessionId?: string;
212
+ /**
213
+ * TikTok target IDC region (e.g. 'useast5').
214
+ * Required when sessionId is provided — must match the account's region.
215
+ */
216
+ ttTargetIdc?: string;
206
217
  }
207
218
  interface RanklistUser {
208
219
  /** TikTok user ID */
@@ -356,12 +367,23 @@ declare class TikTokLive extends EventEmitter {
356
367
  private readonly maxReconnectAttempts;
357
368
  private readonly heartbeatInterval;
358
369
  private readonly debug;
370
+ private _sessionId?;
371
+ private _ttTargetIdc?;
359
372
  constructor(options: TikTokLiveOptions);
360
373
  connect(): Promise<void>;
361
374
  disconnect(): void;
362
375
  get connected(): boolean;
363
376
  get eventCount(): number;
364
377
  get roomId(): string;
378
+ /** Get the stored session ID (if any) */
379
+ get sessionId(): string | undefined;
380
+ /** Update the session ID at runtime (e.g. after TikTok login) */
381
+ setSession(sessionId: string, ttTargetIdc?: string): void;
382
+ /**
383
+ * Build a cookie header string for authenticated API requests (e.g. ranklist).
384
+ * Returns undefined if no session is set.
385
+ */
386
+ buildSessionCookieHeader(): string | undefined;
365
387
  on<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
366
388
  once<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
367
389
  off<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
@@ -405,8 +427,10 @@ interface GetRanklistOptions {
405
427
  /**
406
428
  * Fetch ranked user lists from TikTok via the sign server.
407
429
  *
408
- * Requires `sessionCookie` for authentication without it, TikTok
409
- * returns status 20003 ("Please login first").
430
+ * When `sessionCookie` is provided, the server returns a **sign-and-return**
431
+ * response with a signed URL that you must fetch from your own IP
432
+ * (TikTok sessions are IP-bound). Check for `sign_and_return: true` in
433
+ * the response to detect this mode.
410
434
  *
411
435
  * @example
412
436
  * ```ts
@@ -416,7 +440,19 @@ interface GetRanklistOptions {
416
440
  * sessionCookie: 'sessionid=abc; sid_guard=def',
417
441
  * type: 'online_audience',
418
442
  * });
419
- * console.log(data.data.ranks); // top gifters
443
+ *
444
+ * if (data.sign_and_return) {
445
+ * // Fetch the signed URL from YOUR IP with your session cookie
446
+ * const resp = await fetch(data.signed_url, {
447
+ * method: data.method,
448
+ * headers: { ...data.headers, Cookie: sessionCookie },
449
+ * ...(data.body ? { body: data.body } : {}),
450
+ * });
451
+ * const tikData = await resp.json();
452
+ * console.log(tikData); // TikTok's raw response
453
+ * } else {
454
+ * console.log(data); // Direct TikTok response (no session)
455
+ * }
420
456
  * ```
421
457
  */
422
458
  declare function getRanklist(opts: GetRanklistOptions): Promise<RanklistResponse>;
@@ -448,6 +484,18 @@ interface GetRegionalRanklistOptions {
448
484
  type?: 'list' | 'entrance';
449
485
  /** Gap interval filter (default: "0") */
450
486
  gapInterval?: string;
487
+ /**
488
+ * TikTok session cookie string for authentication.
489
+ * Passed to the API server for proxied requests.
490
+ * Example: "sessionid=abc123; sessionid_ss=abc123"
491
+ */
492
+ sessionCookie?: string;
493
+ /**
494
+ * Client's real IP address (for deployed server scenarios).
495
+ * When running on a remote server, pass the end-user's IP so the
496
+ * API server can proxy the TikTok request from the correct IP.
497
+ */
498
+ clientIp?: string;
451
499
  }
452
500
  interface RegionalRanklistSignedResponse {
453
501
  /** Always 0 on success */
package/dist/index.d.ts CHANGED
@@ -203,6 +203,17 @@ interface TikTokLiveOptions {
203
203
  heartbeatInterval?: number;
204
204
  debug?: boolean;
205
205
  webSocketImpl?: any;
206
+ /**
207
+ * TikTok browser session ID cookie for authenticated connections.
208
+ * Enables ranklist API access and authenticated WebSocket features.
209
+ * Obtain from the user's tiktok.com browser cookies.
210
+ */
211
+ sessionId?: string;
212
+ /**
213
+ * TikTok target IDC region (e.g. 'useast5').
214
+ * Required when sessionId is provided — must match the account's region.
215
+ */
216
+ ttTargetIdc?: string;
206
217
  }
207
218
  interface RanklistUser {
208
219
  /** TikTok user ID */
@@ -356,12 +367,23 @@ declare class TikTokLive extends EventEmitter {
356
367
  private readonly maxReconnectAttempts;
357
368
  private readonly heartbeatInterval;
358
369
  private readonly debug;
370
+ private _sessionId?;
371
+ private _ttTargetIdc?;
359
372
  constructor(options: TikTokLiveOptions);
360
373
  connect(): Promise<void>;
361
374
  disconnect(): void;
362
375
  get connected(): boolean;
363
376
  get eventCount(): number;
364
377
  get roomId(): string;
378
+ /** Get the stored session ID (if any) */
379
+ get sessionId(): string | undefined;
380
+ /** Update the session ID at runtime (e.g. after TikTok login) */
381
+ setSession(sessionId: string, ttTargetIdc?: string): void;
382
+ /**
383
+ * Build a cookie header string for authenticated API requests (e.g. ranklist).
384
+ * Returns undefined if no session is set.
385
+ */
386
+ buildSessionCookieHeader(): string | undefined;
365
387
  on<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
366
388
  once<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
367
389
  off<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
@@ -405,8 +427,10 @@ interface GetRanklistOptions {
405
427
  /**
406
428
  * Fetch ranked user lists from TikTok via the sign server.
407
429
  *
408
- * Requires `sessionCookie` for authentication without it, TikTok
409
- * returns status 20003 ("Please login first").
430
+ * When `sessionCookie` is provided, the server returns a **sign-and-return**
431
+ * response with a signed URL that you must fetch from your own IP
432
+ * (TikTok sessions are IP-bound). Check for `sign_and_return: true` in
433
+ * the response to detect this mode.
410
434
  *
411
435
  * @example
412
436
  * ```ts
@@ -416,7 +440,19 @@ interface GetRanklistOptions {
416
440
  * sessionCookie: 'sessionid=abc; sid_guard=def',
417
441
  * type: 'online_audience',
418
442
  * });
419
- * console.log(data.data.ranks); // top gifters
443
+ *
444
+ * if (data.sign_and_return) {
445
+ * // Fetch the signed URL from YOUR IP with your session cookie
446
+ * const resp = await fetch(data.signed_url, {
447
+ * method: data.method,
448
+ * headers: { ...data.headers, Cookie: sessionCookie },
449
+ * ...(data.body ? { body: data.body } : {}),
450
+ * });
451
+ * const tikData = await resp.json();
452
+ * console.log(tikData); // TikTok's raw response
453
+ * } else {
454
+ * console.log(data); // Direct TikTok response (no session)
455
+ * }
420
456
  * ```
421
457
  */
422
458
  declare function getRanklist(opts: GetRanklistOptions): Promise<RanklistResponse>;
@@ -448,6 +484,18 @@ interface GetRegionalRanklistOptions {
448
484
  type?: 'list' | 'entrance';
449
485
  /** Gap interval filter (default: "0") */
450
486
  gapInterval?: string;
487
+ /**
488
+ * TikTok session cookie string for authentication.
489
+ * Passed to the API server for proxied requests.
490
+ * Example: "sessionid=abc123; sessionid_ss=abc123"
491
+ */
492
+ sessionCookie?: string;
493
+ /**
494
+ * Client's real IP address (for deployed server scenarios).
495
+ * When running on a remote server, pass the end-user's IP so the
496
+ * API server can proxy the TikTok request from the correct IP.
497
+ */
498
+ clientIp?: string;
451
499
  }
452
500
  interface RegionalRanklistSignedResponse {
453
501
  /** Always 0 on success */
package/dist/index.js CHANGED
@@ -863,6 +863,8 @@ var TikTokLive = class extends import_events.EventEmitter {
863
863
  maxReconnectAttempts;
864
864
  heartbeatInterval;
865
865
  debug;
866
+ _sessionId;
867
+ _ttTargetIdc;
866
868
  constructor(options) {
867
869
  super();
868
870
  this.uniqueId = options.uniqueId.replace(/^@/, "");
@@ -873,6 +875,8 @@ var TikTokLive = class extends import_events.EventEmitter {
873
875
  this.maxReconnectAttempts = options.maxReconnectAttempts ?? 5;
874
876
  this.heartbeatInterval = options.heartbeatInterval ?? 1e4;
875
877
  this.debug = options.debug ?? false;
878
+ this._sessionId = options.sessionId;
879
+ this._ttTargetIdc = options.ttTargetIdc;
876
880
  }
877
881
  async connect() {
878
882
  this.intentionalClose = false;
@@ -965,10 +969,17 @@ var TikTokLive = class extends import_events.EventEmitter {
965
969
  wsUrl = rawWsUrl.replace(/^https:\/\//, "wss://");
966
970
  }
967
971
  return new Promise((resolve, reject) => {
972
+ let cookieHeader = `ttwid=${ttwid}`;
973
+ if (this._sessionId) {
974
+ cookieHeader += `; sessionid=${this._sessionId}; sessionid_ss=${this._sessionId}; sid_tt=${this._sessionId}`;
975
+ if (this._ttTargetIdc) {
976
+ cookieHeader += `; tt-target-idc=${this._ttTargetIdc}`;
977
+ }
978
+ }
968
979
  this.ws = new import_ws.default(wsUrl, {
969
980
  headers: {
970
981
  "User-Agent": DEFAULT_UA,
971
- "Cookie": `ttwid=${ttwid}`,
982
+ "Cookie": cookieHeader,
972
983
  "Origin": "https://www.tiktok.com"
973
984
  }
974
985
  });
@@ -1027,6 +1038,29 @@ var TikTokLive = class extends import_events.EventEmitter {
1027
1038
  get roomId() {
1028
1039
  return this._roomId;
1029
1040
  }
1041
+ /** Get the stored session ID (if any) */
1042
+ get sessionId() {
1043
+ return this._sessionId;
1044
+ }
1045
+ /** Update the session ID at runtime (e.g. after TikTok login) */
1046
+ setSession(sessionId, ttTargetIdc) {
1047
+ this._sessionId = sessionId;
1048
+ if (ttTargetIdc) this._ttTargetIdc = ttTargetIdc;
1049
+ }
1050
+ /**
1051
+ * Build a cookie header string for authenticated API requests (e.g. ranklist).
1052
+ * Returns undefined if no session is set.
1053
+ */
1054
+ buildSessionCookieHeader() {
1055
+ if (!this._sessionId) return void 0;
1056
+ const parts = [
1057
+ `sessionid=${this._sessionId}`,
1058
+ `sessionid_ss=${this._sessionId}`,
1059
+ `sid_tt=${this._sessionId}`
1060
+ ];
1061
+ if (this._ttTargetIdc) parts.push(`tt-target-idc=${this._ttTargetIdc}`);
1062
+ return parts.join("; ");
1063
+ }
1030
1064
  on(event, listener) {
1031
1065
  return super.on(event, listener);
1032
1066
  }
@@ -1110,6 +1144,9 @@ async function getRanklist(opts) {
1110
1144
  if (data.status_code !== 0) {
1111
1145
  throw new Error(data.error || `Ranklist failed (status ${data.status_code})`);
1112
1146
  }
1147
+ if (data.sign_and_return) {
1148
+ return data;
1149
+ }
1113
1150
  return data.data;
1114
1151
  }
1115
1152
  async function getRegionalRanklist(opts) {
@@ -1122,6 +1159,8 @@ async function getRegionalRanklist(opts) {
1122
1159
  if (opts.rankType) body.rank_type = opts.rankType;
1123
1160
  if (opts.type) body.type = opts.type;
1124
1161
  if (opts.gapInterval) body.gap_interval = opts.gapInterval;
1162
+ if (opts.sessionCookie) body.session_cookie = opts.sessionCookie;
1163
+ if (opts.clientIp) body.client_ip = opts.clientIp;
1125
1164
  const resp = await fetch(`${base}/webcast/ranklist/regional?apiKey=${ak}`, {
1126
1165
  method: "POST",
1127
1166
  headers: { "Content-Type": "application/json" },