Back to all posts

How to Scrape TikTok Channel Videos in 2026 using SocialKit API

Jonathan Geiger
TikTok APITikTok ScrapingChannel VideosSocial Media AnalyticsData Extraction

Want to get a list of all videos from a TikTok profile programmatically? Whether you're building a competitor analysis tool, influencer vetting dashboard, or content monitoring system, pulling channel video data is something that keeps coming up.

The problem is that TikTok's video list is loaded dynamically using browser session tokens. A plain HTTP request to their internal API returns an empty body. You need a real browser to get the data, which makes rolling your own scraper painful to maintain.

This guide covers the straightforward way to do it using the TikTok Channel Videos API — one request, clean JSON back.

What You Get Back

Each video in the response includes:

  • Video ID and direct TikTok URL
  • Caption/description (up to 300 characters)
  • Thumbnail image URL
  • Duration in seconds
  • Publish date (ISO 8601)
  • Views, likes, comments, shares, and saves

The Endpoint

https://api.socialkit.dev/tiktok/channel-videos

Parameters

ParameterTypeRequiredDescription
urlstringYesTikTok profile URL, e.g. https://tiktok.com/@username
access_keystringYesYour API access key
limitnumberNoVideos to return (default 30, max 100)
cursorstringNoPagination cursor from a previous response

Example Request

GET https://api.socialkit.dev/tiktok/channel-videos?access_key=<your-key>&url=https://www.tiktok.com/@khaby.lame&limit=30

Example Response

{
  "success": true,
  "data": {
    "type": "tiktok_channel_videos",
    "url": "https://www.tiktok.com/@khaby.lame",
    "channelName": "khaby.lame",
    "results": [
      {
        "videoId": "7312345678901234567",
        "description": "Simplicity is the key 🔑 #learnfromkhaby #comedy",
        "url": "https://www.tiktok.com/@khaby.lame/video/7312345678901234567",
        "thumbnail": "https://p16-sign.tiktokcdn-us.com/...",
        "duration": 14,
        "createTime": "2026-06-10T12:34:56.000Z",
        "views": 12500000,
        "likes": 1430000,
        "comments": 8200,
        "shares": 45000,
        "collects": 62000
      }
    ],
    "hasMore": true,
    "cursor": "1749556496000"
  }
}

Code Examples

JavaScript / Node.js

const axios = require('axios');

async function getTikTokChannelVideos(profileUrl, accessKey, limit = 30) {
  const response = await axios.get('https://api.socialkit.dev/tiktok/channel-videos', {
    params: { access_key: accessKey, url: profileUrl, limit }
  });
  return response.data;
}

// Basic usage
const data = await getTikTokChannelVideos('https://tiktok.com/@khaby.lame', 'your-key', 50);
console.log(`Got ${data.data.results.length} videos from @${data.data.channelName}`);

data.data.results.forEach(video => {
  console.log(`${video.description.slice(0, 60)}...`);
  console.log(`  Views: ${video.views.toLocaleString()} | Likes: ${video.likes.toLocaleString()}`);
});

Python

import requests

def get_tiktok_channel_videos(profile_url, access_key, limit=30, cursor=None):
    params = {
        'access_key': access_key,
        'url': profile_url,
        'limit': limit,
    }
    if cursor:
        params['cursor'] = cursor

    response = requests.get('https://api.socialkit.dev/tiktok/channel-videos', params=params)
    response.raise_for_status()
    return response.json()

# Basic usage
data = get_tiktok_channel_videos('https://tiktok.com/@khaby.lame', 'your-key', limit=50)

for video in data['data']['results']:
    print(f"{video['description'][:60]}...")
    print(f"  Views: {video['views']:,} | Likes: {video['likes']:,}")

PHP

<?php

function getTikTokChannelVideos($profileUrl, $accessKey, $limit = 30, $cursor = null) {
    $params = [
        'access_key' => $accessKey,
        'url' => $profileUrl,
        'limit' => $limit,
    ];
    if ($cursor) {
        $params['cursor'] = $cursor;
    }

    $url = 'https://api.socialkit.dev/tiktok/channel-videos?' . http_build_query($params);
    $response = file_get_contents($url);
    return json_decode($response, true);
}

$data = getTikTokChannelVideos('https://tiktok.com/@khaby.lame', 'your-key', 30);

foreach ($data['data']['results'] as $video) {
    echo substr($video['description'], 0, 60) . "...\n";
    echo "  Views: " . number_format($video['views']) . "\n\n";
}

cURL

curl -X GET "https://api.socialkit.dev/tiktok/channel-videos?access_key=your-key&url=https://tiktok.com/@khaby.lame&limit=30"

