---
title: "TikTok Music Posts API"
method: GET
path: "/v1/tiktok/music-posts"
tags: ["TikTok"]
---

# TikTok Music Posts API

`GET /v1/tiktok/music-posts`

## Request

- Base URL: `https://api.captapi.com`
- URL: `https://api.captapi.com/v1/tiktok/music-posts`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

List TikTok videos that use a specific sound — caption, author, exact engagement, canonical hashtags, and mentions, with cursor pagination.

Paste a TikTok music/sound URL and get the public videos that use that sound as structured JSON, straight from TikTok's own music feed (native only — there is no backup path). TikTok serves this feed in short pages of a few videos each, so a call returns what lands within ~35s plus a nextCursor; keep paging to collect more. pagination says where you stand: cursor (more pages — hasMore true), end (TikTok's feed for this sound is exhausted — hasMore false), unavailable (cannot tell — hasMore null, never a false "no more posts"). Coverage is limited to what TikTok's public feed exposes, which can be far below the count shown in the app. Every row has one schema: permalink is always url, author is the full eight-key card, and caption / publishedAt / thumbnailUrl / durationSeconds / mediaUrlsExpireAt / hasWatermark / locationCreated are always keyed. Unread engagement counters are null with *IsApproximate: null — never 0 flagged exact. limit is 1–50 (outside that is a 400). When TikTok's feed refuses us, the answer is 503 UPSTREAM_UNAVAILABLE with Retry-After and the real elapsed time (reason native_unavailable, page_miss or timeout) at 0 credits. Photomode covers are mediaType=photo with a /photo/ permalink. Flat 2 credits per successful call.

Docs: https://captapi.com/apis/tiktok-music-posts

## Query parameters

- `url` string, required
- `limit` integer
- `cursor` string
- `cache` boolean

## Response `200`

Success. The data object for this endpoint.

- object
  - `success` unknown, required
  - `data` object, required
    - `url` string: Canonical watch permalink. Always this key — never videoUrl for a /@user/video/ id link.
    - `musicId` string: Envelope-level sound id (single-valued across the page — not repeated per row).
    - `musicName` string: Envelope-level sound title (single-valued across the page — not repeated per row).
    - `totalReturned` integer: Rows on this page. Can be below limit: TikTok serves this feed a few videos per page, and a call returns what lands within ~35s.
    - `posts` object[]
      - `platform` string: Platform identifier for this response (matches the endpoint's platform).
      - `url` string: Canonical watch permalink. Always this key — never videoUrl for a /@user/video/ id link.
      - `id` string: Id of this posts item.
      - `caption` string: Post or creative caption when the platform exposes one.
      - `publishedAt` string: Publish date (ISO 8601) when the platform exposes an absolute timestamp.
      - `durationSeconds` number: Length in seconds for this item (full media length, or a segment span when the endpoint documents a start/end).
      - `thumbnailUrl` string: Thumbnail image URL.
      - `mediaType` string: Media type label for this item (platform-specific enum).
      - `width` integer: Width in pixels.
      - `height` integer: Height in pixels.
      - `videoUrl` string: Playable CDN URL when TikTok exposes one. A watch permalink is moved to url, not left here.
      - `downloadUrl` string: CDN media URL when present (not a dedicated download API).
      - `downloadUrlNoWatermark` unknown
      - `hasWatermark` boolean: Has watermark. Example: true.
      - `mediaUrlsExpireAt` string: ISO-8601 UTC earliest expiry across signed media URLs in this response (expire= / x-expires / TikTok hex path timestamp). Null when no stamp is parseable — never a guess.
      - `author` object: Author name or handle.
        - `id` string, nullable: Id of this posts item.
        - `secUid` string, nullable
        - `username` string
        - `displayName` string
        - `url` string: Canonical watch permalink. Always this key — never videoUrl for a /@user/video/ id link.
        - `followers` unknown
        - `verified` boolean
        - `profileImage` string
        - `region` string
      - `engagement` object: Engagement metrics for the item.
        - `views` integer
        - `likes` integer
        - `comments` integer
        - `shares` integer
        - `saves` integer
        - `viewsIsApproximate` boolean
        - `likesIsApproximate` boolean
        - `commentsIsApproximate` boolean
        - `sharesIsApproximate` boolean
        - `savesIsApproximate` boolean
        - `downloads` integer
      - `hashtags` string[]: Hashtags extracted from the text.
      - `mentions` unknown[]: Accounts mentioned in the text.
        - unknown
      - `musicAuthor` string: Music author. Example: "Khabane lame".
      - `locationCreated` string: ISO country where the TikTok video was posted/served (item locationCreated). Not the creator's home country — use authorRegion or /tiktok/profile-region for that.
      - `descLanguage` string, nullable: Language code TikTok assigns to the video caption when exposed.
      - `isAd` boolean: Whether the item is a paid promotion.
      - `isPaidPartnership` boolean: Is paid partnership. Example: false.
    - `nextCursor` string: Pass back as cursor for the next page of videos using this sound. Present only when pagination is cursor.
    - `hasMore` boolean: true when pagination is cursor, false when it is end, null when it is unavailable. Breaking change (Oct 2026): was always a boolean, and false used to also mean "cannot page".
    - `pagination` string: "cursor" — more pages, pass nextCursor. "end" — TikTok's public feed for this sound is exhausted. "unavailable" — the page cannot tell whether more exist (hasMore null). Always keyed.
    - `source` unknown

## Other responses

- `400`: Bad request: wrong platform URL, unknown endpoint, or an invalid parameter value. Not billed.
- `401`: Missing, invalid or revoked API key. Not billed.
- `402`: Not enough credits for this request. Not billed.
- `404`: The resource does not exist or is not public. Not billed.
- `422`: A required parameter is missing or has the wrong type. Not billed.
- `429`: Rate limit reached. Wait for Retry-After seconds. Not billed.
- `502`: The platform could not be reached or returned nothing usable. Retryable, not billed. 503 and 504 use the same envelope.

---

[API](https://skmtc.dev/captapi/apis/captapi-api.md) · [All operations](https://skmtc.dev/captapi/apis/captapi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/captapi/apis/captapi-api/revisions/c9b9ac5ff1bd?raw)
