Back to blog

TikTok API Python Tutorial: Get TikTok Data With Python

by Simon Balfe ·

Getting TikTok data into a Python script should be simple. Make a request, parse the JSON, move on. In practice, most developers spend hours fighting browser automation, broken libraries, and anti-bot detection before they get a single data point.

This tutorial walks through the practical approach: using a REST API with Python’s requests library to pull TikTok profiles, videos, comments, hashtags, and trending content. Every code block is copy-pasteable and runnable.

Your options for TikTok data in Python

There are two main paths for getting TikTok data with Python.

Open-source libraries

The most well-known TikTok Python library is davidteather/TikTok-Api. It works by automating a browser session, mimicking TikTok’s internal requests, and parsing the responses.

The problem: TikTok actively changes their frontend, internal APIs, and anti-bot measures. These libraries require a headless browser (Playwright or Selenium), which means heavy dependencies and slow execution. When TikTok pushes an update, the library breaks until someone reverse-engineers the changes and publishes a fix. This can take days or weeks.

If you search GitHub issues on any TikTok scraper Python project, you will find a recurring pattern: the library works for a few weeks, TikTok changes something, and users report failures until a new patch lands.

For hobby projects where occasional downtime is acceptable, open-source libraries can work. For anything production-grade, they are a liability.

REST APIs

A REST API handles the scraping infrastructure on the server side. Your Python code sends standard HTTP requests and receives clean JSON responses. When TikTok changes their frontend, the API provider fixes it on their end. Your code stays the same.

This tutorial uses the CreatorCrawl API, which provides 20+ TikTok endpoints with pay-per-use pricing and no rate limits. You get 250 free credits on signup, which is enough to follow along with every example here.

Setting up your Python environment

You only need one dependency: the requests library.

pip install requests

Next, grab your API key:

  1. Create a free CreatorCrawl account
  2. Copy your API key from the dashboard
  3. Store it as an environment variable
export CREATORCRAWL_API_KEY="your_api_key_here"

In your Python scripts, load the key from the environment:

import os
import requests

API_KEY = os.environ["CREATORCRAWL_API_KEY"]
BASE_URL = "https://api.creatorcrawl.com/v1"

headers = {
    "x-api-key": API_KEY
}

Your first API call: Fetching a TikTok profile

Let’s start by pulling a TikTok creator’s profile data. This returns follower counts, bio, verification status, and more.

import os
import requests

API_KEY = os.environ["CREATORCRAWL_API_KEY"]
BASE_URL = "https://api.creatorcrawl.com/v1"
headers = {"x-api-key": API_KEY}

response = requests.get(
    f"{BASE_URL}/tiktok/profile",
    headers=headers,
    params={"handle": "charlidamelio"}
)

data = response.json()
profile = data["data"]

print(f"Username: {profile['uniqueId']}")
print(f"Nickname: {profile['nickname']}")
print(f"Followers: {profile['followerCount']:,}")
print(f"Following: {profile['followingCount']:,}")
print(f"Likes: {profile['heartCount']:,}")
print(f"Videos: {profile['videoCount']:,}")
print(f"Bio: {profile['signature']}")
print(f"Verified: {profile['verified']}")

The response includes everything you need to understand a creator’s presence: audience size, engagement totals, profile metadata, and avatar URLs.

Parsing the response

The API returns a JSON object with a data key containing the profile fields. If the request fails or the handle does not exist, you will get an error response with a message field explaining the issue. Always check the status code before parsing:

if response.status_code == 200:
    profile = response.json()["data"]
else:
    print(f"Error {response.status_code}: {response.json().get('message', 'Unknown error')}")

Getting a creator’s videos

Once you have a profile, the next step is pulling their video feed. This returns recent videos with full metadata.

response = requests.get(
    f"{BASE_URL}/tiktok/profile/videos",
    headers=headers,
    params={"handle": "charlidamelio"}
)

videos = response.json()["data"]

for video in videos[:5]:
    print(f"Description: {video['desc'][:80]}")
    print(f"Views: {video['playCount']:,}")
    print(f"Likes: {video['diggCount']:,}")
    print(f"Comments: {video['commentCount']:,}")
    print(f"Shares: {video['shareCount']:,}")
    print(f"Created: {video['createTime']}")
    print("---")

Each video object includes the description, play count, like count, comment count, share count, creation timestamp, video URL, cover image, and music information. This is everything you need for content analysis, competitive research, or building a TikTok analytics dashboard.

Calculating engagement rate

With the video data in hand, you can compute engagement metrics:

total_engagement = 0
total_views = 0

for video in videos:
    engagement = video["diggCount"] + video["commentCount"] + video["shareCount"]
    total_engagement += engagement
    total_views += video["playCount"]

if total_views > 0:
    engagement_rate = (total_engagement / total_views) * 100
    print(f"Average engagement rate: {engagement_rate:.2f}%")

