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.

500 free credits on signup — 250 lookups across Instagram, TikTok, X and Facebook. Credits never expire.

Related guides