New: image reposting, and Repostit for Claude and ChatGPT. See what’s new
RepostitLog inStart free trial
New: image reposting and AI plugins. See what’s new
RepostitTry it free

How to Post TikTok Videos via API Using Python

· 21 min read

How to Post TikTok Videos via API Using Python: A Complete Developer Guide

If you want to post TikTok videos via API using Python, you are in the right place. For developers, growth hackers, and social media managers who need to publish TikTok content programmatically, the TikTok Content Posting API unlocks the ability to upload videos, set captions, and manage publishing, all from a Python script. No more manually opening the app, selecting files, and typing captions for every single post. Whether you are building an internal tool, a SaaS product, or automating your own creator workflow, this guide walks you through how to post TikTok videos via API using Python from zero to a working implementation.

This guide covers authentication, token management, chunked file uploads, caption configuration, error handling, and production best practices for anyone looking to post TikTok videos via API using Python. If you want a no-code alternative that handles cross-platform posting automatically, check out Repostit.io, but if you want to build it yourself, keep reading.

Why Post TikTok Videos via API Using Python?

Manually uploading videos works fine when you publish a few times per week. But the moment you manage multiple accounts, run scheduled campaigns, or build content pipelines that originate from external sources (CMS platforms, video editors, AI generators), manual uploads become a bottleneck. The TikTok Content Posting API exists specifically to solve this problem and lets you post TikTok videos via API using Python at scale.

Here is what programmatic posting enables that manual posting cannot:

Capability Manual Upload Post TikTok Videos via API (Python)
Scheduled Publishing Requires being at your phone at the right time Cron job or task queue handles timing automatically
Multi-Account Management Log in/out of each account manually Token-based auth switches accounts in milliseconds
Pipeline Integration Copy files between apps manually Direct integration with video editors, CMS, or AI tools
Batch Uploads One video at a time, full attention required Queue dozens of videos with a single script execution
Error Recovery Start over if the app crashes mid-upload Retry logic with exponential backoff handles failures gracefully

If any of those scenarios apply to you, learning how to post TikTok videos via API using Python will save you significant time every week.

Prerequisites to Post TikTok Videos via API Using Python

Before writing any code to post TikTok videos via API using Python, you need to set up your TikTok developer environment. This is the part that trips up most developers because TikTok’s API access model is more restrictive than platforms like YouTube or Twitter.

Step 1: Create a TikTok Developer Account

  1. Go to the TikTok for Developers portal and sign up.
  2. Create a new application in the developer dashboard.
  3. Under Products, enable Content Posting API (also called “Video Upload” in some dashboard versions).
  4. Configure your redirect URI, this is where TikTok sends the authorization code after user login. For local development, use https://localhost:3000/callback.
  5. Note your Client Key and Client Secret. You will need both.

Step 2: Understand the Sandbox Limitations

TikTok requires all new apps to start in sandbox mode, which has strict limitations you must be aware of before testing:

Limitation Sandbox Mode Production Mode
Test Users Maximum 5 accounts Unlimited
Daily Upload Limit ~5 videos per day ~15 videos per day per user
Video Visibility Private only (not visible to public) Public, friends-only, or private
Approval Required No Yes — TikTok reviews your app

This means your videos will not appear publicly until your app passes TikTok’s review process. Plan accordingly — build and test in sandbox, then submit for review when your integration is solid.

Step 3: Install Python Dependencies

You will need a minimal set of Python packages. Create a virtual environment and install the following:

pip install requests python-dotenv

We use requests for HTTP calls and python-dotenv to keep credentials out of source code. Your .env file should look like this:

# .env
TIKTOK_CLIENT_KEY=your_client_key_here
TIKTOK_CLIENT_SECRET=your_client_secret_here
TIKTOK_REDIRECT_URI=https://localhost:3000/callback

Authentication: OAuth 2.0 Flow for TikTok API Python Integration