Searching for users by keyword

If you need to find creators in a specific niche, use the search endpoint. This is useful for influencer discovery and competitive research.

response = requests.get(
    f"{BASE_URL}/tiktok/search/users",
    headers=headers,
    params={"query": "python programming"}
)

users = response.json()["data"]

for user in users:
    print(f"@{user['uniqueId']} - {user['nickname']}")
    print(f"  Followers: {user['followerCount']:,}")
    print(f"  Bio: {user['signature'][:60]}")
    print()

You can use this to build lists of creators in any niche, then pull their profiles and videos for deeper analysis.

Getting video comments

Comments reveal what an audience actually thinks. The comments endpoint returns the top-level comments on any video.

video_id = "7345678901234567890"

response = requests.get(
    f"{BASE_URL}/tiktok/video/comments",
    headers=headers,
    params={"video_id": video_id}
)

comments = response.json()["data"]

for comment in comments[:10]:
    print(f"@{comment['user']['uniqueId']}: {comment['text']}")
    print(f"  Likes: {comment['diggCount']:,}")
    print()

This is especially valuable for sentiment analysis, finding product feedback, or understanding what content resonates with an audience.

Exporting comments to CSV

A common use case is exporting comments for analysis in a spreadsheet or data tool:

import csv

with open("comments.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["Username", "Comment", "Likes", "Timestamp"])

    for comment in comments:
        writer.writerow([
            comment["user"]["uniqueId"],
            comment["text"],
            comment["diggCount"],
            comment["createTime"]
        ])

print(f"Exported {len(comments)} comments to comments.csv")

For a deeper look at comment extraction, see our TikTok comment export guide.

The trending endpoint returns videos currently gaining traction on TikTok. This is useful for content research and trend monitoring.

response = requests.get(
    f"{BASE_URL}/tiktok/trending",
    headers=headers
)

trending = response.json()["data"]

for i, video in enumerate(trending[:10], 1):
    print(f"{i}. {video['desc'][:70]}")
    print(f"   @{video['author']['uniqueId']} | {video['playCount']:,} views")
    print()

You can run this on a schedule to track which content formats and topics are picking up momentum.

Working with hashtag data

Hashtags are a core part of TikTok’s discovery system. The hashtag endpoint lets you pull data about specific hashtags, including associated videos and usage statistics.

response = requests.get(
    f"{BASE_URL}/tiktok/hashtag",
    headers=headers,
    params={"name": "python"}
)

hashtag_data = response.json()["data"]

print(f"Hashtag: #{hashtag_data['title']}")
print(f"Views: {hashtag_data['viewCount']:,}")

if "videos" in hashtag_data:
    print(f"\nTop videos for #{hashtag_data['title']}:")
    for video in hashtag_data["videos"][:5]:
        print(f"  {video['desc'][:60]} | {video['playCount']:,} views")

Hashtag research helps you understand content trends, find related topics, and optimize your own TikTok content strategy.

Building a complete script: TikTok creator analyzer

Now let’s combine everything into a single script that takes a TikTok handle and produces a full creator analysis report.

import os
import json
import requests

API_KEY = os.environ["CREATORCRAWL_API_KEY"]
BASE_URL = "https://api.creatorcrawl.com/v1"
headers = {"x-api-key": API_KEY}


def get_profile(handle):
    response = requests.get(
        f"{BASE_URL}/tiktok/profile",
        headers=headers,
        params={"handle": handle}
    )
    response.raise_for_status()
    return response.json()["data"]


def get_videos(handle):
    response = requests.get(
        f"{BASE_URL}/tiktok/profile/videos",
        headers=headers,
        params={"handle": handle}
    )
    response.raise_for_status()
    return response.json()["data"]


def analyze_videos(videos):
    if not videos:
        return {}

    total_views = sum(v["playCount"] for v in videos)
    total_likes = sum(v["diggCount"] for v in videos)
    total_comments = sum(v["commentCount"] for v in videos)
    total_shares = sum(v["shareCount"] for v in videos)
    count = len(videos)

    engagement = total_likes + total_comments + total_shares
    engagement_rate = (engagement / total_views * 100) if total_views > 0 else 0

    best_video = max(videos, key=lambda v: v["playCount"])

    return {
        "total_videos_analyzed": count,
        "total_views": total_views,
        "avg_views": total_views // count,
        "total_likes": total_likes,
        "avg_likes": total_likes // count,
        "total_comments": total_comments,
        "avg_comments": total_comments // count,
        "total_shares": total_shares,
        "avg_shares": total_shares // count,
        "engagement_rate": round(engagement_rate, 2),
        "best_video": {
            "description": best_video["desc"][:100],
            "views": best_video["playCount"],
            "likes": best_video["diggCount"]
        }
    }


def generate_report(handle):
    print(f"Analyzing @{handle}...\n")

    profile = get_profile(handle)

    print(f"Profile: @{profile['uniqueId']}")
    print(f"Name: {profile['nickname']}")
    print(f"Followers: {profile['followerCount']:,}")
    print(f"Following: {profile['followingCount']:,}")
    print(f"Total Likes: {profile['heartCount']:,}")
    print(f"Total Videos: {profile['videoCount']:,}")
    print(f"Verified: {profile['verified']}")
    print(f"Bio: {profile['signature']}")
    print()

    videos = get_videos(handle)
    stats = analyze_videos(videos)

    print(f"Video Analysis ({stats['total_videos_analyzed']} recent videos):")
    print(f"  Avg Views: {stats['avg_views']:,}")
    print(f"  Avg Likes: {stats['avg_likes']:,}")
    print(f"  Avg Comments: {stats['avg_comments']:,}")
    print(f"  Avg Shares: {stats['avg_shares']:,}")
    print(f"  Engagement Rate: {stats['engagement_rate']}%")
    print()
    print(f"Best Performing Video:")
    print(f"  {stats['best_video']['description']}")
    print(f"  Views: {stats['best_video']['views']:,}")
    print(f"  Likes: {stats['best_video']['likes']:,}")

    report = {
        "handle": handle,
        "profile": {
            "nickname": profile["nickname"],
            "followers": profile["followerCount"],
            "following": profile["followingCount"],
            "total_likes": profile["heartCount"],
            "total_videos": profile["videoCount"],
            "verified": profile["verified"],
            "bio": profile["signature"]
        },
        "video_stats": stats
    }

    filename = f"{handle}_report.json"
    with open(filename, "w") as f:
        json.dump(report, f, indent=2)
    print(f"\nFull report saved to {filename}")


if __name__ == "__main__":
    import sys
    handle = sys.argv[1] if len(sys.argv) > 1 else "charlidamelio"
    generate_report(handle)

Run the script from your terminal:

python creator_analyzer.py khaby.lame

This pulls the profile, fetches recent videos, computes engagement metrics, identifies the best performing video, and saves a structured JSON report.

Error handling and best practices

Production code needs proper error handling. Here is a reusable request wrapper that handles the common failure modes:

import time
import requests


def api_request(endpoint, params=None, max_retries=3):
    url = f"{BASE_URL}{endpoint}"

    for attempt in range(max_retries):
        try:
            response = requests.get(url, headers=headers, params=params, timeout=30)

            if response.status_code == 200:
                return response.json()["data"]

            if response.status_code == 429:
                wait = 2 ** attempt
                print(f"Rate limited. Retrying in {wait}s...")
                time.sleep(wait)
                continue

            if response.status_code == 401:
                raise Exception("Invalid API key. Check your CREATORCRAWL_API_KEY.")

            if response.status_code == 404:
                raise Exception(f"Not found: {endpoint} with params {params}")

            response.raise_for_status()

        except requests.exceptions.Timeout:
            print(f"Request timed out (attempt {attempt + 1}/{max_retries})")
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)

        except requests.exceptions.ConnectionError:
            print(f"Connection error (attempt {attempt + 1}/{max_retries})")
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)

    raise Exception(f"Failed after {max_retries} retries: {endpoint}")

