TikTok API endpoint
Returns one page of an MV channel feed, the app's music-video ("MV") tab. The upstream is `/aweme/v1/mv/aweme/`; `mv_id` is a small numeric CHANNEL index, NOT a video id — measured ids 0-10 each returned a 15-video page of full aweme objects (1.05-1.24 MB), while 100 returned a valid empty page and a real aweme id returned an empty list. The server's page size is 15 and `count` was measured IGNORED (`count=5` and `count=10` both returned 15 items), so `count` is not exposed; page with `cursor`. The returned `cursor` is a reusable next-page token (measured page 1 `cursor: 18, has_more: 1`; `cursor=18` returned a fresh page with `cursor: 38, has_more: 1`). The envelope's `top_awemes` (pinned entries), `original_aweme_id`, `page_extra` and `extra`/`log_pb` are kept as measured. Measured 2026-10-22, A missing or non-numeric `mv_id` is a 400; an unknown numeric channel is a valid empty page.
/tiktok/mobile/mv/videosOne page of the app's MV tab — the music-video channel feed. The upstream is GET /aweme/v1/mv/aweme/, captured
from the running 47.4.3 app and reproduced end-to-end against the live gateway.
mv_id is a channel index, not a video id. Measured ids 0, 1, 2, …, 10 each returned a 15-video page of
full aweme objects (1.05–1.24 MB per page). 100 returned a valid empty page, and a real aweme id
(7681236055831416084) also returned an empty list — so mv_id addresses an MV channel, and every page's videos
are ordinary full video objects (description, author, statistics, media URLs, music, anchors, …).
Real cursor paging, fixed page size. The server returns 15 videos per page and count was measured ignored
(count=5 and count=10 both returned the same 15 items), so the API does not expose count. The returned
cursor is a reusable next-page token: measured page 1 cursor: 18, has_more: true, and cursor=18 returned a
fresh page with cursor: 38, has_more: true. Stop when has_more is false.
It answers on the core
aggr16-normal.tiktokv.us / api16-normal-useast5.tiktokv.us pair.
Query parameters:
mv_id: required. The numeric MV channel index (measured 0–10 populated, 100 empty).cursor: optional. The cursor from the previous response; 0/omitted is the first page.Errors:
mv_id is missing or not numeric, or cursor is negative.Measured 2026-10-22:
| call | result |
|---|---|
mv_id=0 / 1 / 2 … 10 | 15 videos per page, 1.05–1.24 MB, cursor 16–24, has_more: true |
mv_id=1&cursor=18 | next 15 videos, cursor: 38, has_more: true (fresh ids) |
mv_id=1&count=5 | still 15 items (count ignored) |
mv_id=100, mv_id=-1 | valid empty page (aweme_list: []) |
mv_id=7681236055831416084 (a real aweme id) | empty page — the id namespace is the channel index |
bare, mv_id=abc | upstream status 5 "Invalid parameters" → 400 |
| shipped-service canary | page1=15 cursor=18 has_more=true page2=15 has_more=true |
Example request:
GET /api/v1/tiktok/mobile/mv/videos?mv_id=1
Example response (truncated):
{
"code": 200,
"msg": "OK",
"data": {
"mv_id": "1",
"aweme_list": [
{
"aweme_id": "7523859329968016647",
"desc": "",
"author": {"unique_id": "..."},
"statistics": {"digg_count": 0, "comment_count": 0, "play_count": 0},
"music": {"title": "original sound - ..."},
"video": {"play_addr": {"url_list": ["..."]}}
}
],
"item_count": 15,
"cursor": 18,
"has_more": true,
"top_awemes": [{"aweme_id": "7505576833954385158"}],
"page_extra": {"pagination_list": null, "downrank_list": null},
"host": "aggr16-normal.tiktokv.us",
"fetched_at": "2026-10-22T05:52:11Z"
}
}
Notes for callers:
top_awemes holds the channel's pinned entries and is separate from the paged aweme_list.page_extra.pagination_list / downrank_list are the app's own paging controls; they were null on the measured
pages./api/v1/tiktok/mobile/music/posts; for the sound charts use
/api/v1/tiktok/mobile/music/trending and /api/v1/tiktok/mobile/music/pick.| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| x-api-key (header) | string | Yes | API key required | ||
| mv_id | string | Yes | MV channel index (small integer; measured 0-10 populated, 100 empty) | 1 | |
| cursor | integer | No | Next-page token from the previous response (0 = first page) | 0 |
curl -X GET "https://api.crawlora.net/api/v1/tiktok/mobile/mv/videos?mv_id=1" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"mv_id": "1",
"aweme_list": [
{
"aweme_id": "7523859329968016647",
"desc": "",
"author": {
"unique_id": "..."
},
"statistics": {
"digg_count": 0,
"comment_count": 0,
"play_count": 0
},
"music": {
"title": "original sound - ..."
},
"video": {
"play_addr": {
"url_list": [
"..."
]
}
}
}
],
"item_count": 15,
"cursor": 18,
"has_more": true,
"top_awemes": [
{
"aweme_id": "7505576833954385158"
}
],
"page_extra": {
"pagination_list": null,
"downrank_list": null
},
"host": "aggr16-normal.tiktokv.us",
"fetched_at": "2026-10-22T05:52:11Z"
}
}Request schema
No body schema
Response schema
#/definitions/tiktokmobile.mvFeedResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| aweme_list | array | No | ||||
| cursor | integer | No | 18 | |||
| extra | unknown | No | ||||
| fetched_at | string | No | ||||
| has_more | boolean | No | true | |||
| host | string | No | aggr16-normal.tiktokv.us | |||
| item_count | integer | No | 15 | |||
| log_pb | unknown | No | ||||
| mv_id | string | No | 1 | |||
| original_aweme_id | string | No | ||||
| page_extra | unknown | No | ||||
| top_awemes | array | No |
| Status | Description | Schema |
|---|---|---|
| 400 | Invalid input | #/definitions/app.Response |
| 429 | Rate limit exceeded | #/definitions/app.Response |
| 500 | Internal server error | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/tiktok/mobile/mv/videos?mv_id=1" \
-H "x-api-key: $CRAWLORA_API_KEY"