TikTok uses OAuth 2.0 with PKCE for user authentication. This is a server-side flow where the user authorizes your app in their browser, TikTok redirects back to your server with an authorization code, and you exchange that code for an access token. Mastering this flow is essential before you can post TikTok videos via API using Python. Here is the complete flow implemented in Python:

Generate the Authorization URL

import os
import secrets
import hashlib
import base64
from urllib.parse import urlencode
from dotenv import load_dotenv

load_dotenv()

CLIENT_KEY = os.getenv("TIKTOK_CLIENT_KEY")
REDIRECT_URI = os.getenv("TIKTOK_REDIRECT_URI")

# Generate PKCE code verifier and challenge
code_verifier = secrets.token_urlsafe(64)
code_challenge = base64.urlsafe_b64encode(
    hashlib.sha256(code_verifier.encode()).digest()
).rstrip(b"=").decode()

# Store code_verifier — you'll need it when exchanging the auth code
print(f"Save this code_verifier: {code_verifier}")

params = {
    "client_key": CLIENT_KEY,
    "response_type": "code",
    "scope": "video.upload,video.publish",
    "redirect_uri": REDIRECT_URI,
    "state": secrets.token_hex(16),
    "code_challenge": code_challenge,
    "code_challenge_method": "S256",
}

auth_url = f"https://www.tiktok.com/v2/auth/authorize/?{urlencode(params)}"
print(f"Open this URL in your browser:\n{auth_url}")

The user opens the URL, logs into TikTok, grants permissions, and TikTok redirects to your redirect_uri with a code parameter in the URL.

Exchange the Authorization Code for Tokens

import requests

CLIENT_SECRET = os.getenv("TIKTOK_CLIENT_SECRET")

def exchange_code_for_token(auth_code: str, code_verifier: str) -> dict:
    """Exchange authorization code for access and refresh tokens."""
    url = "https://open.tiktokapis.com/v2/oauth/token/"
    
    payload = {
        "client_key": CLIENT_KEY,
        "client_secret": CLIENT_SECRET,
        "code": auth_code,
        "grant_type": "authorization_code",
        "redirect_uri": REDIRECT_URI,
        "code_verifier": code_verifier,
    }
    
    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    
    response = requests.post(url, data=payload, headers=headers)
    response.raise_for_status()
    
    token_data = response.json()
    
    if "access_token" not in token_data:
        raise ValueError(f"Token exchange failed: {token_data}")
    
    print(f"Access token expires in: {token_data['expires_in']} seconds")
    print(f"Refresh token expires in: {token_data['refresh_expires_in']} seconds")
    
    return token_data

# Usage:
# token_data = exchange_code_for_token("AUTH_CODE_FROM_REDIRECT", code_verifier)

Refreshing Expired Tokens

TikTok access tokens expire after 24 hours. Refresh tokens last much longer (typically 365 days). You must implement token refresh logic for any production system, otherwise your uploads will silently fail overnight:

def refresh_access_token(refresh_token: str) -> dict:
    """Refresh an expired access token using the refresh token."""
    url = "https://open.tiktokapis.com/v2/oauth/token/"
    
    payload = {
        "client_key": CLIENT_KEY,
        "client_secret": CLIENT_SECRET,
        "grant_type": "refresh_token",
        "refresh_token": refresh_token,
    }
    
    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    
    response = requests.post(url, data=payload, headers=headers)
    response.raise_for_status()
    
    token_data = response.json()
    
    if "access_token" not in token_data:
        raise ValueError(f"Token refresh failed: {token_data}")
    
    # IMPORTANT: Store the new refresh_token — it rotates on each refresh
    return token_data

Critical detail: TikTok rotates the refresh token on every use. When you call this function, store the new refresh token from the response. If you keep using the old one, it will be invalidated and the user will need to re-authorize.

Uploading Videos: The Two-Phase Process to Post TikTok Videos via API

TikTok’s Content Posting API uses a two-phase upload process. First, you initialize the upload and tell TikTok about the video. Then, you upload the actual file bytes. Finally, you publish. Understanding this flow is the core of learning how to post TikTok videos via API using Python.

