Posts
List TikTok videos: a creator's, a hashtag's, a sound's, a playlist's, or the explore feed.
GET | POST /v1/tiktok/postsSend parameters as a query string with GET, or as a JSON body with POST. Both are equivalent.
What to Pass
| Pass | Reads | Notes |
|---|---|---|
username or userId | A creator's videos | type: posts (default), reposts, likes (when public) |
hashtag | Videos under a hashtag | A name, or its numeric id (saves a lookup) |
sound | Videos using a sound | |
playlist | The videos in a playlist | |
| nothing | The explore feed | category (default 120) |
Pass one source per call. Every identifier also takes the page URL.
Parameters
| Parameter | Type | Required | Notes |
|---|---|---|---|
category | string | Default feed only: explore category id (default 120). | |
cursor | string | Opaque cursor from the previous page's cursor. Pass it alone for the next page. | |
hashtag | string | Videos under a hashtag: its name, or its numeric id (saves the lookup). A hashtag that is itself a number takes its # (#2024). | |
limit | integer 1–30 | Items per page, 1–30. | |
playlist | string | Videos in a playlist: id or URL (…/playlist/-<id>). | |
sound | string | Videos using a sound: sound id or URL (…/music/-<id>). | |
type | enum | username/userId: the creator's posts (default), reposts or likes. posts reposts likes | |
userId | string | Creator secUid. Pass it instead of a username to save the lookup (1 unit instead of 2). | |
username | string | Creator @handle (with or without @), or the profile URL. |
Request
curl "https://gateway.apinoa.com/v1/tiktok/posts?username=tiktok&limit=3" \
-H "x-api-key: $APINOA_API_KEY"Response
Returns Page of Post in data. A real response, shortened: arrays keep their first entries and long text is cut.
{
"success": true,
"data": {
"platform": "tiktok",
"items": [
{
"platform": "tiktok",
"id": "7700009319382650142",
"url": "https://www.tiktok.com/@tiktok/video/770000931938…",
"author": {
"platform": "tiktok",
"id": "107955",
"handle": "tiktok",
"displayName": "TikTok",
"url": "https://www.tiktok.com/@tiktok",
"avatarUrl": "https://p19-common-sign.tiktokcdn-us.com/tos-usea…",
"verified": true,
"counts": {
"followers": 96400000,
"following": 1,
"posts": 1512
},
"ext": {
"secUid": "MS4wLjABAAAAv7iSuuXDJGDvJkmH_vz1qkDZYo1apxgzaxdBS…",
"signature": "Your next discovery is waiting on TikTok.",
"totalLikes": 466000000,
"likesGiven": 4377
}
},
"text": "The best part of searching a new city on TikTok?…",
"createdAt": "2026-10-23T23:29:02.000Z",
"lang": "en",
"media": [
{
"type": "video",
"url": "https://www.tiktok.com/aweme/v1/play/?faid=1988&f…",
"width": 720,
"height": 1280,
"thumbnailUrl": "https://p19-common-sign.tiktokcdn-us.com/tos-usea…",
"durationSec": 107,
"variants": [
{
"url": "https://www.tiktok.com/aweme/v1/play/?faid=1988&f…",
"width": 720,
"height": 1280,
"bitrate": 740138,
"contentType": "video/mp4"
}
],
"ext": {
"playAddr": "https://v16-webapp-prime.us.tiktok.com/video/tos/…",
"downloadAddr": "https://v16-webapp-prime.us.tiktok.com/video/tos/…",
"dynamicCover": "https://p19-common-sign.tiktokcdn-us.com/tos-usea…",
"definition": "720p",
"videoQuality": "normal",
"ratio": "720p",
"codec": "h264",
"format": "mp4",
"bitrate": 740138,
"sizeBytes": 9949494,
"loudness": -19.9,
"peak": 1,
"hasOriginalAudio": true,
"autoCaption": true,
"bitrateVariants": [
{
"gearName": "normal_720_0",
"fps": 23,
"codec": "h264",
"sizeBytes": 9949494
}
],
"subtitles": [
{
"lang": "eng-US",
"langId": "2",
"url": "https://v16m-webapp.tiktokcdn-us.com/be8291ee2919…",
"format": "webvtt",
"source": "ASR"
}
]
}
}
],
"metrics": {
"likes": 2235,
"comments": 553,
"shares": 144,
"views": 122800,
"reposts": 0,
"saves": 132
},
"entities": {
"mentions": [
{
"handle": "morimatcha__",
"id": "7547085538516485175"
}
]
},
"audio": {
"id": "7700009421400869662",
"title": "original sound",
"artist": "TikTok",
"url": "https://v16m.tiktokcdn-us.com/b9eda378f913298c1de…"
},
"ext": {
"music": {
"original": true,
"coverUrl": "https://p19-common-sign.tiktokcdn-us.com/tos-usea…",
"durationSec": 107,
"isCommerceMusic": true,
"appleMusicId": "1543888610",
"spotifyId": "5Cf5U4MLpSJQb29IqY8bWA"
},
"duetEnabled": true,
"stitchEnabled": true
}
}
],
"cursor": "z3_ejXLXnHrW_fwkl8jd8OBVtLZI0s7eC6UysxOBxhQMNFiYF…"
}
}Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_CURSOR | The cursor is not one this operation returned. Start again without it. |
| 400 | INVALID_PARAMS | A parameter is missing, unknown or out of range. The message names it. |
| 401 | UNAUTHORIZED | The x-api-key header is missing, or the key is revoked or unknown. |
| 402 | INSUFFICIENT_BALANCE | The balance does not cover this call. Top up in the dashboard. |
| 404 | NOT_FOUND | The account, post or group does not exist, or is private, deleted or age-restricted. |
| 429 | MARKETPLACE_SATURATED | Too many concurrent calls. Retry after the Retry-After seconds. |
| 502 | UPSTREAM_ERROR | The platform answered with something unusable. Retry with backoff. |
Every code is listed in Errors. Failed calls are not billed.
Pricing
Price $0.001 per call, plus $0.001 for each extra call it makes — at most 1 more, so $0.002 in total. List price; the rate steps down above 1,000 calls a day.
Notes
userIdis the creator'ssecUid. Passing it instead ofusernamesaves a lookup: 1 unit instead of 2.