Nimbryxo Studio

TikTok Video, Audio & Cover Downloader

Download TikTok videos, cover thumbnails, background audio, and slideshow images by post URL, with quality selection and a stable download link per file.

Input schema

Input fields, types, required flags, descriptions, defaults, and prefills come from the published definition. Prefill examples are distinct from defaults.

FieldTypeRequiredDescription
postUrlsarrayrequiredTikTok post URLs or IDs. Accepts /@user/video/ID, /@user/photo/ID, /video/ID, /photo/ID, embed URLs (/embed/v2/ID), vm.tiktok.com / vt.tiktok.com / /t/ short links, m.tiktok.com/v/ID.html, and bare numeric post IDs. Duplicates are processed once.
assetTypesarrayoptionalAssets to produce for each post. 'video' = MP4; 'audio' = TikTok sound; 'cover' = cover image; 'slideshow' = ordered photo frames; 'metadata' = post/author/stats/music row.
videoVariantstringoptional'clean' = no-watermark MP4 (requires a same-page browser session and is always re-hosted). 'watermarked' = logo copy, usable as an expiring CDN URL. 'both' = one row per variant.
Show all input fields
FieldTypeRequiredDescription
postUrlsarrayrequiredTikTok post URLs or IDs. Accepts /@user/video/ID, /@user/photo/ID, /video/ID, /photo/ID, embed URLs (/embed/v2/ID), vm.tiktok.com / vt.tiktok.com / /t/ short links, m.tiktok.com/v/ID.html, and bare numeric post IDs. Duplicates are processed once.
assetTypesarrayoptionalAssets to produce for each post. 'video' = MP4; 'audio' = TikTok sound; 'cover' = cover image; 'slideshow' = ordered photo frames; 'metadata' = post/author/stats/music row.
videoVariantstringoptional'clean' = no-watermark MP4 (requires a same-page browser session and is always re-hosted). 'watermarked' = logo copy, usable as an expiring CDN URL. 'both' = one row per variant.
qualitystringoptionalTarget clean-video quality. 'best' sorts by resolution first, then bitrate. Watermarked copies are single-resolution.
downloadToKvbooleanoptionalStore watermarked video, audio, cover, and slideshow files in the run's Key-Value Store and return stable kvsUrl links. Clean video is always stored because its source URL is session-bound. Set false to return expiring CDN URLs only.
maxFileSizeMbintegeroptionalPer-file size cap. Files above the cap produce a 'too_large' status row instead of a partial download.
maxItemsintegeroptionalMaximum number of unique posts to process. Inputs beyond the cap receive a 'limit_reached' status row.
maxConcurrencyintegeroptionalNumber of posts processed in parallel (1-3). Embed requests are retried with backoff when TikTok rate-limits them.
proxyConfigurationobjectoptionalOptional. The actor uses a direct connection by default and does not require a proxy. Use this only if you want to route requests through Apify Proxy.

Download the published input schema

