TikTok API endpoint
Searches TikTok's effect catalogue by `keyword`, returning the app's full effect objects (`name`, `hint`, `icon_url`, `file_url`, `effect_id`, `types`, `tags`, `parent`/`children`, `effect_type`, `music`, `source`, `designer_id`, `schema`). The upstream is `/aweme/v1/search/effect/`; the page is unfolded to the top level (`effects`, `cursor`, `has_more`, `search_id`, `use_hot`, plus `bind_effects`/`collection` on some queries). Paging is real but needs BOTH halves of the token: pass the previous response's `cursor` and `search_id` together (measured: page 1 `cursor: 100`, page 2 with `cursor=100&search_id=...` returned the final effect with `has_more: false`; a cursor without its `search_id` returns an empty page, which the service rejects as a 400). `count` and `offset` were measured as no-ops. Measured 2026-10-21 with the pure-Go (device-free) signer: `keyword=green screen` -> 6 effects (11,831 B) + 1 on page 2, `green` -> 2, `字幕` -> 4; a keyword with no matches is a valid empty page. The route is not signature-gated, so it does not need the device-backed signer.
/tiktok/mobile/search/effectsSearches TikTok's effect/sticker catalogue by keyword, as the app's effect picker does. The upstream is
GET /aweme/v1/search/effect/, captured from the running 47.4.3 app and reproduced end-to-end against the live
gateway.
What an effect carries. Each effects entry is the app's full effect object: name, hint, icon_url,
file_url, id/effect_id, types, tags, parent/children, effect_type, music, source,
designer_id and schema. The page is unfolded to the top level (effects, cursor, has_more, search_id,
use_hot), with bind_effects/collection present only on some queries.
Paging needs both halves of the token. The upstream wraps results in a search session: to fetch the next page
you must send the previous response's cursor and search_id together. Sending a cursor without its
search_id returns an empty page, so this API rejects that combination with a 400 instead of silently returning
nothing. count and offset are shape-parity parameters the server was measured to ignore — the server chooses
the page size.
Device-free. The pure-Go placeholder signer returned the same results, so a deployment needs
TIKTOK_MOBILE_PARAMS but not the device-backed signer (TIKTOK_MOBILE_SIGNER_URL). It answers on the core
aggr16-normal.tiktokv.us / api16-normal-useast5.tiktokv.us pair.
Query parameters:
keyword: required. Effect name or text; a keyword with no matches is a valid empty page.cursor: optional. The cursor from the previous response; 0/omitted is the first page.search_id: optional. The search_id from the previous response; required whenever cursor is set.count: optional. Accepted for shape parity and validated, but the server was measured to ignore it.Errors:
keyword is missing, cursor/count are out of range, or cursor was sent without search_id.| call | result |
|---|---|
keyword=green screen | 11,831 B; 6 effects on page 1, cursor: 100, has_more: true, search_id present |
page 2 = cursor=100 + that search_id | 1 more effect, cursor: 200, has_more: false (the full result set) |
cursor without search_id | empty page — rejected locally as 400 |
keyword=green / glitch | 2 effects each |
keyword=字幕 | 4 effects (non-Latin script) |
| bare keyword | 512 B; valid empty page (effects: null) |
count=5 / 20 / 50, offset=20, count=1 | identical pages (parameters ignored) |
| shipped-service canary | page1=6 cursor=100 has_more=true → page2=1 has_more=false |
Example request:
GET /api/v1/tiktok/mobile/search/effects?keyword=green%20screen
Example response (truncated):
{
"code": 200,
"msg": "OK",
"data": {
"effects": [
{
"name": "Green Screen Brush",
"hint": "",
"effect_id": "123",
"types": ["Green Screen"],
"tags": ["green screen", "background"],
"icon_url": {"url_list": ["https://p16-...tiktokcdn-us.com/..."] },
"file_url": {"uri": "...", "url_list": ["..."]},
"designer_id": "456",
"source": "artist",
"schema": ""
}
],
"cursor": 100,
"has_more": true,
"search_id": "20261021173221C8185FF1D4A1062AD97C",
"use_hot": false,
"status_code": 0,
"status_msg": ""
}
}
Notes for callers:
keyword plus the previous cursor and search_id; stop when has_more is
false.use_hot: true marks the app's hot-fallback list (returned when the query has no exact matches).| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| x-api-key (header) | string | Yes | API key required | ||
| keyword | string | Yes | Effect name or text, e.g. green screen | green screen | |
| count | integer | No | Accepted for shape parity; the server was measured to ignore it | 20 | |
| cursor | integer | No | Next-page token from the previous response (0 = first page) | 100 | |
| search_id | string | No | Search-session token from the previous response; required together with cursor | 20261021173221C8185FF1D4A1062AD97C |
curl -X GET "https://api.crawlora.net/api/v1/tiktok/mobile/search/effects?keyword=green+screen&count=10" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"effects": [
{
"name": "Green Screen Brush",
"hint": "",
"effect_id": "123",
"types": [
"Green Screen"
],
"tags": [
"green screen",
"background"
],
"icon_url": {
"url_list": [
"https://p16-...tiktokcdn-us.com/..."
]
},
"file_url": {
"uri": "...",
"url_list": [
"..."
]
},
"designer_id": "456",
"source": "artist",
"schema": ""
}
],
"cursor": 100,
"has_more": true,
"search_id": "20261021173221C8185FF1D4A1062AD97C",
"use_hot": false,
"status_code": 0,
"status_msg": ""
}
}Request schema
No body schema
Response schema
#/definitions/tiktokmobile.searchEffectsResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| bind_effects | unknown | No | ||||
| collection | unknown | No | ||||
| cursor | integer | No | 100 | |||
| effects | array | No | ||||
| has_more | boolean | No | true | |||
| search_id | string | No | 20261021173221C8185FF1D4A1062AD97C | |||
| status_code | integer | No | 0 | |||
| status_msg | string | No | ||||
| use_hot | boolean | No | false |
| Status | Description | Schema |
|---|---|---|
| 400 | Invalid input, including a cursor sent without its search_id | #/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/search/effects?keyword=green+screen&count=10" \
-H "x-api-key: $CRAWLORA_API_KEY"