Post TikTok videos via API using Python — upload flow diagram showing the two-phase process
The TikTok Content Posting API uses a multi-step upload and publish process to post TikTok videos via API using Python.

Upload Method Selection

TikTok supports two upload methods. Choose based on your file size and infrastructure:

Method How It Works Best For
FILE_UPLOAD Upload video bytes directly to TikTok in chunks Files on your server or local machine
PULL_FROM_URL Provide a public URL; TikTok downloads the file itself Files already hosted on CDN/cloud storage

We will implement both methods below.

Method A: Direct File Upload (Chunked)

This is the most common approach when you post TikTok videos via API using Python. You send the video file in chunks of exactly 5,242,880 bytes (5 MB) to TikTok’s upload endpoint. Here is the complete implementation:

import os
import math
import requests

CHUNK_SIZE = 5_242_880  # 5 MB — required by TikTok

def init_direct_upload(access_token: str, video_path: str, caption: str) -> dict:
    """Phase 1: Initialize the upload and get the upload URL."""
    file_size = os.path.getsize(video_path)
    total_chunks = math.ceil(file_size / CHUNK_SIZE)
    
    url = "https://open.tiktokapis.com/v2/post/publish/inbox/video/init/"
    
    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json; charset=UTF-8",
    }
    
    payload = {
        "post_info": {
            "title": caption[:150],  # TikTok caption limit
            "privacy_level": "SELF_ONLY",  # Use SELF_ONLY for testing
            "disable_duet": False,
            "disable_comment": False,
            "disable_stitch": False,
        },
        "source_info": {
            "source": "FILE_UPLOAD",
            "video_size": file_size,
            "chunk_size": CHUNK_SIZE,
            "total_chunk_count": total_chunks,
        },
    }
    
    response = requests.post(url, json=payload, headers=headers)
    response.raise_for_status()
    
    data = response.json()
    
    if data.get("error", {}).get("code") != "ok":
        raise ValueError(f"Upload init failed: {data}")
    
    return {
        "publish_id": data["data"]["publish_id"],
        "upload_url": data["data"]["upload_url"],
        "total_chunks": total_chunks,
        "file_size": file_size,
    }


def upload_chunks(upload_url: str, video_path: str, file_size: int, total_chunks: int):
    """Phase 2: Upload the video file in chunks."""
    with open(video_path, "rb") as f:
        for chunk_index in range(total_chunks):
            chunk_data = f.read(CHUNK_SIZE)
            chunk_start = chunk_index * CHUNK_SIZE
            chunk_end = min(chunk_start + len(chunk_data), file_size) - 1
            
            headers = {
                "Content-Type": "video/mp4",
                "Content-Length": str(len(chunk_data)),
                "Content-Range": f"bytes {chunk_start}-{chunk_end}/{file_size}",
            }
            
            response = requests.put(upload_url, data=chunk_data, headers=headers)
            
            if response.status_code not in (200, 201, 206):
                raise ValueError(
                    f"Chunk {chunk_index + 1}/{total_chunks} failed: "
                    f"{response.status_code} — {response.text}"
                )
            
            print(f"Uploaded chunk {chunk_index + 1}/{total_chunks} "
                  f"({chunk_end + 1}/{file_size} bytes)")
    
    print("All chunks uploaded successfully.")

Method B: Pull from URL

If your video is already hosted on a CDN, S3 bucket, or any publicly accessible URL, this method is simpler — TikTok downloads the file directly:

def init_url_upload(access_token: str, video_url: str, caption: str) -> dict:
    """Initialize upload by providing a public video URL for TikTok to pull."""
    url = "https://open.tiktokapis.com/v2/post/publish/inbox/video/init/"
    
    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json; charset=UTF-8",
    }
    
    payload = {
        "post_info": {
            "title": caption[:150],
            "privacy_level": "SELF_ONLY",
            "disable_duet": False,
            "disable_comment": False,
            "disable_stitch": False,
        },
        "source_info": {
            "source": "PULL_FROM_URL",
            "video_url": video_url,
        },
    }
    
    response = requests.post(url, json=payload, headers=headers)
    response.raise_for_status()
    
    data = response.json()
    
    if data.get("error", {}).get("code") != "ok":
        raise ValueError(f"URL upload init failed: {data}")
    
    return {"publish_id": data["data"]["publish_id"]}
    