View complete JSON
{
  "description": "Download TikTok videos (clean or watermarked), audio, covers, slideshow frames, and post metadata. Clean MP4 files are downloaded inside a browser session and re-hosted in Apify Key-Value Store; watermarked/direct assets can be re-hosted or returned as expiring CDN URLs.",
  "properties": {
    "assetTypes": {
      "default": [
        "video"
      ],
      "description": "Assets to produce for each post. 'video' = MP4; 'audio' = TikTok sound; 'cover' = cover image; 'slideshow' = ordered photo frames; 'metadata' = post/author/stats/music row.",
      "editor": "select",
      "items": {
        "enum": [
          "video",
          "audio",
          "cover",
          "slideshow",
          "metadata"
        ],
        "enumTitles": [
          "Video (MP4)",
          "Audio",
          "Cover image",
          "Slideshow frames",
          "Metadata"
        ],
        "type": "string"
      },
      "prefill": [
        "video"
      ],
      "title": "Asset Types",
      "type": "array"
    },
    "downloadToKv": {
      "default": true,
      "description": "Store watermarked video, audio, cover, and slideshow files in the run's Key-Value Store and return stable kvsUrl links. Clean video is always stored because its source URL is session-bound. Set false to return expiring CDN URLs only.",
      "prefill": true,
      "title": "Download Files to Apify Key-Value Store",
      "type": "boolean"
    },
    "maxConcurrency": {
      "default": 3,
      "description": "Number of posts processed in parallel (1-3). Embed requests are retried with backoff when TikTok rate-limits them.",
      "maximum": 3,
      "minimum": 1,
      "prefill": 1,
      "title": "Max Concurrency",
      "type": "integer"
    },
    "maxFileSizeMb": {
      "default": 100,
      "description": "Per-file size cap. Files above the cap produce a 'too_large' status row instead of a partial download.",
      "maximum": 100,
      "minimum": 1,
      "prefill": 100,
      "title": "Max File Size (MB)",
      "type": "integer"
    },
    "maxItems": {
      "default": 1000,
      "description": "Maximum number of unique posts to process. Inputs beyond the cap receive a 'limit_reached' status row.",
      "maximum": 1000,
      "minimum": 1,
      "prefill": 1,
      "title": "Max Posts",
      "type": "integer"
    },
    "postUrls": {
      "description": "TikTok post URLs or IDs. Accepts /@user/video/ID, /@user/photo/ID, /video/ID, /photo/ID, embed URLs (/embed/v2/ID), vm.tiktok.com / vt.tiktok.com / /t/ short links, m.tiktok.com/v/ID.html, and bare numeric post IDs. Duplicates are processed once.",
      "editor": "stringList",
      "items": {
        "type": "string"
      },
      "prefill": [
        "https://www.tiktok.com/@nba/video/7693329153680035102"
      ],
      "title": "Post URLs",
      "type": "array"
    },
    "proxyConfiguration": {
      "description": "Optional. The actor uses a direct connection by default and does not require a proxy. Use this only if you want to route requests through Apify Proxy.",
      "editor": "proxy",
      "title": "Proxy Configuration",
      "type": "object"
    },
    "quality": {
      "default": "best",
      "description": "Target clean-video quality. 'best' sorts by resolution first, then bitrate. Watermarked copies are single-resolution.",
      "editor": "select",
      "enum": [
        "best",
        "1080p",
        "720p",
        "540p",
        "360p",
        "smallest"
      ],
      "enumTitles": [
        "Best (highest resolution)",
        "1080p",
        "720p",
        "540p",
        "360p",
        "Smallest file"
      ],
      "prefill": "540p",
      "title": "Video Quality",
      "type": "string"
    },
    "videoVariant": {
      "default": "clean",
      "description": "'clean' = no-watermark MP4 (requires a same-page browser session and is always re-hosted). 'watermarked' = logo copy, usable as an expiring CDN URL. 'both' = one row per variant.",
      "editor": "select",
      "enum": [
        "clean",
        "watermarked",
        "both"
      ],
      "enumTitles": [
        "Clean (no watermark)",
        "Watermarked",
        "Both variants"
      ],
      "prefill": "clean",
      "title": "Video Variant",
      "type": "string"
    }
  },
  "required": [
    "postUrls"
  ],
  "schemaVersion": 1,
  "title": "TikTok Downloader API 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.

FieldTypeRequiredDescription
postsstringoptionalDataset containing downloaded TikTok assets, post metadata, and status rows.

Download the published output schema

View complete JSON
{
  "actorOutputSchemaVersion": 1,
  "description": "One dataset row per asset (video clean/watermarked, audio, cover, slideshow frame, metadata) plus explicit status rows for unavailable, private, region-blocked, age-gated, duplicate, over-limit, and too-large inputs. Each row carries post identity, variant, quality, MIME type, byte size, dimensions, duration, stable Key-Value Store link, original CDN URL, expiry, and status.",
  "properties": {
    "posts": {
      "description": "Dataset containing downloaded TikTok assets, post metadata, and status rows.",
      "template": "{{links.apiDefaultDatasetUrl}}/items",
      "title": "Downloaded Posts and Assets",
      "type": "string"
    }
  },
  "title": "TikTok Video, Audio & Cover Downloader 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": {
    "assetType": {
      "description": "video, audio, cover, slideshow, metadata, or post for post-level status rows",
      "title": "Asset Type",
      "type": "string"
    },
    "authorId": {
      "description": "TikTok user ID (metadata rows)",
      "title": "Author ID",
      "type": "string"
    },
    "authorNickname": {
      "description": "Display name (metadata rows)",
      "title": "Author Nickname",
      "type": "string"
    },
    "authorUsername": {
      "description": "TikTok username (metadata rows)",
      "title": "Author Username",
      "type": "string"
    },
    "authorVerified": {
      "description": "Whether the author is verified (metadata rows)",
      "title": "Author Verified",
      "type": "boolean"
    },
    "byteSize": {
      "description": "File size in bytes",
      "title": "Byte Size",
      "type": "integer"
    },
    "caption": {
      "description": "Post caption (metadata rows)",
      "title": "Caption",
      "type": "string"
    },
    "collectCount": {
      "description": "Post collect count (metadata rows)",
      "title": "Collect Count",
      "type": "integer"
    },
    "commentCount": {
      "description": "Post comment count (metadata rows)",
      "title": "Comment Count",
      "type": "integer"
    },
    "createTime": {
      "description": "Unix timestamp of the post (metadata rows)",
      "title": "Create Time",
      "type": "integer"
    },
    "downloadedAt": {
      "description": "ISO 8601 timestamp when the asset was stored or metadata was captured",
      "title": "Downloaded At",
      "type": "string"
    },
    "duration": {
      "description": "Video or audio duration in seconds",
      "title": "Duration (s)",
      "type": "number"
    },
    "error": {
      "description": "Human-readable explanation for non-ok status rows",
      "title": "Error",
      "type": "string"
    },
    "expiresAt": {
      "description": "ISO 8601 expiry of the source CDN URL, when signed",
      "title": "Expires At",
      "type": "string"
    },
    "height": {
      "description": "Media height in pixels",
      "title": "Height",
      "type": "integer"
    },
    "imageCount": {
      "description": "Number of slideshow images (metadata rows)",
      "title": "Image Count",
      "type": "integer"
    },
    "imageHeight": {
      "description": "Slideshow frame height",
      "title": "Image Height",
      "type": "integer"
    },
    "imageWidth": {
      "description": "Slideshow frame width",
      "title": "Image Width",
      "type": "integer"
    },
    "kvsKey": {
      "description": "Key in Apify Key-Value Store",
      "title": "KVS Key",
      "type": "string"
    },
    "kvsUrl": {
      "description": "Stable public Apify Key-Value Store URL for the downloaded file",
      "title": "KVS URL",
      "type": "string"
    },
    "likeCount": {
      "description": "Post like/digg count (metadata rows)",
      "title": "Like Count",
      "type": "integer"
    },
    "mimeType": {
      "description": "MIME type of the stored file",
      "title": "MIME Type",
      "type": "string"
    },
    "musicAuthor": {
      "description": "Sound author (metadata rows)",
      "title": "Music Author",
      "type": "string"
    },
    "musicDuration": {
      "description": "Sound duration in seconds (metadata rows)",
      "title": "Music Duration",
      "type": "integer"
    },
    "musicId": {
      "description": "TikTok sound ID (metadata/audio rows)",
      "title": "Music ID",
      "type": "string"
    },
    "musicTitle": {
      "description": "Sound title (metadata/audio rows)",
      "title": "Music Title",
      "type": "string"
    },
    "ordinal": {
      "description": "0-based slideshow frame index",
      "title": "Ordinal",
      "type": "integer"
    },
    "originalUrl": {
      "description": "Source TikTok CDN URL (expires in about 48 hours)",
      "title": "Original URL",
      "type": "string"
    },
    "playCount": {
      "description": "Post play count (metadata rows)",
      "title": "Play Count",
      "type": "integer"
    },
    "postId": {
      "description": "Unique TikTok post ID",
      "title": "Post ID",
      "type": "string"
    },
    "postType": {
      "description": "video or slideshow",
      "title": "Post Type",
      "type": "string"
    },
    "postUrl": {
      "description": "Canonical URL to the TikTok post",
      "title": "Post URL",
      "type": "string"
    },
    "quality": {
      "description": "Selected quality label (e.g. 1080p, 720p, 540p)",
      "title": "Quality",
      "type": "string"
    },
    "requiresSession": {
      "description": "True when the source URL only works with the extracting browser session (clean video)",
      "title": "Requires Session",
      "type": "boolean"
    },
    "shareCount": {
      "description": "Post share count (metadata rows)",
      "title": "Share Count",
      "type": "integer"
    },
    "status": {
      "description": "ok, not_found, private, region_blocked, login_required, blocked, unsupported_url, short_link_dead, no_video, no_slideshow, no_audio, no_cover, no_assets, download_failed, too_large, duplicate, or limit_reached",
      "title": "Status",
      "type": "string"
    },
    "variant": {
      "description": "Video variant: clean or watermarked",
      "title": "Variant",
      "type": "string"
    },
    "width": {
      "description": "Media width in pixels",
      "title": "Width",
      "type": "integer"
    }
  },
  "title": "TikTok Downloads",
  "views": {
    "issues": {
      "display": {
        "component": "table",
        "properties": {
          "assetType": {
            "format": "text",
            "label": "Asset"
          },
          "error": {
            "format": "text",
            "label": "Error"
          },
          "postId": {
            "format": "text",
            "label": "Post ID"
          },
          "postUrl": {
            "format": "link",
            "label": "Post URL"
          },
          "status": {
            "format": "text",
            "label": "Status"
          },
          "variant": {
            "format": "text",
            "label": "Variant"
          }
        }
      },
      "title": "Status Rows",
      "transformation": {
        "fields": [
          "postId",
          "postUrl",
          "assetType",
          "variant",
          "status",
          "error"
        ]
      }
    },
    "overview": {
      "display": {
        "component": "table",
        "properties": {
          "assetType": {
            "format": "text",
            "label": "Asset"
          },
          "byteSize": {
            "format": "number",
            "label": "Bytes"
          },
          "downloadedAt": {
            "format": "text",
            "label": "Downloaded At"
          },
          "kvsUrl": {
            "format": "link",
            "label": "Download"
          },
          "mimeType": {
            "format": "text",
            "label": "MIME"
          },
          "originalUrl": {
            "format": "link",
            "label": "Source"
          },
          "postId": {
            "format": "text",
            "label": "Post ID"
          },
          "postUrl": {
            "format": "link",
            "label": "Post URL"
          },
          "quality": {
            "format": "text",
            "label": "Quality"
          },
          "status": {
            "format": "text",
            "label": "Status"
          },
          "variant": {
            "format": "text",
            "label": "Variant"
          }
        }
      },
      "title": "Downloaded Assets",
      "transformation": {
        "fields": [
          "postId",
          "postUrl",
          "assetType",
          "variant",
          "quality",
          "mimeType",
          "byteSize",
          "status",
          "kvsUrl",
          "originalUrl",
          "downloadedAt"
        ]
      }
    }
  }
}

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 Video, Audio & Cover Downloader

Download TikTok posts as clean no-watermark MP4, watermarked MP4, sound, cover images, slideshow frames, and post metadata. Each file can be re-hosted in Apify Key-Value Store with a stable public link, and every input gets a dataset row — including posts that are deleted, private, region-blocked, age-gated, duplicated, or too large to download.

No TikTok account, cookies, API key, or proxy setup is required.

What you get

  • One row per asset: video variant, audio, cover, slideshow frame, or metadata
  • Explicit status rows instead of silent skips
  • Clean MP4 (no watermark) downloaded inside the page session and re-hosted to Apify storage
  • Watermarked MP4, covers, audio, and slideshow images returned as stable KV links and/or expiring CDN URLs
  • Resolution-first quality selection (best, 1080p, 720p, 540p, 360p, smallest)
  • Post and author metadata: caption, create time, stats, sound details, post type
  • Short-link support (vm.tiktok.com, vt.tiktok.com, /t/) and embed/bare-ID inputs
  • Duplicate detection, maxItems, maxFileSizeMb, and 1–3 way concurrency

How it works

TikTok exposes two different media paths, and this actor uses both:

  1. Embed fast path — the public embed page returns the watermarked MP4, cover, sound, slideshow images, author, stats, and caption without a browser or login.
  2. Browser page session — the clean playAddr URL is bound to first-party cookies from the same page load and returns 403 when fetched outside that session. The actor opens the post in Chromium, downloads the selected clean stream inside the session, and stores it in Apify Key-Value Store so the output link keeps working.

Watermarked and direct assets are downloaded to Key-Value Store when downloadToKv is true. When it is false, their source URLs are returned instead. Clean video is always downloaded and re-hosted because a bare source URL would not work for you.

Input

Field Type Default Description
postUrls array of strings required Canonical post URLs, short links, embed URLs, or numeric post IDs. Duplicates are processed once.
assetTypes multi-select ["video"] video, audio, cover, slideshow, metadata.
videoVariant select clean clean, watermarked, or both.
quality select best best sorts by resolution then bitrate. 1080p, 720p, 540p, 360p, smallest target the closest available stream. Watermarked copies are single-resolution.
downloadToKv boolean true Store watermarked video, audio, cover, and slideshow files and return kvsUrl. Clean video is always stored.
maxFileSizeMb integer 100 Per-file cap (1–100 MB). Larger files produce a too_large row.
maxItems integer 1000 Maximum unique posts to process (1–1000). Extra inputs get a limit_reached row.
maxConcurrency integer 3 Posts processed in parallel (1–3).
proxyConfiguration object none Optional. The actor uses a direct connection by default.

Example — one clean video at 540p

{
  "postUrls": ["https://www.tiktok.com/@nba/video/7693329153680035102"],
  "assetTypes": ["video"],
  "videoVariant": "clean",
  "quality": "540p",
  "downloadToKv": true,
  "maxItems": 1
}

Example — both video variants, cover, and metadata

{
  "postUrls": ["https://www.tiktok.com/@nba/video/7693329153680035102"],
  "assetTypes": ["video", "cover", "metadata"],
  "videoVariant": "both",
  "quality": "720p",
  "downloadToKv": true
}

Example — slideshow frames and sound

{
  "postUrls": ["https://www.tiktok.com/@khaby.lame/photo/7574844184952081686"],
  "assetTypes": ["slideshow", "audio", "metadata"],
  "downloadToKv": true
}

Example — URL-only mode for direct assets

{
  "postUrls": ["https://www.tiktok.com/@nba/video/7693329153680035102"],
  "assetTypes": ["audio", "cover"],
  "downloadToKv": false
}

Output

Each dataset row contains the non-empty fields that apply:

  • postId, postUrl, postType
  • assetType: video, audio, cover, slideshow, metadata, or post for post-level status rows
  • variant: clean or watermarked for video
  • quality: selected quality label
  • ordinal: slideshow frame index
  • mimeType, byteSize, width, height, duration
  • kvsKey, kvsUrl for stored files
  • originalUrl, expiresAt for the source CDN URL
  • downloadedAt, requiresSession
  • status, error
  • Metadata rows add caption, createTime, author fields, play/like/comment/share/collect counts, music fields, and imageCount

Status values

Status Meaning
ok At least one requested asset or metadata row delivered
not_found Deleted, removed, or unavailable post
private Private account or friends-only post
region_blocked Not available in the current region
login_required Age-gated or login-gated post
blocked TikTok bot wall or rate limit after retries
unsupported_url Input is not a recognizable TikTok post
short_link_dead Short link redirected to a homepage/profile, not a post
no_video Video requested for a slideshow post
no_slideshow Slideshow requested for a video post
no_audio No sound track exposed
no_cover No cover image exposed
no_assets Post resolved but none of the requested assets were available
download_failed CDN download or Key-Value Store write failed
too_large File exceeds maxFileSizeMb
duplicate Same post ID appeared earlier in the input
limit_reached maxItems cap reached before this input was processed

URL expiry and storage

  • TikTok CDN URLs (originalUrl) are signed and expire in about 48 hours (some music URLs expire within 24 hours). They are useful for traceability, not long-term hosting.
  • kvsUrl points to the run's Apify Key-Value Store and lasts for that store's retention period. Download important files to your own storage.
  • Clean video source URLs only work with the extracting page session (requiresSession: true). That is why the actor always downloads and re-hosts clean video instead of selling a bare URL.

Limits and behaviour

  • Caps: 1–1000 posts per run, 3 concurrent posts, 100 MB per file.
  • Deduplication: the first occurrence of a post ID is processed; later occurrences get a duplicate row.
  • Clean video: requires a browser session; if the page is blocked, the actor returns a status row for the clean asset while still delivering metadata/watermarked assets when the embed fast path succeeded.
  • Region, private, and age-gated posts: no login and no user cookies are used. Posts that require either are reported with a status row rather than silently omitted.
  • Field drift: the parser accepts both imagePost.images (modern page data) and imagePostInfo.displayImages (embed/legacy), and MIME types are taken from the CDN response rather than assumed.
  • Watermarked resolution: TikTok exposes one watermarked copy per post, so quality affects clean video only.

FAQ

Do I need a TikTok account or cookies? No. The actor uses public pages and browser-generated first-party cookies only.

Why can't I get a no-watermark URL without downloading? TikTok's clean playAddr returns 403 text/html unless it is fetched with cookies from the same page session. The actor downloads the file in that session and re-hosts it.

How long do links stay valid? kvsUrl lasts for the Key-Value Store retention period. originalUrl is a signed CDN URL that expires in about 48 hours.

What happens to posts that cannot be downloaded? They produce a status row with status and error, so you can audit the run instead of diffing post IDs.

Are short links supported? Yes. vm.tiktok.com, vt.tiktok.com, and /t/ links are resolved with an HTTP redirect. A dead link gets short_link_dead.

Can I use a proxy? It is optional. The actor is direct by default. If you want to route requests through Apify Proxy, select a proxy configuration in the input.

Why is a clean video row missing on a slideshow? Slideshows have no video file. Request slideshow or audio instead; a no_video status row is emitted when video is requested.

Is this affiliated with TikTok? No. It is an independent tool for publicly available TikTok media. Only download content you have the right to use.

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.

Open the step-by-step Python guide →

Source build 0qqLJHUzNNtm8LCyD. Documentation is regenerated from the default published build; private drafts are not included.