TikTok Playlist Discovery & Video Order Scraper
Scrape TikTok playlists - discover all playlists for a profile, get playlist metadata, and extract all videos. Supports playlist URLs, IDs, and profile URLs. No cookies required.
Input schema
Input fields, types, required flags, descriptions, defaults, and prefills come from the published definition. Prefill examples are distinct from defaults.
| Field | Type | Required | Description |
|---|---|---|---|
playlistUrls | array | optional | Playlist URLs, e.g. https://www.tiktok.com/@natgeo/playlist/Cinematic-7509464647364283178. Collection URLs pasted here are detected automatically. |
playlistIds | array | optional | Numeric TikTok playlist IDs (15–20 digits). If an ID belongs to a public collection, the collection route is tried automatically. |
collectionUrls | array | optional | Public collection URLs, e.g. https://www.tiktok.com/@user/collection/places-to-go-7154034669288196891. |
Show all input fields
| Field | Type | Required | Description |
|---|---|---|---|
playlistUrls | array | optional | Playlist URLs, e.g. https://www.tiktok.com/@natgeo/playlist/Cinematic-7509464647364283178. Collection URLs pasted here are detected automatically. |
playlistIds | array | optional | Numeric TikTok playlist IDs (15–20 digits). If an ID belongs to a public collection, the collection route is tried automatically. |
collectionUrls | array | optional | Public collection URLs, e.g. https://www.tiktok.com/@user/collection/places-to-go-7154034669288196891. |
collectionIds | array | optional | Numeric TikTok collection IDs (15–20 digits). |
profileUrls | array | optional | TikTok profile URLs. Every public playlist on each profile is discovered, up to the per-profile limit. |
usernames | array | optional | TikTok handles with or without @. Every public playlist on each profile is discovered. |
mode | string | optional | Return playlist/collection metadata rows, video rows, or both. |
maxPostsPerPlaylist | integer | optional | Maximum videos to return from each playlist or collection. Set high enough to cover the full list. |
maxPlaylistsPerProfile | integer | optional | Maximum playlists to process for each profile or username target. |
maxItems | integer | optional | Stop after this many dataset rows across all targets, including status rows. Use 0 for no global limit. |
Download the published input schema
View complete JSON
{
"description": "Scrape TikTok playlists and public collections by URL, numeric ID, profile URL or @username.",
"properties": {
"collectionIds": {
"description": "Numeric TikTok collection IDs (15–20 digits).",
"editor": "stringList",
"items": {
"type": "string"
},
"title": "Collection IDs",
"type": "array"
},
"collectionUrls": {
"description": "Public collection URLs, e.g. https://www.tiktok.com/@user/collection/places-to-go-7154034669288196891.",
"editor": "stringList",
"items": {
"type": "string"
},
"title": "Collection URLs",
"type": "array"
},
"maxItems": {
"default": 0,
"description": "Stop after this many dataset rows across all targets, including status rows. Use 0 for no global limit.",
"maximum": 100000,
"minimum": 0,
"prefill": 1,
"title": "Max Rows (Global)",
"type": "integer"
},
"maxPlaylistsPerProfile": {
"default": 20,
"description": "Maximum playlists to process for each profile or username target.",
"maximum": 100,
"minimum": 1,
"prefill": 1,
"title": "Max Playlists Per Profile",
"type": "integer"
},
"maxPostsPerPlaylist": {
"default": 100,
"description": "Maximum videos to return from each playlist or collection. Set high enough to cover the full list.",
"maximum": 5000,
"minimum": 1,
"prefill": 1,
"title": "Max Videos Per Playlist",
"type": "integer"
},
"mode": {
"default": "both",
"description": "Return playlist/collection metadata rows, video rows, or both.",
"editor": "select",
"enum": [
"metadata",
"posts",
"both"
],
"enumTitles": [
"Playlist metadata only",
"Videos only",
"Metadata and videos"
],
"prefill": "metadata",
"title": "What to Return",
"type": "string"
},
"playlistIds": {
"description": "Numeric TikTok playlist IDs (15–20 digits). If an ID belongs to a public collection, the collection route is tried automatically.",
"editor": "stringList",
"items": {
"type": "string"
},
"title": "Playlist IDs",
"type": "array"
},
"playlistUrls": {
"description": "Playlist URLs, e.g. https://www.tiktok.com/@natgeo/playlist/Cinematic-7509464647364283178. Collection URLs pasted here are detected automatically.",
"editor": "stringList",
"items": {
"type": "string"
},
"prefill": [
"https://www.tiktok.com/@natgeo/playlist/Cinematic-7509464647364283178"
],
"title": "Playlist URLs",
"type": "array"
},
"profileUrls": {
"description": "TikTok profile URLs. Every public playlist on each profile is discovered, up to the per-profile limit.",
"editor": "stringList",
"items": {
"type": "string"
},
"title": "Profile URLs",
"type": "array"
},
"usernames": {
"description": "TikTok handles with or without @. Every public playlist on each profile is discovered.",
"editor": "stringList",
"items": {
"type": "string"
},
"title": "Usernames",
"type": "array"
}
},
"required": [],
"schemaVersion": 1,
"title": "TikTok Playlist & Collection Scraper Input",
"type": "object"
}
Output schema
Published result links and storage locations. This schema is not an exhaustive contract for every field in a dataset record.
| Field | Type | Required | Description |
|---|---|---|---|
playlistsAndVideos | string | optional | Dataset containing playlist/collection rows, ordered video rows and status rows. |
Download the published output schema
View complete JSON
{
"actorOutputSchemaVersion": 1,
"description": "Playlist and collection metadata rows, ordered video rows with engagement and media fields, and visible status rows.",
"properties": {
"playlistsAndVideos": {
"description": "Dataset containing playlist/collection rows, ordered video rows and status rows.",
"template": "{{links.apiDefaultDatasetUrl}}/items",
"title": "Playlists, collections & videos",
"type": "string"
}
},
"title": "TikTok Playlist & Collection Scraper Output"
}
Dataset schema
Published dataset views and any declared field definitions. A view can select only a subset of the returned record fields.
Download the published dataset schema
View complete JSON
{
"actorSpecification": 1,
"fields": {
"AIGCDescription": {
"description": "Description for AI-generated content label (post rows only)",
"title": "AIGC Description",
"type": "string"
},
"adLabelVersion": {
"description": "Ad label version; non-zero when the post is a sponsored ad (post rows only)",
"title": "Ad Label Version",
"type": "integer"
},
"author": {
"description": "Author/creator information at time of scraping (post rows only)",
"properties": {
"avatarUrl": {
"title": "Avatar URL",
"type": "string"
},
"bio": {
"title": "Bio",
"type": "string"
},
"displayName": {
"title": "Display Name",
"type": "string"
},
"followerCount": {
"title": "Followers",
"type": "integer"
},
"followingCount": {
"title": "Following",
"type": "integer"
},
"heartCount": {
"title": "Hearts/Likes",
"type": "integer"
},
"id": {
"title": "User ID",
"type": "string"
},
"privateAccount": {
"title": "Private Account",
"type": "boolean"
},
"roomId": {
"title": "Live Room ID (non-empty when live)",
"type": "string"
},
"secUid": {
"title": "Secure UID",
"type": "string"
},
"username": {
"title": "Username",
"type": "string"
},
"verified": {
"title": "Verified",
"type": "boolean"
},
"videoCount": {
"title": "Videos",
"type": "integer"
}
},
"title": "Author",
"type": "object"
},
"caption": {
"description": "Post caption/description text including hashtags and mentions (post rows only)",
"title": "Caption",
"type": "string"
},
"collectCount": {
"description": "Number of times post was bookmarked/collected (post rows only)",
"title": "Collect Count",
"type": "integer"
},
"commentCount": {
"description": "Number of comments (post rows only)",
"title": "Comment Count",
"type": "integer"
},
"commentStatus": {
"description": "Comment permission setting (0=all, 1=friends, 2=none) (post rows only)",
"title": "Comment Status",
"type": "integer"
},
"coverPostId": {
"description": "Post ID used as the playlist cover thumbnail (playlist rows only)",
"title": "Cover Post ID",
"type": "string"
},
"coverThumbnailUrl": {
"description": "Thumbnail image URL of the playlist cover (playlist rows only)",
"title": "Cover Thumbnail URL",
"type": "string"
},
"createTime": {
"description": "Unix timestamp (seconds) when the post was created (post rows only)",
"title": "Create Time (Unix)",
"type": "integer"
},
"createdAt": {
"description": "ISO 8601 UTC datetime when the post was created (post rows only)",
"title": "Created At",
"type": "string"
},
"creatorAvatarUrl": {
"description": "Avatar image URL of the playlist creator (playlist rows only)",
"title": "Creator Avatar URL",
"type": "string"
},
"creatorDisplayName": {
"description": "Display name (nickname) of the playlist creator (playlist rows only)",
"title": "Creator Display Name",
"type": "string"
},
"creatorId": {
"description": "TikTok user ID of the playlist creator (playlist rows only)",
"title": "Creator ID",
"type": "string"
},
"creatorStats": {
"description": "Creator profile counters at scrape time (playlist rows only, when available).",
"properties": {
"followerCount": {
"title": "Followers",
"type": "integer"
},
"followingCount": {
"title": "Following",
"type": "integer"
},
"heartCount": {
"title": "Hearts/Likes",
"type": "integer"
},
"videoCount": {
"title": "Videos",
"type": "integer"
}
},
"title": "Creator Stats",
"type": "object"
},
"creatorUsername": {
"description": "TikTok @username of the playlist creator (playlist rows only)",
"title": "Creator Username",
"type": "string"
},
"creatorVerified": {
"description": "Whether the playlist creator has a verified badge (playlist rows only)",
"title": "Creator Verified",
"type": "boolean"
},
"diversificationLabels": {
"description": "TikTok topic labels attached to the video when present (post rows only).",
"title": "Diversification Labels",
"type": "array"
},
"duetEnabled": {
"description": "Whether the creator allows duets with this video (post rows only)",
"title": "Duet Enabled",
"type": "boolean"
},
"forFriend": {
"description": "Whether the post is restricted to friends only (post rows only)",
"title": "For Friend",
"type": "boolean"
},
"hashtags": {
"description": "Hashtags used in the post caption (post rows only)",
"items": {
"properties": {
"id": {
"title": "Hashtag ID",
"type": "string"
},
"isCommerce": {
"title": "Is Commerce",
"type": "boolean"
},
"name": {
"title": "Hashtag Name",
"type": "string"
}
},
"type": "object"
},
"title": "Hashtags",
"type": "array"
},
"images": {
"description": "Images for slideshow posts (postType='slideshow') (post rows only)",
"items": {
"properties": {
"height": {
"title": "Height",
"type": "integer"
},
"ordinal": {
"title": "Index",
"type": "integer"
},
"urlList": {
"title": "Image URLs",
"type": "array"
},
"width": {
"title": "Width",
"type": "integer"
}
},
"type": "object"
},
"title": "Slideshow Images",
"type": "array"
},
"input": {
"description": "The original URL, ID or handle that produced this status row (status rows only).",
"title": "Input",
"type": "string"
},
"isAd": {
"description": "Whether this post is a paid advertisement (post rows only)",
"title": "Is Ad",
"type": "boolean"
},
"isAigc": {
"description": "Whether TikTok labels this as AI-generated content (post rows only)",
"title": "Is AI Generated Content",
"type": "boolean"
},
"isECVideo": {
"description": "Whether this is a shopping/e-commerce video (post rows only)",
"title": "Is E-Commerce Video",
"type": "boolean"
},
"likeCount": {
"description": "Number of likes/diggs (post rows only)",
"title": "Like Count",
"type": "integer"
},
"locationCreated": {
"description": "ISO country code where the post was created (post rows only)",
"title": "Location Created",
"type": "string"
},
"mediaUrlExpiresAt": {
"description": "ISO 8601 UTC datetime when signed media URLs expire (post rows only)",
"title": "Media URL Expires At",
"type": "string"
},
"mentions": {
"description": "@mentions in the post caption with text offsets (post rows only)",
"items": {
"properties": {
"awemeId": {
"title": "Mentioned Post ID (if any)",
"type": "string"
},
"end": {
"title": "End Offset",
"type": "integer"
},
"start": {
"title": "Start Offset",
"type": "integer"
},
"username": {
"title": "Username",
"type": "string"
}
},
"type": "object"
},
"title": "Mentions",
"type": "array"
},
"message": {
"description": "Human-readable explanation of the status outcome (status rows only).",
"title": "Message",
"type": "string"
},
"music": {
"description": "Sound/music used in the post (post rows only)",
"properties": {
"album": {
"title": "Album",
"type": "string"
},
"authorName": {
"title": "Author",
"type": "string"
},
"coverUrl": {
"title": "Cover URL",
"type": "string"
},
"dspLinks": {
"title": "DSP Links (Spotify, Apple Music, etc.)",
"type": "array"
},
"duration": {
"title": "Duration (s)",
"type": "integer"
},
"id": {
"title": "Music ID",
"type": "string"
},
"isCommerceMusic": {
"title": "Is Commerce Music",
"type": "boolean"
},
"isCopyrighted": {
"title": "Is Copyrighted",
"type": "boolean"
},
"isPrivate": {
"title": "Is Private Sound",
"type": "boolean"
},
"isUnlimitedMusic": {
"title": "Is Unlimited Music",
"type": "boolean"
},
"original": {
"title": "Original Sound",
"type": "boolean"
},
"playUrl": {
"title": "Play URL",
"type": "string"
},
"shootDuration": {
"title": "Shoot Duration (s)",
"type": "number"
},
"title": {
"title": "Title",
"type": "string"
}
},
"title": "Music",
"type": "object"
},
"originalItem": {
"description": "Whether this post is an original (non-duet, non-stitch) creation (post rows only)",
"title": "Original Item",
"type": "boolean"
},
"playCount": {
"description": "Number of video plays (post rows only)",
"title": "Play Count",
"type": "integer"
},
"playlistCoverUrl": {
"description": "Cover image URL for the playlist or collection (playlist rows only; signed and expiring).",
"title": "Playlist Cover URL",
"type": "string"
},
"playlistId": {
"description": "TikTok playlist or collection ID (playlist and post rows).",
"title": "Playlist ID",
"type": "string"
},
"playlistName": {
"description": "Display name of the playlist or collection (playlist and post rows).",
"title": "Playlist Name",
"type": "string"
},
"playlistType": {
"description": "Whether this row describes a playlist or a public collection (playlist and post rows).",
"title": "Playlist Type",
"type": "string"
},
"playlistUrl": {
"description": "Canonical URL of the playlist or collection (playlist and post rows).",
"title": "Playlist URL",
"type": "string"
},
"poi": {
"description": "TikTok POI/location attachment when the video carries one (post rows only).",
"title": "Point of Interest",
"type": "object"
},
"positionInPlaylist": {
"description": "0-based position of the video within the playlist (post rows only)",
"title": "Position In Playlist",
"type": "integer"
},
"postId": {
"description": "TikTok's unique post/video ID (post rows only)",
"title": "Post ID",
"type": "string"
},
"postType": {
"description": "Either 'video' or 'slideshow' (post rows only)",
"title": "Post Type",
"type": "string"
},
"postUrl": {
"description": "Direct URL to the TikTok post (post rows only)",
"title": "Post URL",
"type": "string"
},
"privateItem": {
"description": "Whether the post is set to private (post rows only)",
"title": "Private Item",
"type": "boolean"
},
"repostCount": {
"description": "Number of reposts (post rows only)",
"title": "Repost Count",
"type": "integer"
},
"rowType": {
"description": "Discriminator: 'playlist', 'post' or 'status'.",
"title": "Row Type",
"type": "string"
},
"scrapedAt": {
"description": "ISO 8601 UTC datetime when this row was generated (all row types).",
"title": "Scraped At",
"type": "string"
},
"shareCount": {
"description": "Number of shares (post rows only)",
"title": "Share Count",
"type": "integer"
},
"shareEnabled": {
"description": "Whether sharing is enabled for this post (post rows only)",
"title": "Share Enabled",
"type": "boolean"
},
"shareMeta": {
"description": "TikTok's share title and description for a public collection (collection rows only).",
"properties": {
"desc": {
"title": "Share Description",
"type": "string"
},
"title": {
"title": "Share Title",
"type": "string"
}
},
"title": "Share Meta",
"type": "object"
},
"status": {
"description": "Outcome for a failed or partial target: invalid, not_found, private, empty, blocked or partial (status rows only).",
"title": "Status",
"type": "string"
},
"stitchEnabled": {
"description": "Whether the creator allows stitching this video (post rows only)",
"title": "Stitch Enabled",
"type": "boolean"
},
"textLanguage": {
"description": "Detected language code of the caption text (post rows only)",
"title": "Text Language",
"type": "string"
},
"video": {
"description": "Video technical metadata and signed play/cover URLs (post rows only)",
"properties": {
"bitrate": {
"title": "Bitrate",
"type": "integer"
},
"bitrateInfo": {
"description": "All available quality/bitrate variants with play URLs (post rows only)",
"title": "Bitrate Info",
"type": "array"
},
"codecType": {
"title": "Codec",
"type": "string"
},
"cover": {
"title": "Cover Image URL",
"type": "string"
},
"definition": {
"title": "Definition",
"type": "string"
},
"downloadAddr": {
"title": "Download URL",
"type": "string"
},
"duration": {
"title": "Duration (s)",
"type": "integer"
},
"dynamicCover": {
"title": "Dynamic Cover URL",
"type": "string"
},
"format": {
"title": "Format",
"type": "string"
},
"height": {
"title": "Height (px)",
"type": "integer"
},
"originCover": {
"title": "Original Cover URL",
"type": "string"
},
"playUrl": {
"title": "Play URL",
"type": "string"
},
"ratio": {
"title": "Aspect Ratio",
"type": "string"
},
"size": {
"title": "File Size (bytes)",
"type": "integer"
},
"videoQuality": {
"title": "Video Quality Label",
"type": "string"
},
"volumeInfo": {
"description": "Audio loudness and peak level metadata (post rows only)",
"title": "Volume Info",
"type": "object"
},
"width": {
"title": "Width (px)",
"type": "integer"
}
},
"title": "Video",
"type": "object"
},
"videoCount": {
"description": "Total number of videos in the playlist as reported by TikTok (playlist rows only)",
"title": "Video Count",
"type": "integer"
},
"viewerRegion": {
"description": "ISO country code of the inferred viewer region (post rows only)",
"title": "Viewer Region",
"type": "string"
}
},
"title": "TikTok Playlists, Collections & Videos",
"views": {
"overview": {
"description": "Mixed dataset with playlist, post and status rows. Use rowType to distinguish them.",
"display": {
"component": "table",
"properties": {
"caption": {
"format": "text",
"label": "Caption"
},
"creatorUsername": {
"format": "text",
"label": "Creator"
},
"likeCount": {
"format": "number",
"label": "Likes"
},
"playCount": {
"format": "number",
"label": "Views"
},
"playlistId": {
"format": "text",
"label": "Playlist ID"
},
"playlistName": {
"format": "text",
"label": "Playlist Name"
},
"playlistType": {
"format": "text",
"label": "Playlist Type"
},
"playlistUrl": {
"format": "link",
"label": "Playlist URL"
},
"positionInPlaylist": {
"format": "number",
"label": "Position"
},
"postId": {
"format": "text",
"label": "Post ID"
},
"postUrl": {
"format": "link",
"label": "Post URL"
},
"rowType": {
"format": "text",
"label": "Type"
},
"scrapedAt": {
"format": "text",
"label": "Scraped At"
},
"videoCount": {
"format": "number",
"label": "Video Count"
}
}
},
"title": "Playlists & Posts Overview",
"transformation": {
"fields": [
"rowType",
"playlistType",
"playlistId",
"playlistName",
"videoCount",
"creatorUsername",
"positionInPlaylist",
"postId",
"caption",
"playCount",
"likeCount",
"postUrl",
"playlistUrl",
"scrapedAt"
]
}
},
"status": {
"description": "Visible outcomes for invalid, empty, private, blocked or partially fetched targets.",
"display": {
"component": "table",
"properties": {
"input": {
"format": "text",
"label": "Input"
},
"message": {
"format": "text",
"label": "Message"
},
"playlistId": {
"format": "text",
"label": "Playlist ID"
},
"playlistName": {
"format": "text",
"label": "Playlist Name"
},
"playlistType": {
"format": "text",
"label": "Target Type"
},
"rowType": {
"format": "text",
"label": "Type"
},
"scrapedAt": {
"format": "text",
"label": "Scraped At"
},
"status": {
"format": "text",
"label": "Status"
}
}
},
"title": "Status Rows",
"transformation": {
"fields": [
"rowType",
"status",
"playlistType",
"playlistId",
"playlistName",
"input",
"message",
"scrapedAt"
]
}
}
}
}
Key-value schema
Published key-value store definitions, when provided by this build.
This definition is not present in the default published build. See the published README for available documentation.
Published README
Read the full published documentation
TikTok Playlist & Collection Scraper
Collect every public video in a TikTok playlist or collection, in the creator's order, plus the playlist details that make the data usable: cover image, owner, owner stats, view/like/comment counts, sound metadata, media URLs, hashtags, mentions and slideshow images.
Give it a playlist URL, a collection URL, a numeric ID, a profile URL or a plain @handle. It returns one row per playlist or collection, one row per video, and clear status rows when a target cannot be read. No login, cookies or proxy setup are needed.
What this actor does
- Scrapes playlists (
/@user/playlist/...) and public collections (/@user/collection/...) - Accepts full URLs, numeric playlist/collection IDs, profile URLs and handles — mix them in one run
- Returns the full ordered video list, not just the first visible page
- Discovers every public playlist on a profile, up to a limit you set
- Adds the playlist cover, creator identity, creator stats,
shareMetafor collections and ascrapedAttimestamp - Captures slideshow posts as slideshows with their ordered image URLs
- Reports invalid, private, empty, blocked and partial targets as
rowType: "status"rows - Deduplicates videos by post ID and omits empty fields at every depth
Input
| Field | Type | Default | Description |
|---|---|---|---|
playlistUrls |
string[] | – | Playlist URLs. Collection URLs pasted here are detected automatically. |
playlistIds |
string[] | — | Numeric playlist IDs (15–20 digits). A collection ID is retried on the collection route. |
collectionUrls |
string[] | — | Public collection URLs. |
collectionIds |
string[] | — | Numeric collection IDs. |
profileUrls |
string[] | — | Profile URLs; every public playlist on the profile is discovered. |
usernames |
string[] | — | Handles with or without @. |
mode |
select | both |
metadata, posts or both. |
maxPostsPerPlaylist |
integer | 100 | Videos per playlist/collection (1–5000). Raise it for large playlists. |
maxPlaylistsPerProfile |
integer | 20 | Playlists processed per profile (1–100). |
maxItems |
integer | 0 | Global row cap across all targets and status rows. 0 means no cap. |
Example: one playlist, metadata only
{
"playlistUrls": ["https://www.tiktok.com/@natgeo/playlist/Cinematic-7509464647364283178"],
"mode": "metadata",
"maxPostsPerPlaylist": 1
}
Example: full playlist in creator order
{
"playlistUrls": ["https://www.tiktok.com/@natgeo/playlist/Cinematic-7509464647364283178"],
"mode": "posts",
"maxPostsPerPlaylist": 500
}
Example: a public collection by URL or ID
{
"collectionUrls": ["https://www.tiktok.com/@aubreyisamess/collection/places%20to%20go-7154034669288196891"],
"mode": "both",
"maxPostsPerPlaylist": 1000
}
Example: discover a profile's playlists
{
"usernames": ["natgeo"],
"mode": "metadata",
"maxPlaylistsPerProfile": 20
}
Example: mixed targets with a global cap
{
"playlistIds": ["7509464647364283178"],
"collectionIds": ["7154034669288196891"],
"usernames": ["natgeo"],
"mode": "both",
"maxPostsPerPlaylist": 500,
"maxPlaylistsPerProfile": 5,
"maxItems": 250
}
Output
All rows share rowType, scrapedAt and (when applicable) playlistId, playlistName, playlistType and playlistUrl.
Playlist / collection row (rowType: "playlist")
playlistType—"playlist"or"collection"playlistId,playlistName,videoCountplaylistUrl— canonical TikTok URLplaylistCoverUrlandcoverThumbnailUrl— cover image (signed, expiring)coverPostId— only when TikTok names a cover videocreatorId,creatorUsername,creatorDisplayName,creatorVerified,creatorAvatarUrlcreatorStats—followerCount,followingCount,heartCount,videoCountshareMeta—titleanddescfor public collectionsscrapedAt— ISO 8601 UTC timestamp
Video row (rowType: "post")
playlistId,playlistName,playlistType,playlistUrl,positionInPlaylist(zero-based, source order)postId,postType(videoorslideshow),postUrlcaption,textLanguage,createTime,createdAtplayCount,likeCount,commentCount,shareCount,collectCount,repostCountcommentStatus,shareEnabled,duetEnabled,stitchEnabledisAd,isECVideo,privateItem,forFriend,originalItem,isAigc,AIGCDescriptionauthor— ID, secure ID, username, display name, bio, verified, avatar, follower/following/heart/video countsmusic— ID, title, author, duration, original flag, cover URL and play URL when TikTok exposes itvideo— dimensions, duration, ratio, definition, codec, bitrate info, play/download/cover URLsimages— ordered slideshow images with width, height and URL listhashtags,mentionsmediaUrlExpiresAt— when signed video/cover URLs expirescrapedAt
Status row (rowType: "status")
status—invalid,not_found,private,empty,blockedorpartialinput— the URL, ID or handle that produced the rowplaylistId,playlistName,playlistTypewhen knownmessage— plain-language explanationscrapedAt
Ordering and completeness
positionInPlaylist follows the order TikTok serves for that playlist or collection. It is not sorted by publish date, because creators deliberately order series, tutorials and trip lists. Every page is read until the source reports no more videos or your maxPostsPerPlaylist / maxItems limit is reached.
Collections can report more videos than are publicly accessible (deleted, private or region-locked items are still counted). The actor returns every accessible video once and never invents filler rows.
Use cases
- Archiving a creator's series before videos disappear
- Researching how publishers group content into themed playlists
- Auditing collection-based campaigns and their engagement
- Building ordered video libraries from travel, education or recipe collections
- Tracking creator output, follower growth and playlist size over time
- Feeding ordered short-form video datasets into a CMS, dashboard or model
FAQ
Do I need cookies or a login? No. The actor reads public pages without credentials.
Do I need to configure a proxy? No. The actor chooses its own connection automatically.
Why is positionInPlaylist not sorted by date?
Playlists and collections have a creator-defined order. The position preserves that order, which is usually the point of scraping a playlist.
How many videos will I get?
All publicly accessible videos, up to maxPostsPerPlaylist per target and maxItems overall. A playlist reported as 34 videos with 34 public items returns 34 rows.
Why does a collection say 651 videos but return fewer? TikTok counts unavailable entries in the collection total. Only publicly accessible videos can be returned.
What happens with a bad or private target? The run finishes successfully and emits a status row explaining the outcome instead of a fake playlist row.
Are the video and image URLs permanent?
No. TikTok's CDN URLs are signed and expire after a few hours. Use postUrl as the stable reference and re-run when you need fresh media URLs.
Can I combine playlists, collections and profiles in one run? Yes. Add any mix of the input arrays. Duplicate targets are processed once.
What does maxItems count?
Every dataset row, including playlist, video and status rows.
Python quickstart
Use a schema-derived input and the Python standard library to start a run. An Apify account and token are required for execution.
Source build Dawm0G9OaKftgReSB. Documentation is regenerated from the default published build; private drafts are not included.