# Usage:
# result = init_url_upload(access_token, "https://cdn.example.com/video.mp4", "My caption #fyp")

Important: The URL must be publicly accessible (no authentication required), return proper Content-Type headers, and the file must be in a supported format (.mp4, .mov, or .webm). Pre-signed S3 URLs work perfectly for this.

Checking Upload Status When You Post TikTok Videos via API

After uploading, TikTok processes the video asynchronously. You need to poll the status endpoint to know when your video is live. This is a step many tutorials skip, but it is essential when you post TikTok videos via API using Python in production systems:

import time

def check_publish_status(access_token: str, publish_id: str, max_attempts: int = 15) -> dict:
    """Poll TikTok until the video is published or fails."""
    url = "https://open.tiktokapis.com/v2/post/publish/status/fetch/"
    
    headers = {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json; charset=UTF-8",
    }
    
    payload = {"publish_id": publish_id}
    
    for attempt in range(1, max_attempts + 1):
        response = requests.post(url, json=payload, headers=headers)
        response.raise_for_status()
        
        data = response.json()
        status = data.get("data", {}).get("status")
        
        print(f"Attempt {attempt}/{max_attempts}: status = {status}")
        
        if status == "PUBLISH_COMPLETE":
            print(f"Video published! ID: {data['data'].get('publicaly_available_post_id', ['N/A'])}")
            return data
        
        elif status in ("FAILED", "PUBLISH_FAILED"):
            fail_reason = data.get("data", {}).get("fail_reason", "Unknown")
            raise ValueError(f"Publish failed: {fail_reason}")
        
        # Status is PROCESSING_UPLOAD or PROCESSING_DOWNLOAD — wait and retry
        wait_time = min(5 * attempt, 30)  # Exponential backoff, max 30s
        time.sleep(wait_time)
    
    raise TimeoutError(f"Video still processing after {max_attempts} attempts")

The status will transition through these states:

Status Meaning Action
PROCESSING_UPLOAD TikTok is receiving/processing your file chunks Wait and poll again
PROCESSING_DOWNLOAD TikTok is downloading from your URL (PULL_FROM_URL only) Wait and poll again
PROCESSING_PUBLISH Video is being encoded and prepared for feed Wait and poll again
PUBLISH_COMPLETE Video is live on TikTok Done — log the video ID
FAILED Upload or processing failed Check fail_reason, retry or alert

Complete Python Script to Post TikTok Videos via API

Here is the complete end-to-end function that ties all the pieces together into a single call. This is the production-ready code you need to post TikTok videos via API using Python:

def post_video_to_tiktok(
    access_token: str,
    video_path: str,
    caption: str = "Check this out! #fyp",
    privacy_level: str = "SELF_ONLY",
) -> dict:
    """
    Complete workflow to post TikTok videos via API using Python.
    Upload a local video file to TikTok and wait for publishing.
    
    Args:
        access_token: Valid OAuth2 access token with video.upload + video.publish scopes
        video_path: Path to the video file (.mp4, .mov, or .webm)
        caption: Video caption (max 150 characters)
        privacy_level: SELF_ONLY, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, or PUBLIC_TO_EVERYONE
    
    Returns:
        dict with publish status and video ID
    """
    # Validate file
    if not os.path.exists(video_path):
        raise FileNotFoundError(f"Video file not found: {video_path}")
    
    file_size = os.path.getsize(video_path)
    if file_size > 4 * 1024 * 1024 * 1024:  # 4 GB
        raise ValueError("File exceeds TikTok's 4GB maximum size limit")
    
    if file_size < 1024:  # Sanity check
        raise ValueError("File appears too small to be a valid video")
    
    ext = os.path.splitext(video_path)[1].lower()
    if ext not in (".mp4", ".mov", ".webm"):
        raise ValueError(f"Unsupported format: {ext}. Use .mp4, .mov, or .webm")
    
    print(f"Uploading: {video_path} ({file_size / 1024 / 1024:.1f} MB)")
    print(f"Caption: {caption[:150]}")
    print(f"Privacy: {privacy_level}")
    
    # Phase 1: Initialize
    init_data = init_direct_upload(access_token, video_path, caption)
    print(f"Upload initialized. Publish ID: {init_data['publish_id']}")
    
    # Phase 2: Upload chunks
    upload_chunks(
        upload_url=init_data["upload_url"],
        video_path=video_path,
        file_size=init_data["file_size"],
        total_chunks=init_data["total_chunks"],
    )
    
    # Phase 3: Wait for publishing
    result = check_publish_status(access_token, init_data["publish_id"])
    
    return result


