Skip to main content
POST
Submit a TikTok keyword search (async)
Start an asynchronous TikTok keyword search and get a task_id back immediately.

Overview

This endpoint runs an actual keyword search across TikTok (not a single profile) and returns multiple matching videos. It is asynchronous: the search runs in a background worker, and you poll GET /tiktok/search/{task_id} for cursor-paginated results. Results are retained for ~1 hour. Results are returned sorted by published_at descending (newest first) across pagination, full retrieval, and the signed download_url payload — unless you set sort_by, in which case that order is kept.
This is different from the TikTok Profile scrape, which walks a single account’s videos. Use this endpoint to discover videos across TikTok by keyword.

Billing

Charges happen in the background worker and are disclosed on the polling endpoint (see below), not here.
  • Billing is pages_fetched × residential_request. No search_request is billed for TikTok keyword search.
  • parallel_search_slices scales the cost linearly. By default (1) the search runs a single paginated query chain, naturally capped at roughly 115–140 items by TikTok. Setting it to 2..4 runs that many concurrent chains and dedups by video id, lifting the ceiling — but an N-slice request bills up to N× the residential pages of a single search. Extra slices help most on searches without a date window: with published_within set, every slice searches the same window and can return largely the same videos.
Usage disclosure: this endpoint does not accept include_usage. Because billing happens after the 202 response is sent, there is nothing to disclose at submit time. Pass include_usage=true on GET /tiktok/search/{task_id} instead — it replays the final charges once task_status=completed.

Request Parameters

Diminishing returns on slices: on a representative query without a date window, 2 slices yield ~+43% unique items, 3 slices ~+22%, and 4 slices ~+13% — so 4 already saturates TikTok’s natural ~480-item dedup ceiling for most queries.

Sorting and date windows

sort_by and published_within are applied by TikTok itself, before VidNavigator’s own filters (after_datetime, min_likes, …). Using them well returns more matching videos per billed page. When sort_by is omitted, results are returned newest first, and the search is ordered to fit your filters:
  • after_datetime or before_datetime set → the search runs newest first and stops once it passes after_datetime
  • only min_likes or min_views set → the search runs most liked first
When published_within is omitted and after_datetime is more than 24 hours ago, the smallest window that covers after_datetime is selected automatically. The window actually used is reported in stats.published_within on the result endpoint.

Example Usage

Success Response (202 Accepted)

Get the result

GET /tiktok/search/{task_id} — poll this endpoint with the task_id (or the check_status_url) returned above, or wait for the webhook notification. Polling does not consume credits.
The playground above only covers the submit request. Call the result endpoint with cURL or your HTTP client.

Request Parameters

Usage Disclosure

Because billing happens in the background worker, the submit endpoint cannot disclose usage. Instead, pass include_usage=true here:
  • Returned only when task_status=completed (processing tasks haven’t finished billing; failed tasks have all charges refunded).
  • Charges are pages_fetched × residential_request. No search_request is billed for TikTok keyword search.

Polling Lifecycle

The task_status field will be one of:
  • processing: the search is still running
  • completed: the search finished and results are ready
  • failed: the search ended with an error (all charges refunded)
While processing, results will be empty and download_url will usually be null.

Example Requests

Example Completed Response

The usage block appears only when include_usage=true and task_status=completed.

Understanding the Response

stats

  • pages_fetched: number of TikTok pages fetched (this is what you are billed for, as residential_request)
  • results_count: total normalized items collected
  • next_search_cursor: internal upstream cursor, or null when exhausted
  • sort_by: sort order the search ran with (relevance when sort_by was omitted)
  • published_within: date window the search ran with — shows the window chosen from after_datetime when published_within was omitted; all means no window

results

Each item is a normalized TikTok video with id, description, timestamp, published_at (UTC ISO 8601), author, stats (views/likes/comments/shares/collects), music, duration, hashtags, and url. Items are sorted by published_at descending (items without a timestamp go last), unless sort_by was set, in which case TikTok’s order is kept.

download_url

When present, a short-lived signed URL pointing to the full search result as one JSON file (same shape as the paginated results, but unsliced). null when the task hasn’t finished or the full result wasn’t archived — paginate through results instead.

