API Tải Video Douyin — Dành Cho Developer 2026
Bài này dành cho developer muốn tích hợp tính năng tải video Douyin vào app / bot / pipeline tự động. Bao gồm: endpoint reverse engineer, ví dụ code Python / Node.js / Go, rate limit, auth, cách xử lý captcha, và so sánh build tự vs dùng service như HapuDub API.
Mục lục
1. Douyin API — landscape hiện tại
Douyin (TikTok Trung Quốc, domain douyin.com) có 3 loại API:
- › Douyin Open Platform (chính thức): Chỉ mở cho app TQ đã verify với ByteDance. Developer ngoài TQ không đăng ký được.
- › TikTok for Developers (chính thức, khác DB): Dành cho TikTok (ngoài TQ), không trả về video Douyin.
- › Reverse-engineered endpoint (không chính thức): Cộng đồng open source đã reverse app Douyin web/mobile, biết endpoint
/api/douyin/web/fetch_one_video. Project nổi tiếng: evil0ctal/Douyin_TikTok_Download_API.
Hầu hết tool tải video Douyin public (bao gồm HapuDub) đều dùng cách #3. Ưu điểm: miễn phí, không cần đăng ký. Nhược: có thể bị Douyin block IP hoặc đổi signature khiến code fail. Cần maintain liên tục.
2. Endpoint tải video Douyin
Quy trình 2 bước:
- Extract aweme_id từ URL: URL Douyin có dạng
https://v.douyin.com/xxx(short) hoặchttps://www.douyin.com/video/7234567890. Cần redirect để lấyaweme_id(số 19-20 digit). - Gọi API /fetch_one_video: Pass
aweme_id→ nhận về JSON có fieldplay_addr.url_list[]= link MP4 không watermark.
Sample response structure
{
"aweme_detail": {
"aweme_id": "7234567890123456789",
"desc": "Video description",
"author": { "nickname": "creator_name", "uid": "123" },
"video": {
"play_addr": {
"url_list": [
"https://aweme.snssdk.com/play/video/xxx.mp4"
],
"width": 1080,
"height": 1920
},
"duration": 15000,
"cover": { "url_list": ["https://..."] }
},
"music": {
"title": "original_sound",
"play_url": { "url_list": ["..."] }
}
}
}
3. Ví dụ code
Sample dùng sidecar evil0ctal/Douyin_TikTok_Download_API đang chạy tại localhost:80:
Python (requests)
import requests
def download_douyin(url: str, out_path: str) -> bool:
# Step 1: fetch video metadata
api = "http://localhost/api/hybrid/video_data"
r = requests.get(api, params={"url": url})
data = r.json()
if data.get("code") != 200:
return False
video_url = data["data"]["video"]["play_addr"]["url_list"][0]
# Step 2: download MP4
mp4 = requests.get(video_url, stream=True)
with open(out_path, "wb") as f:
for chunk in mp4.iter_content(1024 * 1024):
f.write(chunk)
return True
download_douyin("https://v.douyin.com/xyz", "out.mp4")
Node.js (axios)
import axios from 'axios';
import fs from 'fs';
async function downloadDouyin(url, outPath) {
const api = 'http://localhost/api/hybrid/video_data';
const { data } = await axios.get(api, { params: { url } });
if (data.code !== 200) return false;
const videoUrl = data.data.video.play_addr.url_list[0];
const stream = await axios.get(videoUrl, { responseType: 'stream' });
stream.data.pipe(fs.createWriteStream(outPath));
return true;
}
Go (net/http)
package main
import (
"encoding/json"
"io"
"net/http"
"net/url"
"os"
)
func downloadDouyin(videoUrl, outPath string) error {
api := "http://localhost/api/hybrid/video_data"
q := url.Values{"url": {videoUrl}}
resp, err := http.Get(api + "?" + q.Encode())
if err != nil { return err }
defer resp.Body.Close()
var data struct {
Code int `json:"code"`
Data struct {
Video struct {
PlayAddr struct {
URLList []string `json:"url_list"`
} `json:"play_addr"`
} `json:"video"`
} `json:"data"`
}
json.NewDecoder(resp.Body).Decode(&data)
if data.Code != 200 { return nil }
mp4, _ := http.Get(data.Data.Video.PlayAddr.URLList[0])
defer mp4.Body.Close()
out, _ := os.Create(outPath)
defer out.Close()
io.Copy(out, mp4.Body)
return nil
}
4. Rate limit + captcha
Douyin rate-limit khá chặt — nếu gọi quá nhanh sẽ nhận:
- × HTTP 403 Forbidden: IP bị ban tạm thời (thường 10-30 phút).
- × Captcha challenge: Request trả về JSON có field
captcha_required: true. Phải giải captcha (image slider) trước khi tiếp tục. - ⚠️ Empty response: Thỉnh thoảng Douyin trả
play_addr.url_list: []dù video vẫn public — thử lại sau 30 giây.
Giải pháp
- Proxy rotation: Dùng 5-10 IP luân phiên (residential proxy tốt hơn datacenter). Giới hạn ~10 req/IP/phút.
- User-Agent rotation: Thay đổi UA mỗi request (dùng lib fake-useragent).
- Retry with backoff: Gặp 403, đợi 60s → retry. Gặp captcha, skip IP đó.
- Dùng service trung gian: HapuDub và một số service khác đã tự quản lý proxy pool + captcha → dev chỉ cần gọi 1 endpoint clean.
5. HapuDub API — alternative turn-key
Nếu không muốn maintain code reverse-engineer + proxy + captcha, có thể dùng HapuDub API. Tính năng:
- ✓ REST endpoint đơn giản, 1 URL → 1 response
- ✓ Tự động handle retry, proxy rotation, captcha (server-side)
- ✓ Hỗ trợ cả Douyin, TikTok, YouTube trong cùng endpoint
- ✓ Bonus: tích hợp pipeline dubbing AI + sub, không phải build lại
API access
Hiện HapuDub API chưa mở public. Developer quan tâm tích hợp vui lòng liên hệ hapuragroup@gmail.com với use case cụ thể. Pricing dựa trên volume request (có tier miễn phí cho developer indie).
6. Build tự vs dùng service
| Tiêu chí | Build tự | HapuDub API |
|---|---|---|
| Thời gian setup | 1-2 tuần | 1 giờ |
| Maintenance | Liên tục (Douyin đổi signature) | Không |
| Chi phí proxy | $20-50/tháng | Đã included |
| Khả năng kiểm soát | 100% | Dependencies |
| Phù hợp | High volume, tech team lớn | Startup, solo dev, MVP |
7. FAQ
HapuDub có API public không?
Chưa mở public keys. Liên hệ hapuragroup@gmail.com để request.
Douyin có API chính thức không?
Có (Open Platform) nhưng chỉ cho app TQ verify. Developer quốc tế dùng reverse-engineer.
Rate limit Douyin là bao nhiêu?
~100 req/phút/IP. Vượt = 403 hoặc captcha.
Có repo open-source nào đáng tin?
evil0ctal/Douyin_TikTok_Download_API trên GitHub — star cao, maintain active.
Bài viết liên quan
Cần API integration?
Liên hệ để request access HapuDub API — tích hợp Douyin + TikTok + YouTube trong 1 endpoint.
Liên hệ dev team →