tiktok-live-api 1.4.6 → 1.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/README.md +48 -0
- package/dist/index.d.mts +105 -1
- package/dist/index.d.ts +105 -1
- package/dist/index.js +216 -2
- package/dist/index.mjs +213 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -185,6 +185,54 @@ client.on('chat', (e) => console.log(e.comment));
|
|
|
185
185
|
client.connect();
|
|
186
186
|
```
|
|
187
187
|
|
|
188
|
+
## REST API - leaderboards, recruiting, profiles, gifts
|
|
189
|
+
|
|
190
|
+
The WebSocket client streams live events. For everything else - leaderboards,
|
|
191
|
+
gaming ranks, recruiting, live status, gift catalogs, profiles - use the
|
|
192
|
+
`TikTool` REST client. One method per endpoint, fully promise-based.
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { TikTool } from 'tiktok-live-api';
|
|
196
|
+
|
|
197
|
+
const api = new TikTool({ apiKey: 'YOUR_KEY' });
|
|
198
|
+
|
|
199
|
+
// Live status (single + bulk)
|
|
200
|
+
await api.liveStatus('charlidamelio');
|
|
201
|
+
await api.bulkLiveCheck(['user1', 'user2', 'user3']);
|
|
202
|
+
|
|
203
|
+
// Leaderboards + rankings
|
|
204
|
+
await api.leaderboard({ region: 'US+' });
|
|
205
|
+
await api.ranklistGaming('US+');
|
|
206
|
+
await api.regionMovers('US+'); // entered top today, below cutoff now
|
|
207
|
+
|
|
208
|
+
// Recruiting (Global Agency) - find eligible creators
|
|
209
|
+
await api.eligibleCreators({ region: 'US+', limit: 50, min_score: 1000 });
|
|
210
|
+
|
|
211
|
+
// Profiles + gifts
|
|
212
|
+
await api.profileInfo('khaby.lame');
|
|
213
|
+
await api.userProfile('khaby.lame');
|
|
214
|
+
await api.giftsByCountry('US');
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Tier gating is enforced server-side: a call above your tier throws a
|
|
218
|
+
`TikToolError` with `status === 403`. Any endpoint not yet wrapped is reachable
|
|
219
|
+
via `api.request('/webcast/...', { query })`.
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import { TikTool, TikToolError } from 'tiktok-live-api';
|
|
223
|
+
try {
|
|
224
|
+
await api.eligibleCreators({ region: 'US+' });
|
|
225
|
+
} catch (e) {
|
|
226
|
+
if (e instanceof TikToolError && e.status === 403) {
|
|
227
|
+
console.log('Upgrade required:', e.message);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Method groups: signing/connection, live status, rankings/leaderboards, gifts,
|
|
233
|
+
user/profile, content/feed, live analytics, moderation, CAPTCHA solver, captions.
|
|
234
|
+
See [the full endpoint + tier matrix](https://tik.tools/docs).
|
|
235
|
+
|
|
188
236
|
## Events (54 v3 event types)
|
|
189
237
|
|
|
190
238
|
Every event is dispatched by name. `client.on('chat', e => ...)` is fully typed end-to-end. Each event payload extends `BaseEvent` (`type`, `timestamp`, `msgId`, optional `protoVersion: 1 | 2 | 3`).
|
package/dist/index.d.mts
CHANGED
|
@@ -326,6 +326,110 @@ declare class TikTokLive {
|
|
|
326
326
|
private _maybeReconnect;
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
/**
|
|
330
|
+
* TikTool REST client - typed methods for every customer-facing tik.tools
|
|
331
|
+
* REST endpoint. Pairs with the {@link TikTokLive} WebSocket client.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```typescript
|
|
335
|
+
* import { TikTool } from 'tiktok-live-api';
|
|
336
|
+
*
|
|
337
|
+
* const api = new TikTool({ apiKey: 'YOUR_KEY' });
|
|
338
|
+
*
|
|
339
|
+
* const live = await api.isLive('username');
|
|
340
|
+
* const board = await api.leaderboard({ region: 'US+' });
|
|
341
|
+
* const recruits = await api.eligibleCreators({ region: 'US+', limit: 50 });
|
|
342
|
+
* ```
|
|
343
|
+
*
|
|
344
|
+
* Uses the global `fetch` (Node 18+ or any browser).
|
|
345
|
+
*/
|
|
346
|
+
interface TikToolOptions {
|
|
347
|
+
apiKey: string;
|
|
348
|
+
/** Override the API base URL. Defaults to https://api.tik.tools */
|
|
349
|
+
baseUrl?: string;
|
|
350
|
+
}
|
|
351
|
+
/** Thrown when an endpoint returns a non-2xx status. `body` holds the parsed error payload. */
|
|
352
|
+
declare class TikToolError extends Error {
|
|
353
|
+
readonly status: number;
|
|
354
|
+
readonly body: unknown;
|
|
355
|
+
constructor(status: number, body: unknown);
|
|
356
|
+
}
|
|
357
|
+
type Query = Record<string, string | number | boolean | undefined | null>;
|
|
358
|
+
interface RequestOpts {
|
|
359
|
+
method?: 'GET' | 'POST';
|
|
360
|
+
query?: Query;
|
|
361
|
+
body?: unknown;
|
|
362
|
+
}
|
|
363
|
+
declare class TikTool {
|
|
364
|
+
private readonly apiKey;
|
|
365
|
+
private readonly baseUrl;
|
|
366
|
+
constructor(options: TikToolOptions);
|
|
367
|
+
/** Low-level request. Use the named methods below; this is exposed for endpoints not yet wrapped. */
|
|
368
|
+
request<T = any>(path: string, opts?: RequestOpts): Promise<T>;
|
|
369
|
+
/**
|
|
370
|
+
* Creator-identifier query params. The API is inconsistent about whether an
|
|
371
|
+
* endpoint reads `unique_id`, `username`, or `uniqueId`, so we send all three;
|
|
372
|
+
* unused ones are ignored server-side.
|
|
373
|
+
*/
|
|
374
|
+
private uid;
|
|
375
|
+
signUrl(url: string): Promise<any>;
|
|
376
|
+
signWebsocket(body: Record<string, unknown>): Promise<any>;
|
|
377
|
+
wsCredentials(uniqueId: string): Promise<any>;
|
|
378
|
+
connectionMode(uniqueId: string): Promise<any>;
|
|
379
|
+
checkAlive(uniqueId: string): Promise<any>;
|
|
380
|
+
rateLimits(): Promise<any>;
|
|
381
|
+
wsSessions(): Promise<any>;
|
|
382
|
+
jwt(body?: Record<string, unknown>): Promise<any>;
|
|
383
|
+
isLive(uniqueId: string): Promise<any>;
|
|
384
|
+
liveStatus(uniqueId: string): Promise<any>;
|
|
385
|
+
bulkLiveCheck(usernames: string[]): Promise<any>;
|
|
386
|
+
liveCounts(region?: string): Promise<any>;
|
|
387
|
+
roomId(uniqueId: string): Promise<any>;
|
|
388
|
+
roomInfo(uniqueId: string): Promise<any>;
|
|
389
|
+
roomCover(uniqueId: string): Promise<any>;
|
|
390
|
+
roomVideo(uniqueId: string): Promise<any>;
|
|
391
|
+
rankings(query?: Query): Promise<any>;
|
|
392
|
+
ranklist(query?: Query): Promise<any>;
|
|
393
|
+
ranklistRegional(region: string): Promise<any>;
|
|
394
|
+
ranklistGaming(region: string): Promise<any>;
|
|
395
|
+
gamingMovers(region: string): Promise<any>;
|
|
396
|
+
regionMovers(region: string): Promise<any>;
|
|
397
|
+
leaderboard(query: {
|
|
398
|
+
region: string;
|
|
399
|
+
} & Query): Promise<any>;
|
|
400
|
+
eligibleCreators(query: {
|
|
401
|
+
region?: string;
|
|
402
|
+
page?: number;
|
|
403
|
+
limit?: number;
|
|
404
|
+
min_score?: number;
|
|
405
|
+
} & Query): Promise<any>;
|
|
406
|
+
giftInfo(query?: Query): Promise<any>;
|
|
407
|
+
giftGallery(query?: Query): Promise<any>;
|
|
408
|
+
giftsByCountry(country: string): Promise<any>;
|
|
409
|
+
lookupUsername(uniqueId: string): Promise<any>;
|
|
410
|
+
profileInfo(uniqueId: string): Promise<any>;
|
|
411
|
+
resolveUserIds(usernames: string[]): Promise<any>;
|
|
412
|
+
userProfile(uniqueId: string): Promise<any>;
|
|
413
|
+
userVideos(uniqueId: string, query?: Query): Promise<any>;
|
|
414
|
+
userFollowers(uniqueId: string, query?: Query): Promise<any>;
|
|
415
|
+
userFollowing(uniqueId: string, query?: Query): Promise<any>;
|
|
416
|
+
userLikes(uniqueId: string, query?: Query): Promise<any>;
|
|
417
|
+
userEarnings(uniqueId: string): Promise<any>;
|
|
418
|
+
hashtagList(query?: Query): Promise<any>;
|
|
419
|
+
fetch(body: Record<string, unknown>): Promise<any>;
|
|
420
|
+
feed(query?: Query): Promise<any>;
|
|
421
|
+
chat(uniqueId: string, query?: Query): Promise<any>;
|
|
422
|
+
analyticsVideoList(query?: Query): Promise<any>;
|
|
423
|
+
analyticsVideoDetail(query?: Query): Promise<any>;
|
|
424
|
+
analyticsUserInteractions(query?: Query): Promise<any>;
|
|
425
|
+
moderationMutes(uniqueId: string): Promise<any>;
|
|
426
|
+
moderationBans(uniqueId: string): Promise<any>;
|
|
427
|
+
solvePuzzle(body: Record<string, unknown>): Promise<any>;
|
|
428
|
+
solveRotate(body: Record<string, unknown>): Promise<any>;
|
|
429
|
+
solveShapes(body: Record<string, unknown>): Promise<any>;
|
|
430
|
+
captionsCredits(): Promise<any>;
|
|
431
|
+
}
|
|
432
|
+
|
|
329
433
|
/**
|
|
330
434
|
* TikTokCaptions - Real-time AI speech-to-text for TikTok LIVE streams.
|
|
331
435
|
*
|
|
@@ -431,4 +535,4 @@ declare class TikTokCaptions {
|
|
|
431
535
|
disconnect(): void;
|
|
432
536
|
}
|
|
433
537
|
|
|
434
|
-
export { type BattleEvent, type CaptionEvent, type ChatEvent, type ConnectedEvent, type CreditsEvent, type DisconnectedEvent, type ErrorEvent, type GiftEvent, type LikeEvent, type MemberEvent, type RoomUserSeqEvent, type SocialEvent, TikTokCaptions, type TikTokCaptionsEventMap, type TikTokCaptionsOptions, TikTokLive, type TikTokLiveEventMap, type TikTokLiveOptions, type TikTokUser, type TranslationEvent };
|
|
538
|
+
export { type BattleEvent, type CaptionEvent, type ChatEvent, type ConnectedEvent, type CreditsEvent, type DisconnectedEvent, type ErrorEvent, type GiftEvent, type LikeEvent, type MemberEvent, type RoomUserSeqEvent, type SocialEvent, TikTokCaptions, type TikTokCaptionsEventMap, type TikTokCaptionsOptions, TikTokLive, type TikTokLiveEventMap, type TikTokLiveOptions, type TikTokUser, TikTool, TikToolError, type TikToolOptions, type TranslationEvent };
|
package/dist/index.d.ts
CHANGED
|
@@ -326,6 +326,110 @@ declare class TikTokLive {
|
|
|
326
326
|
private _maybeReconnect;
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
/**
|
|
330
|
+
* TikTool REST client - typed methods for every customer-facing tik.tools
|
|
331
|
+
* REST endpoint. Pairs with the {@link TikTokLive} WebSocket client.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```typescript
|
|
335
|
+
* import { TikTool } from 'tiktok-live-api';
|
|
336
|
+
*
|
|
337
|
+
* const api = new TikTool({ apiKey: 'YOUR_KEY' });
|
|
338
|
+
*
|
|
339
|
+
* const live = await api.isLive('username');
|
|
340
|
+
* const board = await api.leaderboard({ region: 'US+' });
|
|
341
|
+
* const recruits = await api.eligibleCreators({ region: 'US+', limit: 50 });
|
|
342
|
+
* ```
|
|
343
|
+
*
|
|
344
|
+
* Uses the global `fetch` (Node 18+ or any browser).
|
|
345
|
+
*/
|
|
346
|
+
interface TikToolOptions {
|
|
347
|
+
apiKey: string;
|
|
348
|
+
/** Override the API base URL. Defaults to https://api.tik.tools */
|
|
349
|
+
baseUrl?: string;
|
|
350
|
+
}
|
|
351
|
+
/** Thrown when an endpoint returns a non-2xx status. `body` holds the parsed error payload. */
|
|
352
|
+
declare class TikToolError extends Error {
|
|
353
|
+
readonly status: number;
|
|
354
|
+
readonly body: unknown;
|
|
355
|
+
constructor(status: number, body: unknown);
|
|
356
|
+
}
|
|
357
|
+
type Query = Record<string, string | number | boolean | undefined | null>;
|
|
358
|
+
interface RequestOpts {
|
|
359
|
+
method?: 'GET' | 'POST';
|
|
360
|
+
query?: Query;
|
|
361
|
+
body?: unknown;
|
|
362
|
+
}
|
|
363
|
+
declare class TikTool {
|
|
364
|
+
private readonly apiKey;
|
|
365
|
+
private readonly baseUrl;
|
|
366
|
+
constructor(options: TikToolOptions);
|
|
367
|
+
/** Low-level request. Use the named methods below; this is exposed for endpoints not yet wrapped. */
|
|
368
|
+
request<T = any>(path: string, opts?: RequestOpts): Promise<T>;
|
|
369
|
+
/**
|
|
370
|
+
* Creator-identifier query params. The API is inconsistent about whether an
|
|
371
|
+
* endpoint reads `unique_id`, `username`, or `uniqueId`, so we send all three;
|
|
372
|
+
* unused ones are ignored server-side.
|
|
373
|
+
*/
|
|
374
|
+
private uid;
|
|
375
|
+
signUrl(url: string): Promise<any>;
|
|
376
|
+
signWebsocket(body: Record<string, unknown>): Promise<any>;
|
|
377
|
+
wsCredentials(uniqueId: string): Promise<any>;
|
|
378
|
+
connectionMode(uniqueId: string): Promise<any>;
|
|
379
|
+
checkAlive(uniqueId: string): Promise<any>;
|
|
380
|
+
rateLimits(): Promise<any>;
|
|
381
|
+
wsSessions(): Promise<any>;
|
|
382
|
+
jwt(body?: Record<string, unknown>): Promise<any>;
|
|
383
|
+
isLive(uniqueId: string): Promise<any>;
|
|
384
|
+
liveStatus(uniqueId: string): Promise<any>;
|
|
385
|
+
bulkLiveCheck(usernames: string[]): Promise<any>;
|
|
386
|
+
liveCounts(region?: string): Promise<any>;
|
|
387
|
+
roomId(uniqueId: string): Promise<any>;
|
|
388
|
+
roomInfo(uniqueId: string): Promise<any>;
|
|
389
|
+
roomCover(uniqueId: string): Promise<any>;
|
|
390
|
+
roomVideo(uniqueId: string): Promise<any>;
|
|
391
|
+
rankings(query?: Query): Promise<any>;
|
|
392
|
+
ranklist(query?: Query): Promise<any>;
|
|
393
|
+
ranklistRegional(region: string): Promise<any>;
|
|
394
|
+
ranklistGaming(region: string): Promise<any>;
|
|
395
|
+
gamingMovers(region: string): Promise<any>;
|
|
396
|
+
regionMovers(region: string): Promise<any>;
|
|
397
|
+
leaderboard(query: {
|
|
398
|
+
region: string;
|
|
399
|
+
} & Query): Promise<any>;
|
|
400
|
+
eligibleCreators(query: {
|
|
401
|
+
region?: string;
|
|
402
|
+
page?: number;
|
|
403
|
+
limit?: number;
|
|
404
|
+
min_score?: number;
|
|
405
|
+
} & Query): Promise<any>;
|
|
406
|
+
giftInfo(query?: Query): Promise<any>;
|
|
407
|
+
giftGallery(query?: Query): Promise<any>;
|
|
408
|
+
giftsByCountry(country: string): Promise<any>;
|
|
409
|
+
lookupUsername(uniqueId: string): Promise<any>;
|
|
410
|
+
profileInfo(uniqueId: string): Promise<any>;
|
|
411
|
+
resolveUserIds(usernames: string[]): Promise<any>;
|
|
412
|
+
userProfile(uniqueId: string): Promise<any>;
|
|
413
|
+
userVideos(uniqueId: string, query?: Query): Promise<any>;
|
|
414
|
+
userFollowers(uniqueId: string, query?: Query): Promise<any>;
|
|
415
|
+
userFollowing(uniqueId: string, query?: Query): Promise<any>;
|
|
416
|
+
userLikes(uniqueId: string, query?: Query): Promise<any>;
|
|
417
|
+
userEarnings(uniqueId: string): Promise<any>;
|
|
418
|
+
hashtagList(query?: Query): Promise<any>;
|
|
419
|
+
fetch(body: Record<string, unknown>): Promise<any>;
|
|
420
|
+
feed(query?: Query): Promise<any>;
|
|
421
|
+
chat(uniqueId: string, query?: Query): Promise<any>;
|
|
422
|
+
analyticsVideoList(query?: Query): Promise<any>;
|
|
423
|
+
analyticsVideoDetail(query?: Query): Promise<any>;
|
|
424
|
+
analyticsUserInteractions(query?: Query): Promise<any>;
|
|
425
|
+
moderationMutes(uniqueId: string): Promise<any>;
|
|
426
|
+
moderationBans(uniqueId: string): Promise<any>;
|
|
427
|
+
solvePuzzle(body: Record<string, unknown>): Promise<any>;
|
|
428
|
+
solveRotate(body: Record<string, unknown>): Promise<any>;
|
|
429
|
+
solveShapes(body: Record<string, unknown>): Promise<any>;
|
|
430
|
+
captionsCredits(): Promise<any>;
|
|
431
|
+
}
|
|
432
|
+
|
|
329
433
|
/**
|
|
330
434
|
* TikTokCaptions - Real-time AI speech-to-text for TikTok LIVE streams.
|
|
331
435
|
*
|
|
@@ -431,4 +535,4 @@ declare class TikTokCaptions {
|
|
|
431
535
|
disconnect(): void;
|
|
432
536
|
}
|
|
433
537
|
|
|
434
|
-
export { type BattleEvent, type CaptionEvent, type ChatEvent, type ConnectedEvent, type CreditsEvent, type DisconnectedEvent, type ErrorEvent, type GiftEvent, type LikeEvent, type MemberEvent, type RoomUserSeqEvent, type SocialEvent, TikTokCaptions, type TikTokCaptionsEventMap, type TikTokCaptionsOptions, TikTokLive, type TikTokLiveEventMap, type TikTokLiveOptions, type TikTokUser, type TranslationEvent };
|
|
538
|
+
export { type BattleEvent, type CaptionEvent, type ChatEvent, type ConnectedEvent, type CreditsEvent, type DisconnectedEvent, type ErrorEvent, type GiftEvent, type LikeEvent, type MemberEvent, type RoomUserSeqEvent, type SocialEvent, TikTokCaptions, type TikTokCaptionsEventMap, type TikTokCaptionsOptions, TikTokLive, type TikTokLiveEventMap, type TikTokLiveOptions, type TikTokUser, TikTool, TikToolError, type TikToolOptions, type TranslationEvent };
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
TikTokCaptions: () => TikTokCaptions,
|
|
34
|
-
TikTokLive: () => TikTokLive
|
|
34
|
+
TikTokLive: () => TikTokLive,
|
|
35
|
+
TikTool: () => TikTool,
|
|
36
|
+
TikToolError: () => TikToolError
|
|
35
37
|
});
|
|
36
38
|
module.exports = __toCommonJS(index_exports);
|
|
37
39
|
|
|
@@ -177,6 +179,216 @@ var TikTokLive = class {
|
|
|
177
179
|
}
|
|
178
180
|
};
|
|
179
181
|
|
|
182
|
+
// src/rest.ts
|
|
183
|
+
var REST_BASE = "https://api.tik.tools";
|
|
184
|
+
var TikToolError = class extends Error {
|
|
185
|
+
constructor(status, body) {
|
|
186
|
+
const msg = body && typeof body === "object" && "error" in body ? String(body.error) : `Request failed with status ${status}`;
|
|
187
|
+
super(msg);
|
|
188
|
+
this.name = "TikToolError";
|
|
189
|
+
this.status = status;
|
|
190
|
+
this.body = body;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
var TikTool = class {
|
|
194
|
+
constructor(options) {
|
|
195
|
+
if (!options?.apiKey) throw new Error("TikTool requires an apiKey");
|
|
196
|
+
this.apiKey = options.apiKey;
|
|
197
|
+
this.baseUrl = (options.baseUrl ?? REST_BASE).replace(/\/$/, "");
|
|
198
|
+
}
|
|
199
|
+
/** Low-level request. Use the named methods below; this is exposed for endpoints not yet wrapped. */
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- API boundary
|
|
201
|
+
async request(path, opts = {}) {
|
|
202
|
+
const url = new URL(this.baseUrl + path);
|
|
203
|
+
if (opts.query) {
|
|
204
|
+
for (const [k, v] of Object.entries(opts.query)) {
|
|
205
|
+
if (v !== void 0 && v !== null) url.searchParams.set(k, String(v));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const headers = { "x-api-key": this.apiKey };
|
|
209
|
+
if (opts.body !== void 0) headers["content-type"] = "application/json";
|
|
210
|
+
const res = await fetch(url.toString(), {
|
|
211
|
+
method: opts.method ?? "GET",
|
|
212
|
+
headers,
|
|
213
|
+
body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
|
|
214
|
+
});
|
|
215
|
+
const text = await res.text();
|
|
216
|
+
let data;
|
|
217
|
+
try {
|
|
218
|
+
data = text ? JSON.parse(text) : null;
|
|
219
|
+
} catch {
|
|
220
|
+
data = text;
|
|
221
|
+
}
|
|
222
|
+
if (!res.ok) throw new TikToolError(res.status, data);
|
|
223
|
+
return data;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Creator-identifier query params. The API is inconsistent about whether an
|
|
227
|
+
* endpoint reads `unique_id`, `username`, or `uniqueId`, so we send all three;
|
|
228
|
+
* unused ones are ignored server-side.
|
|
229
|
+
*/
|
|
230
|
+
uid(uniqueId) {
|
|
231
|
+
return { unique_id: uniqueId, username: uniqueId, uniqueId };
|
|
232
|
+
}
|
|
233
|
+
// --- Signing / connection ---
|
|
234
|
+
signUrl(url) {
|
|
235
|
+
return this.request("/webcast/sign_url", { method: "POST", body: { url } });
|
|
236
|
+
}
|
|
237
|
+
signWebsocket(body) {
|
|
238
|
+
return this.request("/webcast/sign_websocket", { method: "POST", body });
|
|
239
|
+
}
|
|
240
|
+
wsCredentials(uniqueId) {
|
|
241
|
+
return this.request("/webcast/ws_credentials", { query: this.uid(uniqueId) });
|
|
242
|
+
}
|
|
243
|
+
connectionMode(uniqueId) {
|
|
244
|
+
return this.request("/webcast/connection_mode", { query: this.uid(uniqueId) });
|
|
245
|
+
}
|
|
246
|
+
checkAlive(uniqueId) {
|
|
247
|
+
return this.request("/webcast/check_alive", { query: this.uid(uniqueId) });
|
|
248
|
+
}
|
|
249
|
+
rateLimits() {
|
|
250
|
+
return this.request("/webcast/rate_limits");
|
|
251
|
+
}
|
|
252
|
+
wsSessions() {
|
|
253
|
+
return this.request("/webcast/ws_sessions");
|
|
254
|
+
}
|
|
255
|
+
jwt(body) {
|
|
256
|
+
return this.request("/authentication/jwt", { method: "POST", body: body ?? {} });
|
|
257
|
+
}
|
|
258
|
+
// --- Live status ---
|
|
259
|
+
isLive(uniqueId) {
|
|
260
|
+
return this.request("/webcast/is_live", { query: this.uid(uniqueId) });
|
|
261
|
+
}
|
|
262
|
+
liveStatus(uniqueId) {
|
|
263
|
+
return this.request("/webcast/live_status", { query: this.uid(uniqueId) });
|
|
264
|
+
}
|
|
265
|
+
bulkLiveCheck(usernames) {
|
|
266
|
+
return this.request("/webcast/bulk_live_check", { method: "POST", body: { usernames } });
|
|
267
|
+
}
|
|
268
|
+
liveCounts(region) {
|
|
269
|
+
return this.request("/webcast/live_counts", { query: { region } });
|
|
270
|
+
}
|
|
271
|
+
roomId(uniqueId) {
|
|
272
|
+
return this.request("/webcast/room_id", { query: this.uid(uniqueId) });
|
|
273
|
+
}
|
|
274
|
+
roomInfo(uniqueId) {
|
|
275
|
+
return this.request("/webcast/room_info", { query: this.uid(uniqueId) });
|
|
276
|
+
}
|
|
277
|
+
roomCover(uniqueId) {
|
|
278
|
+
return this.request("/webcast/room_cover", { query: this.uid(uniqueId) });
|
|
279
|
+
}
|
|
280
|
+
roomVideo(uniqueId) {
|
|
281
|
+
return this.request("/webcast/room_video", { query: this.uid(uniqueId) });
|
|
282
|
+
}
|
|
283
|
+
// --- Rankings / leaderboards ---
|
|
284
|
+
rankings(query) {
|
|
285
|
+
return this.request("/webcast/rankings", { query });
|
|
286
|
+
}
|
|
287
|
+
ranklist(query) {
|
|
288
|
+
return this.request("/webcast/ranklist", { query });
|
|
289
|
+
}
|
|
290
|
+
ranklistRegional(region) {
|
|
291
|
+
return this.request("/webcast/ranklist/regional", { query: { region } });
|
|
292
|
+
}
|
|
293
|
+
ranklistGaming(region) {
|
|
294
|
+
return this.request("/webcast/ranklist/gaming", { query: { region } });
|
|
295
|
+
}
|
|
296
|
+
gamingMovers(region) {
|
|
297
|
+
return this.request("/webcast/ranklist/gaming_movers", { query: { region } });
|
|
298
|
+
}
|
|
299
|
+
regionMovers(region) {
|
|
300
|
+
return this.request("/webcast/ranklist/region_movers", { query: { region } });
|
|
301
|
+
}
|
|
302
|
+
leaderboard(query) {
|
|
303
|
+
return this.request("/webcast/leaderboard", { query });
|
|
304
|
+
}
|
|
305
|
+
eligibleCreators(query) {
|
|
306
|
+
return this.request("/webcast/eligible_creators", { query });
|
|
307
|
+
}
|
|
308
|
+
// --- Gifts ---
|
|
309
|
+
giftInfo(query) {
|
|
310
|
+
return this.request("/webcast/gift_info", { query });
|
|
311
|
+
}
|
|
312
|
+
giftGallery(query) {
|
|
313
|
+
return this.request("/webcast/gift_gallery", { query });
|
|
314
|
+
}
|
|
315
|
+
giftsByCountry(country) {
|
|
316
|
+
return this.request("/webcast/gifts_by_country", { query: { country } });
|
|
317
|
+
}
|
|
318
|
+
// --- User / profile ---
|
|
319
|
+
lookupUsername(uniqueId) {
|
|
320
|
+
return this.request("/webcast/lookup_username", { query: this.uid(uniqueId) });
|
|
321
|
+
}
|
|
322
|
+
profileInfo(uniqueId) {
|
|
323
|
+
return this.request("/webcast/profile_info", { query: this.uid(uniqueId) });
|
|
324
|
+
}
|
|
325
|
+
resolveUserIds(usernames) {
|
|
326
|
+
return this.request("/webcast/resolve_user_ids", { method: "POST", body: { usernames } });
|
|
327
|
+
}
|
|
328
|
+
userProfile(uniqueId) {
|
|
329
|
+
return this.request("/webcast/user_profile", { query: this.uid(uniqueId) });
|
|
330
|
+
}
|
|
331
|
+
userVideos(uniqueId, query) {
|
|
332
|
+
return this.request("/webcast/user_videos", { query: { ...this.uid(uniqueId), ...query } });
|
|
333
|
+
}
|
|
334
|
+
userFollowers(uniqueId, query) {
|
|
335
|
+
return this.request("/webcast/user_followers", { query: { ...this.uid(uniqueId), ...query } });
|
|
336
|
+
}
|
|
337
|
+
userFollowing(uniqueId, query) {
|
|
338
|
+
return this.request("/webcast/user_following", { query: { ...this.uid(uniqueId), ...query } });
|
|
339
|
+
}
|
|
340
|
+
userLikes(uniqueId, query) {
|
|
341
|
+
return this.request("/webcast/user_likes", { query: { ...this.uid(uniqueId), ...query } });
|
|
342
|
+
}
|
|
343
|
+
userEarnings(uniqueId) {
|
|
344
|
+
return this.request("/webcast/user_earnings", { query: this.uid(uniqueId) });
|
|
345
|
+
}
|
|
346
|
+
// --- Content / feed ---
|
|
347
|
+
hashtagList(query) {
|
|
348
|
+
return this.request("/webcast/hashtag_list", { query });
|
|
349
|
+
}
|
|
350
|
+
fetch(body) {
|
|
351
|
+
return this.request("/webcast/fetch", { method: "POST", body });
|
|
352
|
+
}
|
|
353
|
+
feed(query) {
|
|
354
|
+
return this.request("/webcast/feed", { query });
|
|
355
|
+
}
|
|
356
|
+
chat(uniqueId, query) {
|
|
357
|
+
return this.request("/webcast/chat", { query: { ...this.uid(uniqueId), ...query } });
|
|
358
|
+
}
|
|
359
|
+
// --- Live analytics ---
|
|
360
|
+
analyticsVideoList(query) {
|
|
361
|
+
return this.request("/webcast/live_analytics/video_list", { query });
|
|
362
|
+
}
|
|
363
|
+
analyticsVideoDetail(query) {
|
|
364
|
+
return this.request("/webcast/live_analytics/video_detail", { query });
|
|
365
|
+
}
|
|
366
|
+
analyticsUserInteractions(query) {
|
|
367
|
+
return this.request("/webcast/live_analytics/user_interactions", { query });
|
|
368
|
+
}
|
|
369
|
+
// --- Moderation ---
|
|
370
|
+
moderationMutes(uniqueId) {
|
|
371
|
+
return this.request("/webcast/moderation/mutes", { query: this.uid(uniqueId) });
|
|
372
|
+
}
|
|
373
|
+
moderationBans(uniqueId) {
|
|
374
|
+
return this.request("/webcast/moderation/bans", { query: this.uid(uniqueId) });
|
|
375
|
+
}
|
|
376
|
+
// --- CAPTCHA solver (Pro+) ---
|
|
377
|
+
solvePuzzle(body) {
|
|
378
|
+
return this.request("/captcha/solve/puzzle", { method: "POST", body });
|
|
379
|
+
}
|
|
380
|
+
solveRotate(body) {
|
|
381
|
+
return this.request("/captcha/solve/rotate", { method: "POST", body });
|
|
382
|
+
}
|
|
383
|
+
solveShapes(body) {
|
|
384
|
+
return this.request("/captcha/solve/shapes", { method: "POST", body });
|
|
385
|
+
}
|
|
386
|
+
// --- Captions ---
|
|
387
|
+
captionsCredits() {
|
|
388
|
+
return this.request("/captions/credits");
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
180
392
|
// src/captions.ts
|
|
181
393
|
var import_ws2 = __toESM(require("ws"));
|
|
182
394
|
var CAPTIONS_BASE = "wss://api.tik.tools/captions";
|
|
@@ -287,5 +499,7 @@ var TikTokCaptions = class {
|
|
|
287
499
|
// Annotate the CommonJS export names for ESM import in node:
|
|
288
500
|
0 && (module.exports = {
|
|
289
501
|
TikTokCaptions,
|
|
290
|
-
TikTokLive
|
|
502
|
+
TikTokLive,
|
|
503
|
+
TikTool,
|
|
504
|
+
TikToolError
|
|
291
505
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -140,6 +140,216 @@ var TikTokLive = class {
|
|
|
140
140
|
}
|
|
141
141
|
};
|
|
142
142
|
|
|
143
|
+
// src/rest.ts
|
|
144
|
+
var REST_BASE = "https://api.tik.tools";
|
|
145
|
+
var TikToolError = class extends Error {
|
|
146
|
+
constructor(status, body) {
|
|
147
|
+
const msg = body && typeof body === "object" && "error" in body ? String(body.error) : `Request failed with status ${status}`;
|
|
148
|
+
super(msg);
|
|
149
|
+
this.name = "TikToolError";
|
|
150
|
+
this.status = status;
|
|
151
|
+
this.body = body;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
var TikTool = class {
|
|
155
|
+
constructor(options) {
|
|
156
|
+
if (!options?.apiKey) throw new Error("TikTool requires an apiKey");
|
|
157
|
+
this.apiKey = options.apiKey;
|
|
158
|
+
this.baseUrl = (options.baseUrl ?? REST_BASE).replace(/\/$/, "");
|
|
159
|
+
}
|
|
160
|
+
/** Low-level request. Use the named methods below; this is exposed for endpoints not yet wrapped. */
|
|
161
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- API boundary
|
|
162
|
+
async request(path, opts = {}) {
|
|
163
|
+
const url = new URL(this.baseUrl + path);
|
|
164
|
+
if (opts.query) {
|
|
165
|
+
for (const [k, v] of Object.entries(opts.query)) {
|
|
166
|
+
if (v !== void 0 && v !== null) url.searchParams.set(k, String(v));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const headers = { "x-api-key": this.apiKey };
|
|
170
|
+
if (opts.body !== void 0) headers["content-type"] = "application/json";
|
|
171
|
+
const res = await fetch(url.toString(), {
|
|
172
|
+
method: opts.method ?? "GET",
|
|
173
|
+
headers,
|
|
174
|
+
body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0
|
|
175
|
+
});
|
|
176
|
+
const text = await res.text();
|
|
177
|
+
let data;
|
|
178
|
+
try {
|
|
179
|
+
data = text ? JSON.parse(text) : null;
|
|
180
|
+
} catch {
|
|
181
|
+
data = text;
|
|
182
|
+
}
|
|
183
|
+
if (!res.ok) throw new TikToolError(res.status, data);
|
|
184
|
+
return data;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Creator-identifier query params. The API is inconsistent about whether an
|
|
188
|
+
* endpoint reads `unique_id`, `username`, or `uniqueId`, so we send all three;
|
|
189
|
+
* unused ones are ignored server-side.
|
|
190
|
+
*/
|
|
191
|
+
uid(uniqueId) {
|
|
192
|
+
return { unique_id: uniqueId, username: uniqueId, uniqueId };
|
|
193
|
+
}
|
|
194
|
+
// --- Signing / connection ---
|
|
195
|
+
signUrl(url) {
|
|
196
|
+
return this.request("/webcast/sign_url", { method: "POST", body: { url } });
|
|
197
|
+
}
|
|
198
|
+
signWebsocket(body) {
|
|
199
|
+
return this.request("/webcast/sign_websocket", { method: "POST", body });
|
|
200
|
+
}
|
|
201
|
+
wsCredentials(uniqueId) {
|
|
202
|
+
return this.request("/webcast/ws_credentials", { query: this.uid(uniqueId) });
|
|
203
|
+
}
|
|
204
|
+
connectionMode(uniqueId) {
|
|
205
|
+
return this.request("/webcast/connection_mode", { query: this.uid(uniqueId) });
|
|
206
|
+
}
|
|
207
|
+
checkAlive(uniqueId) {
|
|
208
|
+
return this.request("/webcast/check_alive", { query: this.uid(uniqueId) });
|
|
209
|
+
}
|
|
210
|
+
rateLimits() {
|
|
211
|
+
return this.request("/webcast/rate_limits");
|
|
212
|
+
}
|
|
213
|
+
wsSessions() {
|
|
214
|
+
return this.request("/webcast/ws_sessions");
|
|
215
|
+
}
|
|
216
|
+
jwt(body) {
|
|
217
|
+
return this.request("/authentication/jwt", { method: "POST", body: body ?? {} });
|
|
218
|
+
}
|
|
219
|
+
// --- Live status ---
|
|
220
|
+
isLive(uniqueId) {
|
|
221
|
+
return this.request("/webcast/is_live", { query: this.uid(uniqueId) });
|
|
222
|
+
}
|
|
223
|
+
liveStatus(uniqueId) {
|
|
224
|
+
return this.request("/webcast/live_status", { query: this.uid(uniqueId) });
|
|
225
|
+
}
|
|
226
|
+
bulkLiveCheck(usernames) {
|
|
227
|
+
return this.request("/webcast/bulk_live_check", { method: "POST", body: { usernames } });
|
|
228
|
+
}
|
|
229
|
+
liveCounts(region) {
|
|
230
|
+
return this.request("/webcast/live_counts", { query: { region } });
|
|
231
|
+
}
|
|
232
|
+
roomId(uniqueId) {
|
|
233
|
+
return this.request("/webcast/room_id", { query: this.uid(uniqueId) });
|
|
234
|
+
}
|
|
235
|
+
roomInfo(uniqueId) {
|
|
236
|
+
return this.request("/webcast/room_info", { query: this.uid(uniqueId) });
|
|
237
|
+
}
|
|
238
|
+
roomCover(uniqueId) {
|
|
239
|
+
return this.request("/webcast/room_cover", { query: this.uid(uniqueId) });
|
|
240
|
+
}
|
|
241
|
+
roomVideo(uniqueId) {
|
|
242
|
+
return this.request("/webcast/room_video", { query: this.uid(uniqueId) });
|
|
243
|
+
}
|
|
244
|
+
// --- Rankings / leaderboards ---
|
|
245
|
+
rankings(query) {
|
|
246
|
+
return this.request("/webcast/rankings", { query });
|
|
247
|
+
}
|
|
248
|
+
ranklist(query) {
|
|
249
|
+
return this.request("/webcast/ranklist", { query });
|
|
250
|
+
}
|
|
251
|
+
ranklistRegional(region) {
|
|
252
|
+
return this.request("/webcast/ranklist/regional", { query: { region } });
|
|
253
|
+
}
|
|
254
|
+
ranklistGaming(region) {
|
|
255
|
+
return this.request("/webcast/ranklist/gaming", { query: { region } });
|
|
256
|
+
}
|
|
257
|
+
gamingMovers(region) {
|
|
258
|
+
return this.request("/webcast/ranklist/gaming_movers", { query: { region } });
|
|
259
|
+
}
|
|
260
|
+
regionMovers(region) {
|
|
261
|
+
return this.request("/webcast/ranklist/region_movers", { query: { region } });
|
|
262
|
+
}
|
|
263
|
+
leaderboard(query) {
|
|
264
|
+
return this.request("/webcast/leaderboard", { query });
|
|
265
|
+
}
|
|
266
|
+
eligibleCreators(query) {
|
|
267
|
+
return this.request("/webcast/eligible_creators", { query });
|
|
268
|
+
}
|
|
269
|
+
// --- Gifts ---
|
|
270
|
+
giftInfo(query) {
|
|
271
|
+
return this.request("/webcast/gift_info", { query });
|
|
272
|
+
}
|
|
273
|
+
giftGallery(query) {
|
|
274
|
+
return this.request("/webcast/gift_gallery", { query });
|
|
275
|
+
}
|
|
276
|
+
giftsByCountry(country) {
|
|
277
|
+
return this.request("/webcast/gifts_by_country", { query: { country } });
|
|
278
|
+
}
|
|
279
|
+
// --- User / profile ---
|
|
280
|
+
lookupUsername(uniqueId) {
|
|
281
|
+
return this.request("/webcast/lookup_username", { query: this.uid(uniqueId) });
|
|
282
|
+
}
|
|
283
|
+
profileInfo(uniqueId) {
|
|
284
|
+
return this.request("/webcast/profile_info", { query: this.uid(uniqueId) });
|
|
285
|
+
}
|
|
286
|
+
resolveUserIds(usernames) {
|
|
287
|
+
return this.request("/webcast/resolve_user_ids", { method: "POST", body: { usernames } });
|
|
288
|
+
}
|
|
289
|
+
userProfile(uniqueId) {
|
|
290
|
+
return this.request("/webcast/user_profile", { query: this.uid(uniqueId) });
|
|
291
|
+
}
|
|
292
|
+
userVideos(uniqueId, query) {
|
|
293
|
+
return this.request("/webcast/user_videos", { query: { ...this.uid(uniqueId), ...query } });
|
|
294
|
+
}
|
|
295
|
+
userFollowers(uniqueId, query) {
|
|
296
|
+
return this.request("/webcast/user_followers", { query: { ...this.uid(uniqueId), ...query } });
|
|
297
|
+
}
|
|
298
|
+
userFollowing(uniqueId, query) {
|
|
299
|
+
return this.request("/webcast/user_following", { query: { ...this.uid(uniqueId), ...query } });
|
|
300
|
+
}
|
|
301
|
+
userLikes(uniqueId, query) {
|
|
302
|
+
return this.request("/webcast/user_likes", { query: { ...this.uid(uniqueId), ...query } });
|
|
303
|
+
}
|
|
304
|
+
userEarnings(uniqueId) {
|
|
305
|
+
return this.request("/webcast/user_earnings", { query: this.uid(uniqueId) });
|
|
306
|
+
}
|
|
307
|
+
// --- Content / feed ---
|
|
308
|
+
hashtagList(query) {
|
|
309
|
+
return this.request("/webcast/hashtag_list", { query });
|
|
310
|
+
}
|
|
311
|
+
fetch(body) {
|
|
312
|
+
return this.request("/webcast/fetch", { method: "POST", body });
|
|
313
|
+
}
|
|
314
|
+
feed(query) {
|
|
315
|
+
return this.request("/webcast/feed", { query });
|
|
316
|
+
}
|
|
317
|
+
chat(uniqueId, query) {
|
|
318
|
+
return this.request("/webcast/chat", { query: { ...this.uid(uniqueId), ...query } });
|
|
319
|
+
}
|
|
320
|
+
// --- Live analytics ---
|
|
321
|
+
analyticsVideoList(query) {
|
|
322
|
+
return this.request("/webcast/live_analytics/video_list", { query });
|
|
323
|
+
}
|
|
324
|
+
analyticsVideoDetail(query) {
|
|
325
|
+
return this.request("/webcast/live_analytics/video_detail", { query });
|
|
326
|
+
}
|
|
327
|
+
analyticsUserInteractions(query) {
|
|
328
|
+
return this.request("/webcast/live_analytics/user_interactions", { query });
|
|
329
|
+
}
|
|
330
|
+
// --- Moderation ---
|
|
331
|
+
moderationMutes(uniqueId) {
|
|
332
|
+
return this.request("/webcast/moderation/mutes", { query: this.uid(uniqueId) });
|
|
333
|
+
}
|
|
334
|
+
moderationBans(uniqueId) {
|
|
335
|
+
return this.request("/webcast/moderation/bans", { query: this.uid(uniqueId) });
|
|
336
|
+
}
|
|
337
|
+
// --- CAPTCHA solver (Pro+) ---
|
|
338
|
+
solvePuzzle(body) {
|
|
339
|
+
return this.request("/captcha/solve/puzzle", { method: "POST", body });
|
|
340
|
+
}
|
|
341
|
+
solveRotate(body) {
|
|
342
|
+
return this.request("/captcha/solve/rotate", { method: "POST", body });
|
|
343
|
+
}
|
|
344
|
+
solveShapes(body) {
|
|
345
|
+
return this.request("/captcha/solve/shapes", { method: "POST", body });
|
|
346
|
+
}
|
|
347
|
+
// --- Captions ---
|
|
348
|
+
captionsCredits() {
|
|
349
|
+
return this.request("/captions/credits");
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
|
|
143
353
|
// src/captions.ts
|
|
144
354
|
import WebSocket2 from "ws";
|
|
145
355
|
var CAPTIONS_BASE = "wss://api.tik.tools/captions";
|
|
@@ -249,5 +459,7 @@ var TikTokCaptions = class {
|
|
|
249
459
|
};
|
|
250
460
|
export {
|
|
251
461
|
TikTokCaptions,
|
|
252
|
-
TikTokLive
|
|
462
|
+
TikTokLive,
|
|
463
|
+
TikTool,
|
|
464
|
+
TikToolError
|
|
253
465
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiktok-live-api",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.7",
|
|
4
4
|
"description": "Unofficial TikTok LIVE API Client - Real-time chat, gifts, viewers, battles, and AI live captions from any TikTok livestream. Managed WebSocket API with 99.9% uptime.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|