error

Present when task_status is failed: an object with error (a code you can branch on), message and http_status. See Errors.
error_message is deprecated. It is kept for existing integrations, but new code should read error.error / error.message instead.

webhook

Delivery state of the task’s webhook notification (status, attempts, response_status, last_error, delivered_at), or null when no webhook applies.

Error Cases

  • 400: invalid request (e.g. bad cursor)
  • 404: task does not exist, expired, or does not belong to the current user

Tips

  • poll every few seconds while task_status is processing
  • switch to download_url for large completed jobs
  • tasks expire after about 1 hour — use expires_at to avoid polling expired tasks
  • call the endpoint again later if you need a freshly minted download_url

Authorizations

X-API-Key
string
header
required

API key authentication. Include your VidNavigator API key in the X-API-Key header.

Body

application/json
query
string
required

Keyword phrase to search on TikTok.

Minimum string length: 2
Example:

"ai tools"

max_results
integer
default:0

Optional upper bound on results the background task will try to collect. 0 (the default) or omitted means unlimited — pagination only stops when TikTok has no more results or the page cap is reached. With parallel_search_slices=1 that naturally yields ~115-140 items (TikTok serves ~5 pages of ~30 items per chain); with parallel_search_slices=4 up to ~480 unique items. A positive integer caps the merged result count. No hard server-side cap is enforced — a caller asking for 3000 will be billed per residential page actually fetched (~5 pages per slice naturally) and receive whatever TikTok delivers.

Required range: x >= 0
parallel_search_slices
integer
default:1

How many concurrent paginated query chains to run and dedup by video id. 1 (the default) is a single chain naturally capped at roughly 115-140 items. 2..4 runs that many additional chains in parallel, lifting the effective ceiling at the cost of up to ~Nx the residential pages of a single search. Diminishing returns: 2 slices yield ~+43% unique items, 3 slices ~+22%, 4 slices ~+13% on a representative query without a date window, so 4 already saturates TikTok's natural ~480-item dedup ceiling for most queries. With published_within set, every slice searches the same window and extra slices can return largely the same videos, so keep 1 unless you have measured a gain. parallel_search_slices is not a time filter — use published_within, after_datetime or before_datetime for time windows.

Required range: 1 <= x <= 4
Example:

2

sort_by
enum<string>

Sort order applied by TikTok itself (the same control as the app's search Filters sheet). relevance returns results in TikTok's ranking, most_liked by like count, newest by publish date, newest first. When omitted, results are returned newest first, and the search itself is ordered to fit your filters: newest first when after_datetime or before_datetime is set (stopping once it passes after_datetime), most liked first when only min_likes or min_views is set. That returns more matching videos per billed page.

Available options:
relevance,
most_liked,
newest
Example:

"newest"

published_within
enum<string>

Publication window applied by TikTok itself. Windows are rolling (this_week = the last 7 days). When omitted and after_datetime is more than 24 hours ago, the smallest window that covers after_datetime is selected automatically.

Available options:
all,
past_24_hours,
this_week,
this_month,
last_3_months,
last_6_months
Example:

"this_week"

after_datetime
string

Only include videos published on or after this boundary. Accepts YYYY-MM-DD or ISO datetime with timezone. Unless sort_by or published_within is set, it also makes the search run newest first and stop once it passes this boundary, so more results in range come back per billed page.

before_datetime
string

Only include videos published on or before this boundary. Accepts YYYY-MM-DD or ISO datetime with timezone.

min_likes
integer
Required range: x >= 0
max_likes
integer
Required range: x >= 0
min_views
integer
Required range: x >= 0
max_views
integer
Required range: x >= 0
webhook_url
string<uri>

Where to POST the result when the task finishes. Overrides the account-level default configured in Studio → API; pass an empty string to opt this task out of that default. Must be a publicly reachable https URL. The event is a notification, not the payload: a scrape can hold thousands of videos, so it carries stats and tells you to read the result from check_status_url. See https://docs.vidnavigator.com/guides/webhooks

Example:

"https://example.com/hooks/vidnavigator"

Response

Task accepted and queued.

status
enum<string>
Available options:
success
data
object