# === Main execution ===
if __name__ == "__main__":
    load_dotenv()
    
    ACCESS_TOKEN = os.getenv("TIKTOK_ACCESS_TOKEN")  # From OAuth flow
    VIDEO_FILE = "./my_video.mp4"
    CAPTION = "Automated upload via Python 🐍 #coding #automation #fyp"
    
    result = post_video_to_tiktok(
        access_token=ACCESS_TOKEN,
        video_path=VIDEO_FILE,
        caption=CAPTION,
        privacy_level="SELF_ONLY",  # Change to PUBLIC_TO_EVERYONE for production
    )
    
    print(f"\nResult: {result}")

Handling Errors and Rate Limits When Posting TikTok Videos via Python API

Production deployments that post TikTok videos via API using Python must handle the reality that API calls fail — networks drop, tokens expire, and rate limits are hit. Here are the errors you will encounter most often and how to handle each one:

Error Code HTTP Status Cause Solution
access_token_invalid 401 Token expired or revoked Call refresh_access_token() and retry
spam_risk_too_many_posts 403 Exceeded daily upload quota (~15/day) Queue remaining uploads for next 24h window
invalid_file_upload 400 File format, size, or chunk size mismatch Validate file specs before uploading
scope_not_authorized 403 Token missing required scopes Re-authorize with video.upload,video.publish scopes
rate_limit_exceeded 429 Too many API calls in short period Implement exponential backoff with jitter

Here is a resilient wrapper that handles the most common failure modes when you post TikTok videos via API using Python:

import time
import random

def resilient_post(
    access_token: str,
    refresh_token: str,
    video_path: str,
    caption: str,
    max_retries: int = 3,
) -> dict:
    """Upload with automatic token refresh and retry logic."""
    
    current_access_token = access_token
    current_refresh_token = refresh_token
    
    for attempt in range(1, max_retries + 1):
        try:
            return post_video_to_tiktok(
                access_token=current_access_token,
                video_path=video_path,
                caption=caption,
                privacy_level="PUBLIC_TO_EVERYONE",
            )
        
        except requests.exceptions.HTTPError as e:
            status_code = e.response.status_code if e.response else None
            
            if status_code == 401:
                # Token expired — refresh and retry
                print("Access token expired. Refreshing...")
                token_data = refresh_access_token(current_refresh_token)
                current_access_token = token_data["access_token"]
                current_refresh_token = token_data["refresh_token"]
                # Save new tokens to your database/env here
                continue
            
            elif status_code == 429:
                # Rate limited — wait with jitter
                wait = (2 ** attempt) + random.uniform(0, 1)
                print(f"Rate limited. Waiting {wait:.1f}s before retry...")
                time.sleep(wait)
                continue
            
            elif status_code == 403:
                error_body = e.response.json() if e.response else {}
                if "spam_risk" in str(error_body):
                    print("Daily upload limit reached. Try again in 24 hours.")
                    raise  # Don't retry — wait for quota reset
                raise
            
            else:
                raise
        
        except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
            wait = (2 ** attempt) + random.uniform(0, 1)
            print(f"Network error on attempt {attempt}: {e}. Retrying in {wait:.1f}s...")
            time.sleep(wait)
    
    raise RuntimeError(f"Failed after {max_retries} attempts")

