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
- Go to the TikTok for Developers portal and sign up.
- Create a new application in the developer dashboard.
- Under Products, enable Content Posting API (also called “Video Upload” in some dashboard versions).
- Configure your redirect URI, this is where TikTok sends the authorization code after user login. For local development, use
https://localhost:3000/callback. - 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.

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
Related Resources
Continue building your social media automation stack after learning how to post TikTok videos via API using Python:
- TikTok to Instagram Reels Guide: Automate cross-posting between TikTok and Instagram without code.
- TikTok Watermark Removal: Learn why watermark removal matters and how to automate it.
- Content Repurposing Guide: Maximize every piece of content across all platforms.
Official Documentation
- TikTok Content Posting API — Getting Started: Official API documentation and reference.
- TikTok OAuth Token Management: Official guide to token lifecycle and refresh.
- TikTok Community Guidelines: Content policies to follow when posting programmatically.
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.