Guides · Updated 2026-10-25
Download TikTok Videos Without Watermark in Python
When you save a video from the TikTok app, TikTok burns its logo and the uploader's username into the file. The original upload doesn't have that overlay, and that's the file you want for editing, archiving or feeding into a model.
This guide gets that file from Python. You send the TikTok URL to an API, get back HD and SD video links plus the soundtrack, and download the one you need.
Does TikTok's own API do this?
Not for arbitrary videos. The Display API returns a user's own videos after they log in to your app, as share and embed links rather than files. The Content Posting API uploads. The Research API is for approved academic researchers and returns metadata. None of them turns a public video URL into a downloadable MP4.
Setup
pip install requests- Get an API key by signing in with GitHub at soclip.dev — 500 free credits, 2 credits per video.
export SOCLIP_API_KEY=sc_live_...
Resolve and download one video
import os
import requests
API = "https://api.soclip.dev/v1/media"
HEADERS = {"Authorization": f"Bearer {os.environ['SOCLIP_API_KEY']}"}
def resolve(url: str) -> dict:
r = requests.post(API, headers=HEADERS, json={"url": url}, timeout=60)
body = r.json()
if not body.get("success"):
raise RuntimeError(f"{r.status_code}: {body.get('error')}")
return body["data"]def download(media_url: str, path: str) -> None:
with requests.get(media_url, stream=True, timeout=120) as r:
r.raise_for_status()
with open(path, "wb") as f:
for chunk in r.iter_content(chunk_size=1 << 16):
f.write(chunk)data = resolve("https://www.tiktok.com/@tiktok/video/7106594312292453675")
print(data["author"], data["duration"], "seconds")
hd = next(m for m in data["medias"] if m["quality"] == "hd")
download(hd["url"], "tiktok.mp4")medias comes back in a fixed order: hd video, sd video when TikTok has one, then audio. The HD file has no TikTok logo or username overlay. Anything the creator put into the video themselves — a logo, a credit to another account — is part of the original and stays.
Just the sound
audio = next((m for m in data["medias"] if m["type"] == "audio"), None)
if audio:
download(audio["url"], "sound.mp3")A list of videos
Name files by the video ID so reruns don't download the same video twice:
import re
def video_id(url: str) -> str:
m = re.search(r"/video/(\d+)", url)
return m.group(1) if m else re.sub(r"\W+", "_", url)[-40:]
os.makedirs("tiktok", exist_ok=True)
with open("tiktok_urls.txt") as f:
for url in filter(None, (l.strip() for l in f)):
path = os.path.join("tiktok", video_id(url) + ".mp4")
if os.path.exists(path):
continue
try:
data = resolve(url)
hd = data["medias"][0]
download(hd["url"], path)
print("saved", path)
except Exception as e:
print("failed", url, e)Failed lookups are refunded, so a bad URL in the list costs nothing. Retry only on 502 or 503; a 400 means the video is private, deleted or not a TikTok URL. The Instagram guide has a retry helper you can reuse.
From the command line
If you only need files and not a script, the CLI prints a direct link you can pipe into curl:
npm install -g soclip-cli
soclip config set-key sc_live_...
curl -L -o video.mp4 "$(soclip "https://www.tiktok.com/@tiktok/video/7106594312292453675" --quality hd)"More on the endpoint: TikTok video download API. Reposting other people's videos still needs their permission.