Production Architecture: Scheduling and Queue Management for TikTok API Python

For real-world deployments where you post TikTok videos via API using Python, you will want to decouple video submission from actual uploading. A task queue architecture prevents rate-limit issues and handles failures gracefully. Here is a simplified architecture using Python’s built-in capabilities:

import json
import sqlite3
from datetime import datetime, timedelta

class TikTokUploadQueue:
    """Simple SQLite-backed upload queue for scheduled TikTok posting."""
    
    def __init__(self, db_path: str = "upload_queue.db"):
        self.conn = sqlite3.connect(db_path)
        self.conn.execute("""
            CREATE TABLE IF NOT EXISTS upload_queue (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                video_path TEXT NOT NULL,
                caption TEXT NOT NULL,
                scheduled_at TEXT NOT NULL,
                status TEXT DEFAULT 'pending',
                publish_id TEXT,
                tiktok_video_id TEXT,
                error_message TEXT,
                created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_at TEXT DEFAULT CURRENT_TIMESTAMP
            )
        """)
        self.conn.commit()
    
    def schedule(self, video_path: str, caption: str, scheduled_at: datetime):
        """Add a video to the upload queue."""
        self.conn.execute(
            "INSERT INTO upload_queue (video_path, caption, scheduled_at) VALUES (?, ?, ?)",
            (video_path, caption, scheduled_at.isoformat()),
        )
        self.conn.commit()
        print(f"Scheduled: {video_path} at {scheduled_at.isoformat()}")
    
    def get_due_uploads(self) -> list:
        """Get all uploads that are due for processing."""
        now = datetime.utcnow().isoformat()
        cursor = self.conn.execute(
            "SELECT id, video_path, caption FROM upload_queue "
            "WHERE status = 'pending' AND scheduled_at <= ? "
            "ORDER BY scheduled_at ASC LIMIT 5",  # Process max 5 to stay under rate limits
            (now,),
        )
        return cursor.fetchall()
    
    def mark_complete(self, queue_id: int, publish_id: str, video_id: str = None):
        """Mark an upload as successfully completed."""
        self.conn.execute(
            "UPDATE upload_queue SET status = 'complete', publish_id = ?, "
            "tiktok_video_id = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
            (publish_id, video_id, queue_id),
        )
        self.conn.commit()
    
    def mark_failed(self, queue_id: int, error: str):
        """Mark an upload as failed."""
        self.conn.execute(
            "UPDATE upload_queue SET status = 'failed', error_message = ?, "
            "updated_at = CURRENT_TIMESTAMP WHERE id = ?",
            (error, queue_id),
        )
        self.conn.commit()


def process_queue(access_token: str, refresh_token: str):
    """Process all due uploads in the queue. Run this via cron every 5 minutes."""
    queue = TikTokUploadQueue()
    due = queue.get_due_uploads()
    
    if not due:
        print("No uploads due.")
        return
    
    print(f"Processing {len(due)} due upload(s)...")
    
    for queue_id, video_path, caption in due:
        try:
            result = resilient_post(access_token, refresh_token, video_path, caption)
            publish_id = result.get("data", {}).get("publish_id", "unknown")
            queue.mark_complete(queue_id, publish_id)
            print(f"✓ Upload {queue_id} complete: {publish_id}")
            
            # Respect rate limits — wait between uploads
            time.sleep(10)
            
        except Exception as e:
            queue.mark_failed(queue_id, str(e))
            print(f"✗ Upload {queue_id} failed: {e}")

Set up a cron job to process the queue every 5 minutes:

*/5 * * * * cd /home/user/tiktok-poster && /usr/bin/python3 -c "from tiktok_upload import process_queue; process_queue('TOKEN', 'REFRESH')" >> /var/log/tiktok_upload.log 2>&1

File Specifications Reference for TikTok Video API Upload

