diff --git a/README.md b/README.md index d017ec2..5fe7e4f 100644 --- a/README.md +++ b/README.md @@ -260,6 +260,100 @@ Tiktok.GetUserLiked(username, { - [Tiktok User Liked Videos Response](#tiktok-user-liked-videos) +## Tiktok Collection + +Get videos from a TikTok collection (supports collection ID or URL) + +```javascript +const Tiktok = require("@tobyg74/tiktok-api-dl") + +// Using collection ID +const collectionId = "7507916135931218695" +Tiktok.Collection(collectionId, { + cursor: "0", // optional, default is "0" + count: 5, // optional, default is 5 + proxy: "YOUR_PROXY" // optional +}).then((result) => console.log(result)) + +// Using collection URL +const collectionUrl = "https://www.tiktok.com/@username/collection/name-id" +Tiktok.Collection(collectionUrl, { + cursor: "0", + count: 5, + proxy: "YOUR_PROXY" +}).then((result) => console.log(result)) +``` + +### CLI Usage + +```bash +# Using collection ID +tiktokdl collection 7507916135931218695 -n 5 + +# Using collection URL +tiktokdl collection "https://www.tiktok.com/@username/collection/name-id" -n 5 + +# With cursor for pagination +tiktokdl collection 7507916135931218695 -c 5 -n 5 + +# With proxy +tiktokdl collection 7507916135931218695 -n 5 -p "http://your-proxy-url" +``` + +### Response Type + +```typescript +interface TiktokCollectionResponse { + status: "success" | "error" + message?: string + result?: { + itemList: Array<{ + id: string + desc: string + createTime: number + author?: { + id: string + uniqueId: string + nickname: string + avatarThumb: string + avatarMedium: string + avatarLarger: string + signature: string + verified: boolean + } + statistics?: { + playCount: number + diggCount: number + shareCount: number + commentCount: number + collectCount: number + } + video?: { + id: string + height: number + width: number + duration: number + ratio: string + cover: string + originCover: string + dynamicCover: string + playAddr: string + downloadAddr: string + format: string + bitrate: number + } + textExtra?: Array<{ + hashtagName: string + hashtagId: string + type: number + }> + }> + hasMore: boolean + cursor: string + } +} +``` + # API Response Types ## Tiktok Downloader diff --git a/src/cli/index.ts b/src/cli/index.ts index 580d333..c4e88ea 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -404,12 +404,19 @@ program ) .option("-c, --cursor ", "Cursor for pagination", "0") .option("-p, --proxy ", "Proxy URL (http/https/socks)") + .option( + "-n, --count ", + "Number of items to fetch", + (val) => parseInt(val), + 5 + ) .action(async (collectionIdOrUrl, options) => { try { - Logger.info(`Fetching collection...`) + Logger.info(`Fetching collection... (count: ${options.count})`) const results = await Tiktok.Collection(collectionIdOrUrl, { cursor: options.cursor, - proxy: options.proxy + proxy: options.proxy, + count: options.count }) if (results.status === "success" && results.result) { diff --git a/src/constants/params.ts b/src/constants/params.ts index 9fff962..53b622b 100644 --- a/src/constants/params.ts +++ b/src/constants/params.ts @@ -353,9 +353,9 @@ const generateOdinId = () => { return `${prefix}${random}` } -export const _getCollectionParams = (collectionId: string, cursor: string = "0") => { +export const _getCollectionParams = (collectionId: string, cursor: string = "0", count: number = 5) => { return qs.stringify({ - WebIdLastTime: 1741246176, + WebIdLastTime: Date.now(), aid: 1988, app_language: "en", app_name: "tiktok_web", @@ -365,13 +365,12 @@ export const _getCollectionParams = (collectionId: string, cursor: string = "0") browser_platform: "Win32", browser_version: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36", channel: "tiktok_web", - clientABVersions: "70508271,72437276,73356773,73406215,73464037,73558921,73561312,73563784,73607175,73713381,73720541,73737112,73759867,73768252,73787023,73810364,73810951,73811265,73812969,73815488,73815490,73817289,73821742,73849114,73855857,73858886,73858985,73867894,73880997,73902810,70138197,70156809,70405643,71057832,71200802,71381811,71516509,71803300,71962127,72360691,72408100,72854054,72892778,73004916,73171280,73208420,73574728,73628214", collectionId, cookie_enabled: true, - count: 30, + count, cursor, data_collection_enabled: true, - device_id: "7478595310673266194", + device_id: "7002566096994190854", device_platform: "web_pc", focus_state: true, from_page: "user", @@ -389,7 +388,7 @@ export const _getCollectionParams = (collectionId: string, cursor: string = "0") sourceType: 113, tz_name: "Pacific/Auckland", user_is_login: true, - verifyFp: "verify_mb1zbd2f_sMPZ5W5a_A3yc_4dmk_8NT3_kp4HJQOdrhp5", + verifyFp: "verify_lacphy8d_z2ux9idt_xdmu_4gKb_9nng_NNTTTvsFS8ao", webcast_language: "en" }) } diff --git a/src/index.ts b/src/index.ts index 5f574f2..052acb4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -131,6 +131,7 @@ export = { * @param {Object} options - The options for collection * @param {string} [options.proxy] - Optional proxy URL * @param {string} [options.cursor] - Optional cursor for pagination + * @param {number} [options.count] - Optional number of items to fetch * @returns {Promise} */ Collection: async ( @@ -138,6 +139,7 @@ export = { options?: { proxy?: string cursor?: string + count?: number } ): Promise => { const collectionId = extractCollectionId(collectionIdOrUrl) @@ -147,7 +149,7 @@ export = { message: "Invalid collection ID or URL format" } } - return await getCollection(collectionId, options?.proxy, options?.cursor) + return await getCollection(collectionId, options?.proxy, options?.cursor, options?.count) }, /** diff --git a/src/utils/get/getCollection.ts b/src/utils/get/getCollection.ts index 32cfbc9..d9df375 100644 --- a/src/utils/get/getCollection.ts +++ b/src/utils/get/getCollection.ts @@ -31,27 +31,35 @@ const createProxyAgent = (proxy?: string): ProxyConfig => { * @param {string} collectionId - Collection ID * @param {string} proxy - Your Proxy (optional) * @param {string} cursor - Cursor for pagination (optional) + * @param {number} count - Number of items to fetch (optional) * @returns {Promise} */ export const getCollection = async ( collectionId: string, proxy?: string, - cursor: string = "0" + cursor: string = "0", + count: number = 5 ): Promise => { try { const response = await retry( async () => { - const res = await Axios(_tiktokGetCollection(_getCollectionParams(collectionId, cursor)), { - method: "GET", - headers: { - "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36", - "Accept": "*/*", - "Accept-Language": "en-US,en;q=0.7", - "Referer": "https://www.tiktok.com/", - "Origin": "https://www.tiktok.com" - }, - ...createProxyAgent(proxy) - }) + const res = await Axios( + _tiktokGetCollection( + _getCollectionParams(collectionId, cursor, count) + ), + { + method: "GET", + headers: { + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36", + Accept: "*/*", + "Accept-Language": "en-US,en;q=0.7", + Referer: "https://www.tiktok.com/", + Origin: "https://www.tiktok.com" + }, + ...createProxyAgent(proxy) + } + ) if (res.data && res.data.statusCode === 0) { return res.data @@ -78,7 +86,8 @@ export const getCollection = async ( } catch (error) { return { status: "error", - message: error instanceof Error ? error.message : ERROR_MESSAGES.NETWORK_ERROR + message: + error instanceof Error ? error.message : ERROR_MESSAGES.NETWORK_ERROR } } -} \ No newline at end of file +}