You need to pull video data from TikTok or Douyin, but both platforms fight scrapers hard. Rate limits, watermarks, anti-bot detection — the usual mess.
Douyin_TikTok_Download_API is an open-source tool that handles all of that for you. You self-host it, feed it URLs, and get back clean JSON data or watermark-free downloads.
By the end of this guide, you'll have a working instance running locally or on a VPS, configured with valid cookies, and ready to accept API requests from your own scripts.
What Is Douyin_TikTok_Download_API?
Douyin_TikTok_Download_API is a self-hosted, open-source Python tool that scrapes video metadata and downloads from TikTok, Douyin, and Bilibili. It uses FastAPI for REST endpoints and HTTPX for async requests. Deploy it on your own server, pass in a video URL, and get back structured JSON data — including direct links to watermark-free video files.
The project handles X-Bogus and A_Bogus signature generation internally. You don't need to reverse-engineer TikTok's request signing yourself.
Prerequisites
Before you start, make sure you have:
- Python 3.8+ installed (3.10 or 3.11 recommended)
- Docker and Docker Compose (if using the Docker deployment path)
- Git for cloning the repository
- A VPS or local machine that can access TikTok and Douyin (US-based servers work best)
- A web browser for extracting cookies (Chrome or Firefox)
One thing to know upfront: Douyin's API endpoints require valid browser cookies. Without them, most Douyin-related endpoints will fail silently or return empty data.
TikTok endpoints are less strict but still benefit from fresh cookies.
Step 1: Clone the Repository
Start by pulling the project from GitHub.
# Terminal
git clone https://github.com/Evil0ctal/Douyin_TikTok_Download_API.git
cd Douyin_TikTok_Download_API
The project structure looks like this:
./Douyin_TikTok_Download_API
├── app/
│ ├── api/ # FastAPI endpoints
│ ├── download/ # Download handler
│ └── web/ # PyWebIO web interface
├── crawlers/
│ ├── douyin/web/ # Douyin scraper + config
│ ├── tiktok/web/ # TikTok scraper + config
│ ├── bilibili/web/# Bilibili scraper + config
│ └── hybrid/ # Mixed-URL parser
├── config.yaml # Main config
├── start.py # Entry point
└── requirements.txt
The crawlers/ directory is where the actual scraping logic lives. Each platform has its own config file — that's where your cookies go.
Step 2: Choose Your Deployment Method
You have two options: run it directly with Python, or use Docker. Docker is simpler and keeps your environment clean.
Option A: Docker (Recommended)
Pull the pre-built image and start the container:
# Terminal
docker pull evil0ctal/douyin_tiktok_download_api:latest
docker run -d \
--name douyin_tiktok_api \
-p 80:80 \
evil0ctal/douyin_tiktok_download_api
That's it. The API is now live at http://localhost/docs.
For production, use Docker Compose so you can mount your config files:
# docker-compose.yml
version: "3.9"
services:
douyin_tiktok_download_api:
image: evil0ctal/douyin_tiktok_download_api:latest
container_name: douyin_tiktok_api
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./crawlers/douyin/web/config.yaml:/app/crawlers/douyin/web/config.yaml:ro
- ./crawlers/tiktok/web/config.yaml:/app/crawlers/tiktok/web/config.yaml:ro
- ./config.yaml:/app/config.yaml:ro
environment:
- TZ=UTC
Mounting the config files as volumes means you can update cookies without rebuilding the container. Just edit the YAML and restart.
# Terminal
docker-compose up -d
Option B: Direct Python Install
If you prefer running it natively:
# Terminal
pip install -r requirements.txt
python start.py
The server starts on port 80 by default. You can change this in config.yaml.
Step 3: Extract and Configure Cookies
This is the step most people skip, and then wonder why nothing works. Douyin's API requires browser cookies to return data. Without them, you'll get empty responses or 403 errors.
How to Extract Douyin Cookies
- Open Chrome and go to douyin.com
- Log in with a valid account
- Open DevTools (F12) → Application tab → Cookies
- Copy the entire cookie string
Alternatively, use DevTools → Network tab. Click any request to douyin.com and grab the Cookie header value from the request headers.
How to Extract TikTok Cookies
Same process, but on tiktok.com. Log in, open DevTools, and copy the cookie string.
Paste Cookies Into Config
Open crawlers/douyin/web/config.yaml and replace the existing cookie value:
# crawlers/douyin/web/config.yaml
TokenManager:
douyin:
headers:
Cookie: "YOUR_DOUYIN_COOKIE_STRING_HERE"
Do the same for TikTok in crawlers/tiktok/web/config.yaml:
# crawlers/tiktok/web/config.yaml
TokenManager:
tiktok:
headers:
Cookie: "YOUR_TIKTOK_COOKIE_STRING_HERE"
Restart the service after updating cookies. If you're using Docker Compose:
# Terminal
docker-compose restart
Cookies expire. Douyin cookies typically last a few days to a couple of weeks. When your API starts returning empty data, your first move should always be refreshing the cookies.
Step 4: Test the API Endpoints
Once the server is running, open http://localhost/docs in your browser. You'll see a Swagger UI listing every available endpoint.
The two endpoints you'll use most:
Hybrid Video Data Parsing
This endpoint accepts any Douyin or TikTok URL and returns structured JSON:
# Terminal
curl -X GET \
"http://localhost/api/hybrid/video_data?url=https://www.tiktok.com/@username/video/7156033831819037994&minimal=false" \
-H "accept: application/json"
The response includes video title, author info, play counts, and direct download URLs — both with and without watermarks.
Set minimal=true if you only need the download links and basic metadata. The full response is quite large and includes every field TikTok returns.
Video Download
This endpoint returns the actual video file:
# Terminal
curl -X GET \
"http://localhost/api/download?url=https://v.douyin.com/L4FJNR3/&prefix=true&with_watermark=false" \
-H "accept: application/json"
The with_watermark=false parameter strips the TikTok/Douyin watermark. The prefix=true parameter adds the video author's name to the filename.
Note: TikTok video URLs returned by the API will throw HTTP 403 errors if you try to access them directly in a browser. You need to download them through the API's /api/download endpoint or use the proper headers.
Step 5: Call the API from Python
The web interface and curl commands are good for testing. For production use, you'll want to call the API from your own code.
Here's a Python script that fetches video data and downloads the file:
# fetch_video.py
import httpx
import asyncio
import json
API_BASE = "http://localhost"
async def get_video_data(url: str) -> dict:
"""Fetch metadata for a TikTok or Douyin video."""
async with httpx.AsyncClient(timeout=30) as client:
response = await client.get(
f"{API_BASE}/api/hybrid/video_data",
params={"url": url, "minimal": False}
)
response.raise_for_status()
return response.json()
async def main():
video_url = "https://www.tiktok.com/@username/video/7156033831819037994"
data = await get_video_data(video_url)
# Print the video title and play count
print(json.dumps(data, indent=2, ensure_ascii=False))
asyncio.run(main())
The project uses HTTPX internally, so using it in your client code keeps things consistent. But any HTTP library works — requests, aiohttp, whatever you prefer.
Batch Processing Multiple URLs
When you need to process a list of URLs, fire them off concurrently:
# batch_fetch.py
import httpx
import asyncio
API_BASE = "http://localhost"
async def fetch_one(client: httpx.AsyncClient, url: str) -> dict:
"""Fetch data for a single video URL."""
try:
resp = await client.get(
f"{API_BASE}/api/hybrid/video_data",
params={"url": url, "minimal": True}
)
resp.raise_for_status()
return {"url": url, "data": resp.json()}
except httpx.HTTPError as e:
return {"url": url, "error": str(e)}
async def batch_fetch(urls: list[str]) -> list[dict]:
"""Process multiple URLs concurrently."""
async with httpx.AsyncClient(timeout=30) as client:
tasks = [fetch_one(client, url) for url in urls]
return await asyncio.gather(*tasks)
urls = [
"https://www.tiktok.com/t/ZTR9nDNWq/",
"https://v.douyin.com/L4FJNR3/",
"https://www.tiktok.com/t/ZTR9nkkmL/",
]
results = asyncio.run(batch_fetch(urls))
for r in results:
if "error" in r:
print(f"FAILED: {r['url']} - {r['error']}")
else:
print(f"OK: {r['url']}")
Don't go crazy with concurrency though. The API processes requests asynchronously, but if you hammer it with 500 simultaneous requests, you'll hit TikTok's rate limits and start getting blocked.
I've found that 5–10 concurrent requests works well for sustained scraping. If you need higher throughput, add a delay between batches.
Step 6: Use the Pip Package (Alternative Approach)
If you don't want to run a full API server, the project also publishes a pip package you can import directly:
# Terminal
pip install douyin-tiktok-scraper
Then use it in your code:
# scraper_example.py
import asyncio
from douyin_tiktok_scraper.scraper import Scraper
api = Scraper()
async def parse_video(url: str) -> dict:
"""Parse any Douyin or TikTok URL."""
result = await api.hybrid_parsing(url)
return result
url = "https://www.tiktok.com/@username/video/7156033831819037994"
data = asyncio.run(parse_video(url))
print(data)
Fair warning: the pip package hasn't been updated as frequently as the main repo. If you run into issues, the self-hosted API server is the more reliable path.
Supported URL Formats
The hybrid parser handles a wide range of input formats. You don't need to clean up URLs before passing them in.
| Platform | Format | Example |
|---|---|---|
| Douyin | Share text (from app) | 7.43 pda:/ 让你在几秒钟之内记住我 https://v.douyin.com/L5pbfdP/ |
| Douyin | Short URL | https://v.douyin.com/L4FJNR3/ |
| Douyin | Full URL | https://www.douyin.com/video/6914948781100338440 |
| TikTok | Short URL | https://www.tiktok.com/t/ZTR9nDNWq/ |
| TikTok | Full URL | https://www.tiktok.com/@evil0ctal/video/7156033831819037994 |
| Bilibili | Video URL | https://www.bilibili.com/video/BV1xx411c7mD |
You can even paste multiple URLs in a single request to the web interface. The API handles them as a batch.
Key API Endpoints Reference
Here's a quick reference of the most useful endpoints. All of these are documented at /docs on your running instance.
| Endpoint | Method | Purpose |
|---|---|---|
/api/hybrid/video_data |
GET | Parse any TikTok/Douyin URL, return JSON metadata |
/api/download |
GET | Download video file (watermark-free option) |
/api/douyin/video_data |
GET | Douyin-specific video data |
/api/tiktok/video_data |
GET | TikTok-specific video data |
/api/douyin/user_profile |
GET | Fetch a Douyin user's profile info |
/api/tiktok/user_profile |
GET | Fetch a TikTok user's profile info |
/api/douyin/user_posts |
GET | Get all posts from a Douyin user |
/api/tiktok/user_posts |
GET | Get all posts from a TikTok user |
/api/douyin/video_comments |
GET | Fetch comments on a Douyin video |
/api/bilibili/video_data |
GET | Bilibili video metadata |
The hybrid endpoint is the most convenient one. It auto-detects the platform from the URL and routes to the right scraper internally.
Beyond video downloads, the user profile and post listing endpoints are where things get interesting. You can pull an entire creator's post history, including engagement metrics for each video.
The comments endpoint is useful for sentiment analysis or finding trending discussions. It returns threaded replies, so you get the full conversation structure.
Using the Web Interface
If you don't want to touch the API directly, the project includes a PyWebIO-based web UI at http://localhost/.
Open it in your browser and you'll see a simple text input. Paste one or more TikTok/Douyin URLs — the parser accepts multiple links at once, each on its own line.
Hit submit and the tool returns a parsed results page showing video metadata, thumbnail images, and direct download links.
The web interface is handy for one-off downloads or when you need to quickly check if a URL is parseable before building it into a script.
It also supports the Douyin share text format. You can copy the share text directly from the Douyin app (the one that looks like 7.43 pda:/ 让你在几秒钟之内记住我 https://v.douyin.com/L5pbfdP/) and the parser will extract the URL automatically.
How It Works Under the Hood
Understanding the internals helps when things break — and they will, eventually.
When you submit a URL to the /api/hybrid/video_data endpoint, here's what happens:
- URL detection: The hybrid parser identifies whether it's a Douyin, TikTok, or Bilibili link based on the domain.
- URL resolution: Short URLs (like
v.douyin.comlinks) get resolved to their full form via HTTP redirects. - ID extraction: The parser pulls the video ID from the resolved URL.
- Signature generation: For Douyin, the tool generates X-Bogus and A_Bogus parameters. These are anti-bot tokens that Douyin's API requires on every request.
- API request: The tool sends a request to the platform's internal web API (not the public one) using your configured cookies and the generated signatures.
- Data processing: The raw response gets cleaned up and returned as structured JSON.
The signature generation in step 4 is what makes this project valuable. TikTok and Douyin use custom JavaScript-based algorithms to generate these tokens. The project reimplements them in Python, which saves you from running a headless browser just to sign requests.
When platforms update their signature algorithms, this is the part that breaks. The maintainer typically pushes a fix within a few days, which is why keeping the repo updated matters.
Douyin_TikTok_Download_API vs Other TikTok Scrapers
You might wonder how this compares to other tools. Here's a quick breakdown:
vs. TikTokApi (Python pip package): TikTokApi requires Playwright and a real browser session. Douyin_TikTok_Download_API runs entirely server-side with no browser. This makes it faster and lighter for API-style access. However, TikTokApi handles some authentication flows that Douyin_TikTok_Download_API doesn't.
vs. TikTokDownloader (JoeanAmier): TikTokDownloader is more focused on bulk downloading — it's a CLI tool designed for pulling entire accounts. Douyin_TikTok_Download_API is more of an API server you integrate into your own systems.
vs. Building your own scraper: You absolutely can reverse-engineer TikTok's API yourself. The X-Bogus algorithm is publicly documented. But Douyin_TikTok_Download_API saves you weeks of work and has a community maintaining it against platform changes.
The main advantage of Douyin_TikTok_Download_API is that it gives you a clean REST API. Point your application at it, send URLs, get JSON back. No browser automation, no JavaScript execution, no session management.
Cookie Management: The One Thing That Will Break
Let me be direct: 90% of the issues you'll have with this tool come down to cookies.
Douyin's anti-scraping system checks cookies aggressively. Here's what I've learned from running this in production:
Use cookies from a logged-in account. Anonymous cookies work for basic parsing but fail on user profile endpoints and comment data.
Rotate cookies if you're doing high-volume scraping. One account's cookies can handle a few hundred requests per day. Beyond that, you'll start seeing rate limits.
Don't share cookies between instances. If you're running multiple deployments, each one should use cookies from a different account.
Set up a cookie refresh schedule. I check mine every 3 days. When I was lazy about it, my API went down for 2 days before I noticed.
If you're scraping TikTok from a US-based server, cookie issues are less common. Douyin is the problematic one — it's designed for Chinese users and the anti-bot system is more aggressive for non-Chinese IPs.
Using Proxies with Douyin_TikTok_Download_API
If you're running the API from a server that can't directly access Douyin (which is most servers outside China), you'll need a proxy.
The project doesn't have built-in proxy configuration, but you can set the HTTP_PROXY and HTTPS_PROXY environment variables before starting the server:
# Terminal
export HTTP_PROXY="http://your-proxy:8080"
export HTTPS_PROXY="http://your-proxy:8080"
python start.py
For Docker deployments, pass the proxy as an environment variable:
# docker-compose.yml (add to environment section)
environment:
- HTTP_PROXY=http://your-proxy:8080
- HTTPS_PROXY=http://your-proxy:8080
For Douyin scraping, you'll want a proxy with a Chinese IP. For TikTok, a US or European residential proxy works best.
If you're doing any serious volume, residential proxies are worth the investment. Datacenter IPs get flagged quickly by both platforms. Roundproxies offers residential proxy plans that work well for this kind of social media scraping.
Troubleshooting
"Empty response" or missing video data
Why: Your cookies are expired or invalid.
Fix: Extract fresh cookies from your browser and update the config files. Restart the service after updating.
HTTP 403 when accessing TikTok video URLs directly
Why: TikTok video CDN URLs require specific headers (Referer, User-Agent) to serve the file. Direct browser access is blocked.
Fix: Use the /api/download endpoint instead of trying to access video URLs directly. If you need to download in your own code, include the same headers the API uses:
# download_with_headers.py
import httpx
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Referer": "https://www.tiktok.com/",
}
async def download_video(video_url: str, output_path: str):
async with httpx.AsyncClient(headers=headers, follow_redirects=True) as client:
resp = await client.get(video_url)
with open(output_path, "wb") as f:
f.write(resp.content)
API starts but returns errors for Douyin URLs
Why: Your server can't reach Douyin's servers. Douyin blocks most non-Chinese IPs.
Fix: Use a proxy with a Chinese IP address, or deploy to a server in mainland China or Hong Kong.
"X-Bogus" or signature-related errors
Why: TikTok or Douyin updated their signature algorithm and the project hasn't caught up yet.
Fix: Check the GitHub issues page for reports of the same error. Pull the latest version of the repo — these fixes usually land within days of a platform update.
# Terminal
cd Douyin_TikTok_Download_API
git pull origin main
docker-compose down && docker-compose up -d --build
Docker container exits immediately
Why: Usually a missing dependency or a config syntax error.
Fix: Check the logs:
# Terminal
docker logs douyin_tiktok_api
The error message will tell you exactly what went wrong. Most often it's a malformed YAML in one of the config files.
Best Practices
Keep Your Instance Updated
TikTok and Douyin update their APIs and anti-bot systems regularly. The project maintainer (Evil0ctal) pushes fixes quickly — the repo has over 1,100 commits — but you need to actually pull those updates.
Set a reminder to check for updates at least weekly if you're running this in production.
Respect Rate Limits
Both platforms will throttle or ban IPs that make too many requests. In my experience, staying under 300 requests per hour per IP keeps you safe on TikTok. Douyin is stricter — aim for 100–150 per hour.
If you need more throughput, run multiple instances behind different proxies rather than hammering a single endpoint.
Don't Rely on the Demo Server
The project runs a demo at https://douyin.wtf/, but the maintainer has disabled the download functionality and can't guarantee uptime. The cookies on the demo server are the maintainer's own and may be invalid at any given time.
Always run your own instance.
Monitor Cookie Health
Build a simple health check that hits the API every hour with a known-good URL. If it returns empty data, fire an alert so you can refresh cookies before your pipeline breaks.
Wrapping Up
You now have a working Douyin_TikTok_Download_API instance that can parse video data and download watermark-free content from TikTok, Douyin, and Bilibili.
The biggest ongoing maintenance task is cookie management. Get that automated (or at least scheduled) and the rest runs itself.
If you need more endpoints or want to extend the tool, the codebase is clean Python with FastAPI — easy to read and modify. The crawlers/ directory is where you'd add support for new platforms or customize data extraction.
For your next steps, explore the user profile and comment endpoints. They open up interesting possibilities for content analysis and trend tracking that go well beyond simple video downloads.