Before you post TikTok videos via API using Python, ensure each file meets TikTok’s technical requirements. Files that violate these specs will be silently rejected or produce low-quality results:

Specification Requirement Notes
Format .mp4, .mov, .webm .avi and .mkv are rejected
Codec H.264 recommended H.265 works but may increase processing time
Duration 3 seconds – 10 minutes Maximum varies by region and account type
File Size 4 GB maximum Keep under 500 MB for reliability
Chunk Size Exactly 5,242,880 bytes (5 MB) Last chunk can be smaller
Resolution 1080×1920 recommended (9:16) Below 720p may be deprioritized in the feed
Frame Rate 30 fps recommended 60 fps supported but increases file size
Audio AAC, 44.1 kHz Videos without audio are allowed but underperform

You can validate files before uploading with a simple pre-check function:

import subprocess
import json as json_module

def validate_video(video_path: str) -> dict:
    """Validate video file specs before uploading to TikTok."""
    if not os.path.exists(video_path):
        return {"valid": False, "error": "File not found"}
    
    file_size = os.path.getsize(video_path)
    ext = os.path.splitext(video_path)[1].lower()
    
    errors = []
    
    if ext not in (".mp4", ".mov", ".webm"):
        errors.append(f"Unsupported format: {ext}")
    
    if file_size > 4 * 1024**3:
        errors.append(f"File too large: {file_size / 1024**3:.1f} GB (max 4 GB)")
    
    if file_size < 1024:
        errors.append("File too small — likely corrupted")
    
    # Use ffprobe for detailed validation (requires ffmpeg installed)
    try:
        result = subprocess.run(
            [
                "ffprobe", "-v", "quiet", "-print_format", "json",
                "-show_format", "-show_streams", video_path
            ],
            capture_output=True, text=True, timeout=30,
        )
        probe = json_module.loads(result.stdout)
        
        duration = float(probe["format"].get("duration", 0))
        if duration < 3:
            errors.append(f"Too short: {duration:.1f}s (min 3s)")
        if duration > 600:
            errors.append(f"Too long: {duration:.1f}s (max 600s)")
        
        video_stream = next(
            (s for s in probe.get("streams", []) if s["codec_type"] == "video"), None
        )
        if video_stream:
            width = int(video_stream.get("width", 0))
            height = int(video_stream.get("height", 0))
            if height < 720:
                errors.append(f"Resolution too low: {width}x{height} (min 720p)")
    except (FileNotFoundError, subprocess.TimeoutExpired):
        pass  # ffprobe not installed — skip detailed checks
    
    return {
        "valid": len(errors) == 0,
        "file_size_mb": round(file_size / 1024 / 1024, 1),
        "format": ext,
        "errors": errors,
    }

Common Mistakes When You Post TikTok Videos via API Using Python

After helping developers implement how to post TikTok videos via API using Python, these are the mistakes that come up repeatedly:

Mistake What Happens How to Fix It
Not rotating refresh tokens Auth breaks silently after first token refresh Always store the new refresh token from each refresh response
Wrong chunk size invalid_file_upload error Use exactly 5,242,880 bytes (last chunk can be smaller)
Testing with PUBLIC_TO_EVERYONE in sandbox Upload succeeds but video is invisible Sandbox videos are always private — use SELF_ONLY until approved
No status polling Assume upload succeeded when it’s still processing Always poll the status endpoint with exponential backoff
Ignoring rate limits Account gets temporarily blocked from API uploads Cap at 10-12 uploads/day to stay safely under the ~15/day limit
Hardcoding tokens Tokens expire and the script breaks overnight Store tokens in a database and implement automatic refresh

API vs. No-Code: Choosing the Right Approach to Post TikTok Videos

Building a custom Python integration to post TikTok videos via API using Python gives you maximum control, but it is not the right choice for everyone. Here is how the DIY API approach compares to using a managed service:

