curl --request POST \
--url https://api.vidnavigator.com/v1/tiktok/profile \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"profile_url": "https://www.tiktok.com/@tiktok",
"max_posts": 100,
"after_datetime": "2024-01-01T00:00:00Z",
"before_datetime": "2024-12-31",
"min_likes": 1,
"max_likes": 1
}
'import requests
url = "https://api.vidnavigator.com/v1/tiktok/profile"
payload = {
"profile_url": "https://www.tiktok.com/@tiktok",
"max_posts": 100,
"after_datetime": "2024-01-01T00:00:00Z",
"before_datetime": "2024-12-31",
"min_likes": 1,
"max_likes": 1
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
profile_url: 'https://www.tiktok.com/@tiktok',
max_posts: 100,
after_datetime: '2024-01-01T00:00:00Z',
before_datetime: '2024-12-31',
min_likes: 1,
max_likes: 1
})
};
fetch('https://api.vidnavigator.com/v1/tiktok/profile', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vidnavigator.com/v1/tiktok/profile",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'profile_url' => 'https://www.tiktok.com/@tiktok',
'max_posts' => 100,
'after_datetime' => '2024-01-01T00:00:00Z',
'before_datetime' => '2024-12-31',
'min_likes' => 1,
'max_likes' => 1
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vidnavigator.com/v1/tiktok/profile"
payload := strings.NewReader("{\n \"profile_url\": \"https://www.tiktok.com/@tiktok\",\n \"max_posts\": 100,\n \"after_datetime\": \"2024-01-01T00:00:00Z\",\n \"before_datetime\": \"2024-12-31\",\n \"min_likes\": 1,\n \"max_likes\": 1\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vidnavigator.com/v1/tiktok/profile")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"profile_url\": \"https://www.tiktok.com/@tiktok\",\n \"max_posts\": 100,\n \"after_datetime\": \"2024-01-01T00:00:00Z\",\n \"before_datetime\": \"2024-12-31\",\n \"min_likes\": 1,\n \"max_likes\": 1\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vidnavigator.com/v1/tiktok/profile")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"profile_url\": \"https://www.tiktok.com/@tiktok\",\n \"max_posts\": 100,\n \"after_datetime\": \"2024-01-01T00:00:00Z\",\n \"before_datetime\": \"2024-12-31\",\n \"min_likes\": 1,\n \"max_likes\": 1\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"data": {
"task_id": "<string>",
"task_status": "processing",
"profile_url": "<string>",
"expires_at": "2023-11-07T05:31:56Z",
"check_status_url": "/v1/tiktok/profile/550e8400-e29b-41d4-a716-446655440000",
"message": "<string>"
}
}{
"status": "error",
"error": "request_body_required",
"message": "<string>"
}{
"status": "error",
"error": "limit_exceeded",
"message": "<string>"
}{
"status": "error",
"error": "internal_server_error",
"message": "<string>"
}Submit TikTok Profile Scrape
Start an asynchronous TikTok profile scrape and return a task_id immediately.
The scrape runs in the background with shallow extraction so it can stop early when filters are satisfied. Results are retained for 1 hour and, when cloud storage is configured, also uploaded as a single JSON file accessible through download_url.
Billing: Each TikTok API page fetched is billed as one standard request. One page is pre-charged when the task is accepted; remaining pages are reconciled when the scrape completes. If the scrape fails after charging additional pages, all charged pages are reversed. TikTok currently returns ~15 videos per page; this is an internal estimate and may change.
Filters: All filters are applied as the scraper iterates. max_posts and after_datetime allow the scraper to stop fetching new pages early; the other filters reduce result size but do not stop pagination.
Usage disclosure: This endpoint does NOT accept include_usage. Because billing happens in the background worker after the 202 response is sent, there is nothing to disclose at submit time. Pass include_usage=true on GET /tiktok/profile/{task_id} instead — the GET endpoint replays the final charges once task_status=completed.
Use GET /tiktok/profile/{task_id} to poll status and retrieve paginated results, or follow download_url for the complete JSON.
curl --request POST \
--url https://api.vidnavigator.com/v1/tiktok/profile \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"profile_url": "https://www.tiktok.com/@tiktok",
"max_posts": 100,
"after_datetime": "2024-01-01T00:00:00Z",
"before_datetime": "2024-12-31",
"min_likes": 1,
"max_likes": 1
}
'import requests
url = "https://api.vidnavigator.com/v1/tiktok/profile"
payload = {
"profile_url": "https://www.tiktok.com/@tiktok",
"max_posts": 100,
"after_datetime": "2024-01-01T00:00:00Z",
"before_datetime": "2024-12-31",
"min_likes": 1,
"max_likes": 1
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
profile_url: 'https://www.tiktok.com/@tiktok',
max_posts: 100,
after_datetime: '2024-01-01T00:00:00Z',
before_datetime: '2024-12-31',
min_likes: 1,
max_likes: 1
})
};
fetch('https://api.vidnavigator.com/v1/tiktok/profile', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vidnavigator.com/v1/tiktok/profile",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'profile_url' => 'https://www.tiktok.com/@tiktok',
'max_posts' => 100,
'after_datetime' => '2024-01-01T00:00:00Z',
'before_datetime' => '2024-12-31',
'min_likes' => 1,
'max_likes' => 1
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vidnavigator.com/v1/tiktok/profile"
payload := strings.NewReader("{\n \"profile_url\": \"https://www.tiktok.com/@tiktok\",\n \"max_posts\": 100,\n \"after_datetime\": \"2024-01-01T00:00:00Z\",\n \"before_datetime\": \"2024-12-31\",\n \"min_likes\": 1,\n \"max_likes\": 1\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.vidnavigator.com/v1/tiktok/profile")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"profile_url\": \"https://www.tiktok.com/@tiktok\",\n \"max_posts\": 100,\n \"after_datetime\": \"2024-01-01T00:00:00Z\",\n \"before_datetime\": \"2024-12-31\",\n \"min_likes\": 1,\n \"max_likes\": 1\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vidnavigator.com/v1/tiktok/profile")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"profile_url\": \"https://www.tiktok.com/@tiktok\",\n \"max_posts\": 100,\n \"after_datetime\": \"2024-01-01T00:00:00Z\",\n \"before_datetime\": \"2024-12-31\",\n \"min_likes\": 1,\n \"max_likes\": 1\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"data": {
"task_id": "<string>",
"task_status": "processing",
"profile_url": "<string>",
"expires_at": "2023-11-07T05:31:56Z",
"check_status_url": "/v1/tiktok/profile/550e8400-e29b-41d4-a716-446655440000",
"message": "<string>"
}
}{
"status": "error",
"error": "request_body_required",
"message": "<string>"
}{
"status": "error",
"error": "limit_exceeded",
"message": "<string>"
}{
"status": "error",
"error": "internal_server_error",
"message": "<string>"
}task_id immediately.
Overview
This endpoint is designed for profile-level collection, not single-video analysis. It starts a background scrape job that iterates through a TikTok account, applies your filters as it goes, and stores the results temporarily so you can fetch them later. Use it when you want to:- collect recent posts from a TikTok creator
- filter videos by date or like count
- scrape large profiles without blocking on a long request
- export the full result set through a temporary
download_url
How the Async Flow Works
- Send
POST /tiktok/profilewith a public TikTokprofile_urland optional filters. - The API accepts the task and returns a
task_idwithtask_status: "processing". - Poll
GET /tiktok/profile/{task_id}until the task iscompletedorfailed. - Once completed, either page through
videosusing cursors or download the full JSON fromdownload_urlwhen available.
download_url availability.Filters You Can Apply
All filters are optional exceptprofile_url.
| Field | Type | Description |
|---|---|---|
profile_url | string | Public TikTok profile URL, such as https://www.tiktok.com/@username |
max_posts | integer | Maximum number of matching videos to return |
after_datetime | string | Include only videos published on or after this boundary. Accepts YYYY-MM-DD or an ISO datetime with timezone, such as 2024-01-01T00:00:00Z. |
before_datetime | string | Include only videos published on or before this boundary. Accepts YYYY-MM-DD or an ISO datetime with timezone, such as 2024-12-31T23:59:59+02:00. |
min_likes | integer | Include only videos with at least this many likes |
max_likes | integer | Include only videos with at most this many likes |
max_posts and after_datetime are the most useful filters for keeping scrapes smaller and faster because they can stop pagination early.What You Get Back Immediately
The submit endpoint now returns more than just a task ID. The accepted response includes:task_idto identify the scrape jobtask_statusset toprocessingprofile_urlechoing the submitted profileexpires_atso you know when the task record will expirecheck_status_urlwith the relative API path to pollmessageconfirming the job was accepted
Example Request
curl -X POST "https://api.vidnavigator.com/v1/tiktok/profile" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profile_url": "https://www.tiktok.com/@tiktok",
"max_posts": 50,
"after_datetime": "2024-01-01T00:00:00Z",
"min_likes": 10000
}'
import requests
response = requests.post(
"https://api.vidnavigator.com/v1/tiktok/profile",
headers={
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"profile_url": "https://www.tiktok.com/@tiktok",
"max_posts": 50,
"after_datetime": "2024-01-01T00:00:00Z",
"min_likes": 10000,
},
)
print(response.json())
const response = await fetch('https://api.vidnavigator.com/v1/tiktok/profile', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
profile_url: 'https://www.tiktok.com/@tiktok',
max_posts: 50,
after_datetime: '2024-01-01T00:00:00Z',
min_likes: 10000
})
});
const result = await response.json();
Success Response
The endpoint returns202 Accepted because the scrape runs in the background.
{
"status": "success",
"data": {
"task_id": "tt_profile_abc123",
"task_status": "processing",
"profile_url": "https://www.tiktok.com/@tiktok",
"expires_at": "2026-04-26T00:55:00Z",
"check_status_url": "/v1/tiktok/profile/tt_profile_abc123",
"message": "TikTok profile scrape accepted. Poll the status endpoint to retrieve results."
}
}
Billing Notes
TikTok profile scraping is billed by pages consumed during the scrape:- each TikTok API page is billed as one
standard_requestwhen no proxy is used - each TikTok API page is billed as one
residential_requestwhen a residential proxy is used - one page is pre-charged when the task is accepted
- final usage is reconciled when the scrape completes
- if the scrape fails after extra pages were charged, those charges are reversed
Tips for Large Profiles
- use
after_datetimeto avoid crawling older history you do not need - use
max_poststo cap the result size - prefer
download_urlafter completion if you expect a large result set - poll the result endpoint while the task is processing instead of resubmitting the same scrape
Common Errors
request_body_required: the JSON body was missingmissing_parameter:profile_urlwas not sentinvalid_url: the submittedprofile_urlis malformedinvalid_parameter: one of the filters is malformed
unsupported_platform for this endpoint.
Next Step
After you receive thetask_id, poll the result endpoint. You can use either the returned task_id or the check_status_url value:
Authorizations
API key authentication. Include your VidNavigator API key in the X-API-Key header.
Body
Public TikTok profile URL (e.g. https://www.tiktok.com/@username).
"https://www.tiktok.com/@tiktok"
Maximum number of matching videos to return. The scraper stops paginating once this is reached.
x >= 1100
Only include videos published on or after this boundary. Accepts either YYYY-MM-DD or an ISO datetime with timezone (e.g. 2024-01-01T00:00:00Z). Filtering uses per-video timestamp when available (UTC), with upload-date fallback otherwise.
"2024-01-01T00:00:00Z"
Only include videos published on or before this boundary. Accepts either YYYY-MM-DD or an ISO datetime with timezone (e.g. 2024-12-31T23:59:59+02:00). Filtering uses per-video timestamp when available (UTC), with upload-date fallback otherwise.
"2024-12-31"
Only include videos with at least this many likes.
x >= 0Only include videos with at most this many likes.
x >= 0