Key practices to follow

Set timeouts on every request. Without a timeout, a hanging connection can block your script indefinitely. Use timeout=30 as a sensible default.

Use exponential backoff for retries. If a request fails due to a transient issue, wait progressively longer between retries (1s, 2s, 4s). This avoids hammering the server while it recovers.

Store your API key in an environment variable. Never hardcode credentials in your source files. Use os.environ to load the key at runtime.

Cache responses when appropriate. If you are pulling the same profile multiple times in a pipeline, cache the result locally to avoid burning credits on duplicate requests.

Handle missing fields gracefully. TikTok profiles vary. Some creators have bios, some do not. Use .get() with default values instead of direct key access:

bio = profile.get("signature", "No bio available")

What you can build from here

With these building blocks, you can put together a range of Python applications:

Influencer research tools that search for creators in a niche, pull their metrics, and rank them by engagement rate. See our full endpoints reference for every available data point.

Content monitoring systems that track trending videos and alert you when specific hashtags or creators gain traction.

Competitive analysis dashboards that compare multiple creators side by side over time.

Data pipelines that feed TikTok data into machine learning models, recommendation engines, or reporting tools. Our Python integration guide covers more advanced patterns.

For a broader look at TikTok data collection approaches, read our guide on how to scrape TikTok data. If you are evaluating different providers, our comparison of the best TikTok APIs breaks down pricing and feature differences.

Getting started

Sign up for a free CreatorCrawl account to get 250 credits and start making requests in under a minute. No credit card required, and credits never expire. Every example in this tutorial works within the free tier.

Explore CreatorCrawl

More from the Blog