Factor Custom Python (API) Managed Service (Repostit)
Setup Time Hours to days (dev + TikTok app review) 5–10 minutes
Technical Skill Required Python, OAuth 2.0, API design None
Cross-Platform Support Build each integration separately TikTok, Instagram, YouTube, Facebook built-in
Watermark Removal Build your own or use third-party library Automatic
Token Management You handle refresh logic and storage Handled automatically
Rate Limit Handling You implement queue and backoff logic Built-in queue management
Customization Unlimited — full control over every aspect Template-based configuration
Cost Free (your development time + server costs) Free trial, then paid plans
Best For Developers building products or custom workflows Creators and agencies who want results without code

If you are a developer building a product, internal tool, or custom pipeline, the API approach to post TikTok videos via API using Python gives you full control. If you are a creator or agency that wants automated cross-posting without writing code, Repostit handles everything covered in this guide, plus Instagram Reels, YouTube Shorts, and Facebook Reels, out of the box.

Frequently Asked Questions About Posting TikTok Videos via API

Does TikTok have a public API for uploading videos?

Yes. TikTok offers the Content Posting API, which allows developers to post TikTok videos via API using Python or any other programming language. You need to create a TikTok developer app, implement OAuth 2.0 authentication, and submit your app for review to move beyond sandbox mode.

How many videos can I post to TikTok via API per day?

Standard creator accounts are limited to approximately 15 video uploads per 24-hour rolling period via the API. This limit is separate from manual in-app uploads. Exceeding this limit triggers a spam_risk_too_many_posts error.

What video formats does the TikTok API accept?

The TikTok Content Posting API accepts .mp4, .mov, and .webm files. H.264 is the recommended codec. Files can be up to 4 GB in size and must be between 3 seconds and 10 minutes in duration.

Can I schedule TikTok posts via the API using Python?

The TikTok API does not have a native scheduling parameter. However, you can implement scheduling in Python using a task queue (like Celery, cron, or a simple SQLite-backed database queue) that triggers API uploads at specific times to post TikTok videos via API using Python on a schedule.

How long do TikTok API access tokens last?

TikTok access tokens expire after 24 hours. Refresh tokens last approximately 365 days. You must implement token refresh logic for any production system — and remember that TikTok rotates the refresh token on every use.

Is there a Python SDK for the TikTok API?

TikTok does not provide an official Python SDK as of 2026. You interact with the API using standard HTTP requests via the requests library. The code examples in this guide provide a complete working implementation to post TikTok videos via API using Python.

Can I post to TikTok and Instagram Reels simultaneously using Python?

Yes, you can build separate API integrations for both platforms to post TikTok videos via API using Python alongside Instagram. However, this requires maintaining two OAuth flows, two upload pipelines, and two sets of rate limit handling. Services like Repostit handle multi-platform posting without code.

Related Resources

Continue building your social media automation stack after learning how to post TikTok videos via API using Python:

Official Documentation

Start Using Python to Post TikTok Videos via API Today

You now have everything you need to post TikTok videos via API using Python, from OAuth authentication and PKCE flows to chunked file uploads, status polling, error handling, and production queue management. The complete code in this guide is copy-paste ready and handles the edge cases that most tutorials ignore.

For developers, this is the foundation for building custom content pipelines, SaaS tools, or agency-scale automation. For creators who would rather skip the code entirely, Repostit wraps all of this complexity into a point-and-click interface that handles TikTok, Instagram, YouTube, and Facebook simultaneously.

Whichever path you choose, learning to post TikTok videos via API using Python is the future of content distribution. The creators and businesses that automate their publishing workflows in 2026 will outpace those still uploading manually — every single time.

Post once. Repostit shares it everywhere else.

14 days free. No credit card needed.

Start your free trial

Keep reading

AI Agents for Social Media Automation Guide (2026)
CyberAI Agents for Social Media Automation Guide (2026)AI Agents for Social Media: Roles, Tools, and Automation in 2026 AI agents for social media are no longer a futuristic concept, they are already here, posting content, moderating communities, and even building their own digital religions. From autonomous bots chatting on AI-only platforms like Moltbook to practical agentic workflows that schedule, repurpose, and publish […]Mar 2, 2026