Paginating Through a Full Channel

When hasMore is true in the response, there are more videos to fetch. Pass the cursor value from the response to get the next page.

async function getAllChannelVideos(profileUrl, accessKey, maxVideos = 200) {
  let allVideos = [];
  let cursor = null;

  do {
    const params = {
      access_key: accessKey,
      url: profileUrl,
      limit: 100,
    };
    if (cursor) params.cursor = cursor;

    const res = await axios.get('https://api.socialkit.dev/tiktok/channel-videos', { params });
    const { results, hasMore, cursor: nextCursor } = res.data.data;

    allVideos.push(...results);
    cursor = hasMore ? nextCursor : null;

  } while (cursor && allVideos.length < maxVideos);

  return allVideos.slice(0, maxVideos);
}

Same thing in Python:

def get_all_channel_videos(profile_url, access_key, max_videos=200):
    all_videos = []
    cursor = None

    while len(all_videos) < max_videos:
        data = get_tiktok_channel_videos(profile_url, access_key, limit=100, cursor=cursor)
        results = data['data']['results']
        all_videos.extend(results)

        if not data['data']['hasMore']:
            break
        cursor = data['data']['cursor']

    return all_videos[:max_videos]

Real Use Cases

Find a Channel's Top Videos by Views

async function getTopVideos(profileUrl, accessKey, topN = 10) {
  const data = await getTikTokChannelVideos(profileUrl, accessKey, 100);
  return data.data.results
    .sort((a, b) => b.views - a.views)
    .slice(0, topN);
}

Monitor for New Uploads

Poll a channel on a schedule and compare video IDs against your stored list to detect new uploads.

import json
from datetime import datetime

def check_for_new_videos(profile_url, access_key, known_ids_file):
    with open(known_ids_file) as f:
        known_ids = set(json.load(f))

    data = get_tiktok_channel_videos(profile_url, access_key, limit=30)
    current_videos = data['data']['results']

    new_videos = [v for v in current_videos if v['videoId'] not in known_ids]

    if new_videos:
        print(f"Found {len(new_videos)} new video(s)!")
        for v in new_videos:
            print(f"  - {v['description'][:60]}...")

    # Update known IDs
    all_ids = known_ids | {v['videoId'] for v in current_videos}
    with open(known_ids_file, 'w') as f:
        json.dump(list(all_ids), f)

    return new_videos

Calculate Average Engagement Rate

function calcEngagementRate(videos) {
  if (!videos.length) return 0;
  const total = videos.reduce((sum, v) => sum + v.likes + v.comments + v.shares, 0);
  const totalViews = videos.reduce((sum, v) => sum + v.views, 0);
  return totalViews > 0 ? ((total / totalViews) * 100).toFixed(2) : 0;
}

const data = await getTikTokChannelVideos('https://tiktok.com/@mkbhd', 'your-key', 50);
const rate = calcEngagementRate(data.data.results);
console.log(`Average engagement rate: ${rate}%`);

Why Not Roll Your Own Scraper?

TikTok's video list page requires a real browser session to load the video data. Their internal item_list API silently returns an empty body for unauthenticated direct HTTP requests. To get around this you need:

  • Puppeteer or Playwright running in a headless browser
  • Working around bot detection (residential proxies, stealth plugins, etc.)
  • Network interception to catch the internal API responses
  • Constant maintenance as TikTok changes their anti-bot logic

It's doable, but it breaks every few weeks. The API just handles it.

Pricing

Each API request costs 1 credit. Plans start at 20 free credits, with paid plans from $14/month.

  • Free: 20 credits
  • Starter: $19/month (4,000 credits)
  • Standard: $29/month (12,000 credits)
  • Ultimate: $95/month (50,000 credits)
  • Enterprise and higher plans are also available

We also support Pay As You Go plans, so you can buy one-time credits that never expire.

View full pricing

Free tools:

Frequently Asked Questions

Does it work for private accounts?

No. Only public TikTok profiles are supported.

How fresh is the data?

Fetched live at request time. Views and likes reflect what's on TikTok right now.

Can I get more than 100 videos per request?

Not in a single request, but you can paginate using the cursor to walk through an entire channel's history.

What does the cursor value represent?

It's a timestamp that TikTok uses internally to page through a channel's video history. You don't need to parse it, just pass it back in the next request.

Do failed requests count against my quota?

No. Only successful requests are charged.

Get Started

Sign up at socialkit.dev and get 20 free credits. No credit card required.

API docs: docs.socialkit.dev/api-reference/tiktok-channel-videos-api