December 5, 2025
214 Views
Default

Leitfaden zum Herunterladen von Video-Links von mehreren Plattformen

Dieses Dokument erläutert im Detail, wie man nach dem Abrufen von Videolinks von Plattformen wie Douyin, TikTok, Bilibili, Xiaohongshu und Weibo Videodateien korrekt herunterlädt. Der Schwerpunkt liegt auf der Lösung häufiger Probleme wie Cross-Domain, Hotlink-Schutz und Request-Header-Validierung.

Leitfaden zum Herunterladen von Videolinks auf mehreren Plattformen

Dieses Dokument erläutert detailliert, wie Videodateien nach dem Abrufen von Videolinks von Plattformen wie Douyin, TikTok, Bilibili, Xiaohongshu, Weibo usw. korrekt heruntergeladen werden. Der Schwerpunkt liegt auf der Lösung häufiger Probleme wie Cross-Domain, Hotlink-Schutz und Header-Validierung.

Inhaltsverzeichnis


Allgemeine Problemübersicht

Nach dem Abrufen von Videolinks von verschiedenen Plattformen treten beim direkten Herunterladen in der Regel die folgenden Probleme auf:

ProblemtypBeschreibungLösung
Hotlink-Schutz (Referer)Der Server prüft die Herkunft der Anfrage und lehnt unzulässige Quellen abDen korrekten Referer-Header setzen
Cross-Domain (CORS)Die Browsersicherheitsrichtlinie blockiert Cross-Domain-AnfragenBackend-Proxy / Serverseitiger Download
User-Agent-ValidierungDer Server prüft die Client-KennungBrowser-UA simulieren
Cookie-ValidierungEinige Links erfordern einen Login-StatusGültige Cookies mitsenden
Ablaufzeit des LinksVideolinks haben ein AblaufdatumRechtzeitig verwenden, nach Ablauf neu abrufen
IP-BeschränkungEinige Links beschränken den Zugriff nach RegionEinen Proxy aus der entsprechenden Region verwenden

Douyin (Douyin)

Douyin-Videolinks liegen typischerweise in den folgenden Formen vor:

txt
1# 播放地址 (无水印)
2https://www.douyin.com/aweme/v1/play/?video_id=xxx&line=0&file_id=xxx
3
4# CDN 地址
5https://v26-web.douyinvod.com/xxx/xxx.mp4
6
7# 带水印下载地址
8https://aweme.snssdk.com/aweme/v1/playwm/?video_id=xxx

Download-Anforderungen

Request-HeaderErforderlich?Wert
RefererErforderlichhttps://www.douyin.com/
User-AgentEmpfohlenBrowser-UA
CookieOptionalFür einige HD-Links erforderlich

Beispiel für serverseitigen Download

python
1import httpx
2
3async def download_douyin_video(video_url: str, save_path: str) -> bool:
4    """
5    下载抖音视频
6
7    Args:
8        video_url: 视频播放地址
9        save_path: 保存路径
10
11    Returns:
12        是否下载成功
13    """
14    headers = {
15        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
16        "Referer": "https://www.douyin.com/",  # 必须
17        "Accept": "*/*",
18        "Accept-Encoding": "identity",  # 避免压缩,方便流式下载
19        "Range": "bytes=0-",  # 支持断点续传
20    }
21
22    async with httpx.AsyncClient(follow_redirects=True, timeout=60) as client:
23        async with client.stream("GET", video_url, headers=headers) as response:
24            if response.status_code in [200, 206]:
25                with open(save_path, "wb") as f:
26                    async for chunk in response.aiter_bytes(chunk_size=8192):
27                        f.write(chunk)
28                return True
29    return False

Frontend-Cross-Domain-Problem

Douyin-Videolinks unterstützen kein CORS; direkte Anfragen vom Frontend werden vom Browser blockiert:

javascript
1// ❌ 错误方式 - 会被 CORS 拦截
2fetch('https://v26-web.douyinvod.com/xxx.mp4')
3  .then(res => res.blob())  // CORS error!
4
5// ✅ 正确方式 - 使用后端代理
6fetch('/api/proxy/video?url=' + encodeURIComponent(videoUrl))
7  .then(res => res.blob())
8  .then(blob => {
9    const url = URL.createObjectURL(blob);
10    const a = document.createElement('a');
11    a.href = url;
12    a.download = 'video.mp4';
13    a.click();
14  });

Hinweise

  1. Ablaufzeit des Links: Douyin-Videolinks sind in der Regel 24 Stunden gültig
  2. Wasserzeichenfreie Links: Verwenden Sie play_addr statt download_addr
  3. HD-Links: Einige 4K-/Originalqualitätsvideos sind sehr groß; es wird empfohlen, segmentiert herunterzuladen, um einen einmaligen Downloadfehler zu vermeiden

TikTok

txt
1# 播放地址
2https://v16-webapp-prime.tiktok.com/video/tos/xxx.mp4
3
4# 无水印地址
5https://www.tiktok.com/aweme/v1/play/?video_id=xxx
6
7# 带水印地址
8https://v16-webapp.tiktok.com/video/tos/xxx.mp4

Download-Anforderungen

Request-HeaderErforderlich?Wert
RefererErforderlichhttps://www.tiktok.com/
User-AgentErforderlichBrowser-UA
CookieErforderlichErfordert das Feld tt_chain_token

Wichtig: Von der TikTok-Webversion zurückgegebene Videolinks können nur mit dem Cookie tt_chain_token heruntergeladen werden, andernfalls wird ein 403-Fehler zurückgegeben.

Request-HeaderErforderlich?Wert
User-AgentEmpfohlenBeliebiger UA
CookieNicht erforderlichFür App-Links gilt diese Einschränkung nicht

Empfehlung: Wenn Sie App-Links abrufen können, verwenden Sie bevorzugt App-Links, da dann kein Cookie-Problem behandelt werden muss.

Beispiel für serverseitigen Download

Download der Web-Version (erfordert tt_chain_token)

python
1import httpx
2
3async def download_tiktok_video_web(
4    video_url: str,
5    save_path: str,
6    tt_chain_token: str  # 必须提供
7) -> bool:
8    """
9    下载 TikTok Web 端视频
10
11    注意:
12    - Web 端链接必须携带 tt_chain_token Cookie
13    - tt_chain_token 可从浏览器或 API 响应中获取
14    """
15    headers = {
16        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
17        "Referer": "https://www.tiktok.com/",
18        "Accept": "video/webm,video/ogg,video/*;q=0.9,*/*;q=0.8",
19        "Accept-Language": "en-US,en;q=0.5",
20        "Cookie": f"tt_chain_token={tt_chain_token}",  # 必须
21        "Sec-Fetch-Dest": "video",
22        "Sec-Fetch-Mode": "no-cors",
23        "Sec-Fetch-Site": "cross-site",
24    }
25
26    async with httpx.AsyncClient(follow_redirects=True, timeout=60) as client:
27        async with client.stream("GET", video_url, headers=headers) as response:
28            if response.status_code in [200, 206]:
29                with open(save_path, "wb") as f:
30                    async for chunk in response.aiter_bytes(chunk_size=8192):
31                        f.write(chunk)
32                return True
33            elif response.status_code == 403:
34                print("下载失败: tt_chain_token 无效或缺失")
35    return False
python
1async def download_tiktok_video_app(video_url: str, save_path: str) -> bool:
2    """
3    下载 TikTok App 端视频
4
5    App 端链接无需 Cookie,直接下载即可
6    """
7    headers = {
8        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
9        "Accept": "*/*",
10    }
11
12    async with httpx.AsyncClient(follow_redirects=True, timeout=60) as client:
13        async with client.stream("GET", video_url, headers=headers) as response:
14            if response.status_code in [200, 206]:
15                with open(save_path, "wb") as f:
16                    async for chunk in response.aiter_bytes(chunk_size=8192):
17                        f.write(chunk)
18                return True
19    return False

Wie man tt_chain_token erhält

tt_chain_token ist das von TikTok für die Authentifizierung beim Video-Download verwendete Cookie; die Beschaffungsmethoden sind:

  1. Aus dem Browser abrufen: TikTok-Website öffnen, F12-Entwicklertools -> Application -> Cookies -> tt_chain_token finden

  2. Aus der API-Antwort abrufen: In den Set-Cookie-Headern einiger TikTok-API-Antworten kann dieser Wert enthalten sein

  3. TikHub API verwenden: Die API-Rückgabedaten können bereits ein verfügbares Token enthalten

python
1# 示例:从响应头提取 tt_chain_token
2def extract_tt_chain_token(response_headers: dict) -> str:
3    """从响应头中提取 tt_chain_token"""
4    cookies = response_headers.get("set-cookie", "")
5    for cookie in cookies.split(";"):
6        if "tt_chain_token=" in cookie:
7            return cookie.split("tt_chain_token=")[1].split(";")[0]
8    return ""

Regionseinschränkungen

TikTok-Videos können Regionseinschränkungen haben; einige Videos sind nur in bestimmten Ländern zugänglich:

python
1# 使用代理下载特定地区视频
2proxies = {
3    "http://": "http://us-proxy:8080",
4    "https://": "http://us-proxy:8080",
5}
6
7async with httpx.AsyncClient(proxies=proxies) as client:
8    # ...

Hinweise

  1. Regionseinschränkung: Einige Videos erfordern eine US-/Europa-IP, um zugänglich zu sein
  2. Ablaufzeit des Links: Die Gültigkeit des Links beträgt etwa 24 Stunden
  3. Wasserzeichenfrei: Bevorzugt das Feld downloadAddr verwenden

Bilibili (Bilibili)

Bilibili-Videolinks sind etwas Besonderes, Audio und Video sind getrennt:

txt
1# 视频流 (DASH)
2https://upos-sz-mirrorali.bilivideo.com/xxx/xxx.m4s
3
4# 音频流 (DASH)
5https://upos-sz-mirrorali.bilivideo.com/xxx/xxx.m4s
6
7# FLV 格式 (旧版)
8https://upos-sz-mirrorali.bilivideo.com/xxx/xxx.flv

Download-Anforderungen

Request-HeaderErforderlich?Wert
RefererErforderlichhttps://www.bilibili.com/
User-AgentEmpfohlenBrowser-UA
CookieHD, 4K erforderlichSESSDATA usw.
RangeEmpfohlenSegmentierter Download

Beispiel für serverseitigen Download

python
1import httpx
2import subprocess
3from pathlib import Path
4
5async def download_bilibili_video(
6    video_url: str,
7    audio_url: str,
8    save_path: str,
9    cookie: str = None
10) -> bool:
11    """
12    下载 B站 视频 (需要合并音视频)
13
14    Args:
15        video_url: 视频流地址
16        audio_url: 音频流地址
17        save_path: 最终保存路径
18        cookie: 可选,高清视频需要 SESSDATA
19    """
20    headers = {
21        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
22        "Referer": "https://www.bilibili.com/",  # 必须,否则 403
23        "Accept": "*/*",
24        "Accept-Encoding": "identity",
25        "Origin": "https://www.bilibili.com",
26    }
27
28    if cookie:
29        headers["Cookie"] = cookie
30
31    # 临时文件路径
32    video_temp = save_path + ".video.m4s"
33    audio_temp = save_path + ".audio.m4s"
34
35    async with httpx.AsyncClient(follow_redirects=True, timeout=120) as client:
36        # 下载视频流
37        async with client.stream("GET", video_url, headers=headers) as response:
38            if response.status_code not in [200, 206]:
39                return False
40            with open(video_temp, "wb") as f:
41                async for chunk in response.aiter_bytes(chunk_size=8192):
42                    f.write(chunk)
43
44        # 下载音频流
45        async with client.stream("GET", audio_url, headers=headers) as response:
46            if response.status_code not in [200, 206]:
47                return False
48            with open(audio_temp, "wb") as f:
49                async for chunk in response.aiter_bytes(chunk_size=8192):
50                    f.write(chunk)
51
52    # 使用 FFmpeg 合并音视频
53    try:
54        subprocess.run([
55            "ffmpeg", "-y",
56            "-i", video_temp,
57            "-i", audio_temp,
58            "-c:v", "copy",
59            "-c:a", "copy",
60            save_path
61        ], check=True, capture_output=True)
62
63        # 删除临时文件
64        Path(video_temp).unlink()
65        Path(audio_temp).unlink()
66        return True
67    except subprocess.CalledProcessError:
68        return False
QualitätAnmeldung erforderlich?Cookie-Anforderung
360P/480PNeinKeine
720PJaSESSDATA
1080PJaSESSDATA + Premium-Mitgliedschaft
4K/HDRJaSESSDATA + Premium-Mitgliedschaft

Hinweise

  1. Muss zusammengeführt werden: Im DASH-Format sind Audio und Video getrennt; sie müssen mit FFmpeg zusammengeführt werden
  2. Referer erforderlich: Ohne korrekten Referer wird 403 zurückgegeben
  3. Ablaufzeit des Links: Etwa 2 Stunden gültig
  4. Segmentierter Download: Für große Dateien wird empfohlen, mit dem Range-Header segmentiert herunterzuladen

Xiaohongshu (Xiaohongshu)

txt
1# 视频地址
2https://sns-video-bd.xhscdn.com/xxx.mp4
3https://sns-video-hw.xhscdn.com/xxx.mp4
4
5# 图片地址
6https://sns-img-bd.xhscdn.com/xxx.jpg

Download-Anforderungen

Request-HeaderErforderlich?Wert
RefererErforderlichhttps://www.xiaohongshu.com/
User-AgentEmpfohlenBrowser-UA
CookieOptionalFür einige Inhalte erforderlich

Beispiel für serverseitigen Download

python
1import httpx
2
3async def download_xiaohongshu_video(video_url: str, save_path: str) -> bool:
4    """
5    下载小红书视频
6
7    小红书对 Referer 检查较严格
8    """
9    headers = {
10        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
11        "Referer": "https://www.xiaohongshu.com/",  # 必须
12        "Accept": "*/*",
13        "Origin": "https://www.xiaohongshu.com",
14        "Sec-Fetch-Dest": "video",
15        "Sec-Fetch-Mode": "cors",
16        "Sec-Fetch-Site": "cross-site",
17    }
18
19    async with httpx.AsyncClient(follow_redirects=True, timeout=60) as client:
20        async with client.stream("GET", video_url, headers=headers) as response:
21            if response.status_code in [200, 206]:
22                with open(save_path, "wb") as f:
23                    async for chunk in response.aiter_bytes(chunk_size=8192):
24                        f.write(chunk)
25                return True
26    return False

Bild-Download

Auch Xiaohongshu-Bilder haben Hotlink-Schutz:

python
1async def download_xiaohongshu_image(image_url: str, save_path: str) -> bool:
2    """下载小红书图片"""
3    headers = {
4        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
5        "Referer": "https://www.xiaohongshu.com/",
6        "Accept": "image/avif,image/webp,image/apng,image/*,*/*;q=0.8",
7    }
8
9    async with httpx.AsyncClient(follow_redirects=True) as client:
10        response = await client.get(image_url, headers=headers)
11        if response.status_code == 200:
12            with open(save_path, "wb") as f:
13                f.write(response.content)
14            return True
15    return False

Hinweise

  1. Strenger Referer: Der Referer muss xiaohongshu.com enthalten
  2. CDN-Knoten: Unterschiedliche Knoten wie bd (Baidu Cloud), hw (Huawei Cloud) usw.
  3. Wasserzeichenfrei: Die von der API zurückgegebenen Links sind in der Regel wasserzeichenfrei

Weibo (Weibo)

Weibo-Videolinks gibt es in vielen Formaten:

txt
1# 标准视频
2https://f.video.weibocdn.com/xxx.mp4
3
4# 直播回放
5https://live.video.weibocdn.com/xxx.flv
6
7# 高清视频
8https://video.weibo.com/media/play?fid=xxx

Download-Anforderungen

Request-HeaderErforderlich?Wert
RefererErforderlichhttps://weibo.com/ oder https://m.weibo.cn/
User-AgentEmpfohlenBrowser-UA
CookieTeilweise erforderlichFür private Videos erforderlich

Beispiel für serverseitigen Download

python
1import httpx
2
3async def download_weibo_video(video_url: str, save_path: str) -> bool:
4    """
5    下载微博视频
6
7    微博支持多个 Referer 域名
8    """
9    headers = {
10        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
11        "Referer": "https://weibo.com/",  # 或 https://m.weibo.cn/
12        "Accept": "*/*",
13        "Accept-Encoding": "identity",
14    }
15
16    async with httpx.AsyncClient(follow_redirects=True, timeout=60) as client:
17        async with client.stream("GET", video_url, headers=headers) as response:
18            if response.status_code in [200, 206]:
19                with open(save_path, "wb") as f:
20                    async for chunk in response.aiter_bytes(chunk_size=8192):
21                        f.write(chunk)
22                return True
23    return False

Auswahl mehrerer Auflösungen

Weibo-Videos bieten in der Regel mehrere Auflösungen:

python
1def select_best_quality(media_info: dict) -> str:
2    """选择最高清晰度的视频链接"""
3    # 清晰度优先级
4    quality_priority = ["mp4_720p_mp4", "mp4_hd_mp4", "mp4_ld_mp4"]
5
6    playback_list = media_info.get("playback_list", [])
7
8    for quality in quality_priority:
9        for item in playback_list:
10            if item.get("quality_label") == quality:
11                return item.get("play_info", {}).get("url")
12
13    # 降级使用 stream_url
14    return media_info.get("stream_url")

Hinweise

  1. Referer-Domain: Unterstützt weibo.com und m.weibo.cn
  2. Mehrere Auflösungen: In den Rückgabedaten sind mehrere Auflösungen auswählbar
  3. Ablauf des Links: Einige Links haben eine zeitliche Begrenzung

YouTube

YouTube-Videolinks liegen typischerweise in den folgenden Formen vor:

txt
1# 标准视频流地址
2https://rr1---sn-xxx.googlevideo.com/videoplayback?expire=xxx&ei=xxx&ip=xxx&id=xxx&itag=xxx&source=youtube&...
3
4# 自适应流地址 (DASH)
5https://manifest.googlevideo.com/api/manifest/dash/...
6
7# 直播流地址 (HLS)
8https://manifest.googlevideo.com/api/manifest/hls_variant/...

Download-Anforderungen

Strenge IP-Beschränkung: Die Video-Stream-Adresse von YouTube unterliegt einer äußerst strengen Prüfung der IP-Geolokation; zum erfolgreichen Download muss eine IP aus Los Angeles, Kalifornien, USA verwendet werden, andernfalls wird ein 403-Forbidden-Fehler zurückgegeben.

Request-HeaderErforderlich?Wert
User-AgentErforderlichBrowser-UA
RefererEmpfohlenhttps://www.youtube.com/
OriginEmpfohlenhttps://www.youtube.com
Proxy-IPErforderlichIP aus Los Angeles, Kalifornien, USA

Erläuterung der IP-Regionseinschränkung

Die Video-Stream-Adresse von YouTube wird bei der Generierung an die IP-Adresse des Anfragenden gebunden; beim Download muss dieselbe regionale IP verwendet werden:

txt
1# 视频流 URL 中包含 IP 绑定参数
2https://rr1---sn-xxx.googlevideo.com/videoplayback?
3    expire=1234567890        # 过期时间
4    &ei=xxx                  # 加密标识
5    &ip=1.2.3.4             # 绑定的 IP 地址 (关键!)
6    &id=xxx
7    &itag=137               # 视频质量标识
8    &source=youtube
9    &...

Warum muss es eine IP aus Los Angeles sein?

  1. Die meisten YouTube-CDN-Knoten befinden sich an der US-Westküste
  2. Bei der Generierung der Video-Stream-URL wird basierend auf der Anforderungs-IP das nächstgelegene CDN ausgewählt
  3. Eine nicht übereinstimmende IP-Region beim Download führt zu einem 403-Fehler
  4. Los Angeles ist der Standort eines der wichtigsten Rechenzentren von YouTube und bietet die beste Kompatibilität

Beispiel für serverseitigen Download

python
1import httpx
2
3async def download_youtube_video(
4    video_url: str,
5    save_path: str,
6    proxy: str = None  # 必须是美国加州洛杉矶代理
7) -> bool:
8    """
9    下载 YouTube 视频
10
11    重要:
12    - 必须使用美国加利福尼亚州洛杉矶地区的代理 IP
13    - 其他地区 IP 会返回 403 Forbidden
14    - 视频流 URL 有时效性,通常 6 小时内有效
15    """
16    headers = {
17        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
18        "Referer": "https://www.youtube.com/",
19        "Origin": "https://www.youtube.com",
20        "Accept": "*/*",
21        "Accept-Language": "en-US,en;q=0.9",
22        "Accept-Encoding": "identity",  # 避免压缩
23        "Range": "bytes=0-",  # 支持断点续传
24        "Sec-Fetch-Dest": "video",
25        "Sec-Fetch-Mode": "no-cors",
26        "Sec-Fetch-Site": "cross-site",
27    }
28
29    # 代理配置 - 必须是洛杉矶 IP
30    proxies = None
31    if proxy:
32        proxies = {
33            "http://": proxy,
34            "https://": proxy,
35        }
36
37    async with httpx.AsyncClient(
38        follow_redirects=True,
39        timeout=120,
40        proxies=proxies
41    ) as client:
42        async with client.stream("GET", video_url, headers=headers) as response:
43            if response.status_code in [200, 206]:
44                with open(save_path, "wb") as f:
45                    async for chunk in response.aiter_bytes(chunk_size=8192):
46                        f.write(chunk)
47                return True
48            elif response.status_code == 403:
49                print("下载失败: IP 地区不符合要求,请使用美国加州洛杉矶的代理")
50            elif response.status_code == 410:
51                print("下载失败: 视频链接已过期,请重新获取")
52    return False

Trennung von Audio und Video

YouTube-HD-Videos (1080p+) verwenden das DASH-Format; Audio und Video sind getrennt:

python
1import subprocess
2from pathlib import Path
3
4async def download_youtube_video_with_audio(
5    video_url: str,
6    audio_url: str,
7    save_path: str,
8    proxy: str = None
9) -> bool:
10    """
11    下载 YouTube 视频并合并音频
12
13    YouTube 1080p 及以上清晰度的视频,音频和视频是分离的
14    需要分别下载后使用 FFmpeg 合并
15    """
16    video_temp = save_path + ".video.mp4"
17    audio_temp = save_path + ".audio.m4a"
18
19    # 下载视频流
20    success = await download_youtube_video(video_url, video_temp, proxy)
21    if not success:
22        return False
23
24    # 下载音频流
25    success = await download_youtube_video(audio_url, audio_temp, proxy)
26    if not success:
27        return False
28
29    # 使用 FFmpeg 合并
30    try:
31        subprocess.run([
32            "ffmpeg", "-y",
33            "-i", video_temp,
34            "-i", audio_temp,
35            "-c:v", "copy",
36            "-c:a", "aac",
37            save_path
38        ], check=True, capture_output=True)
39
40        # 删除临时文件
41        Path(video_temp).unlink()
42        Path(audio_temp).unlink()
43        return True
44    except subprocess.CalledProcessError as e:
45        print(f"FFmpeg 合并失败: {e}")
46        return False

Beispiel für die Proxy-Konfiguration

python
1# 推荐的代理配置 - 必须是洛杉矶地区
2LA_PROXIES = [
3    "http://user:pass@la-proxy1.example.com:8080",  # 洛杉矶代理 1
4    "http://user:pass@la-proxy2.example.com:8080",  # 洛杉矶代理 2
5    "socks5://user:pass@la-socks.example.com:1080", # SOCKS5 代理
6]
7
8# 验证代理 IP 是否在洛杉矶
9async def verify_proxy_location(proxy: str) -> bool:
10    """验证代理 IP 是否在洛杉矶地区"""
11    async with httpx.AsyncClient(proxies={"https://": proxy}) as client:
12        response = await client.get("https://ipapi.co/json/")
13        data = response.json()
14
15        city = data.get("city", "")
16        region = data.get("region", "")
17        country = data.get("country_code", "")
18
19        # 检查是否在加州洛杉矶
20        is_la = (
21            country == "US" and
22            region == "California" and
23            "Los Angeles" in city
24        )
25
26        if is_la:
27            print(f"✓ 代理 IP 位于: {city}, {region}, {country}")
28        else:
29            print(f"✗ 代理 IP 位于: {city}, {region}, {country} (不符合要求)")
30
31        return is_la

Zuordnungstabelle der Qualitätskennzeichnungen (itag)

itagAuflösungFormatEnthält Audio?
18360pMP4Ja
22720pMP4Ja
1371080pMP4Nein (muss zusammengeführt werden)
2481080pWebMNein (muss zusammengeführt werden)
2711440pWebMNein (muss zusammengeführt werden)
3132160pWebMNein (muss zusammengeführt werden)
140-M4A-AudioNur Audio
251-WebM-AudioNur Audio

Hinweise

  1. IP-Beschränkung ist extrem streng: Es muss eine IP aus Los Angeles, Kalifornien, USA verwendet werden; andere Regionen (einschließlich anderer US-Bundesstaaten) können ebenfalls fehlschlagen
  2. Ablaufzeit des Links: Die Video-Stream-URL ist in der Regel 6 Stunden gültig
  3. Trennung von Audio und Video: Bei Auflösungen über 720p müssen Audio und Video separat heruntergeladen und anschließend zusammengeführt werden
  4. Ratenbegrenzung: YouTube begrenzt die Download-Geschwindigkeit; für große Dateien wird segmentierter Download empfohlen
  5. Urheberrechtsschutz: Einige Videos sind durch DRM geschützt und können nicht direkt heruntergeladen werden

Frontend-Download-Lösung

Aufgrund von CORS-Beschränkungen kann das Frontend die Videos der meisten Plattformen nicht direkt herunterladen. Die folgenden Lösungen sind praktikabel:

Lösung 1: Backend-Proxy (empfohlen)

javascript
1// 前端请求后端代理接口
2async function downloadVideo(videoUrl, platform, filename) {
3  const proxyUrl = `/api/download/video?url=${encodeURIComponent(videoUrl)}&platform=${platform}`;
4
5  const response = await fetch(proxyUrl);
6  const blob = await response.blob();
7
8  // 创建下载链接
9  const url = URL.createObjectURL(blob);
10  const a = document.createElement('a');
11  a.href = url;
12  a.download = filename || 'video.mp4';
13  document.body.appendChild(a);
14  a.click();
15  document.body.removeChild(a);
16  URL.revokeObjectURL(url);
17}

Lösung 2: In neuem Fenster öffnen (bei einigen Plattformen verfügbar)

javascript
1// 部分平台链接可以直接在新窗口打开下载
2function openVideoInNewTab(videoUrl) {
3  window.open(videoUrl, '_blank');
4}

Lösung 3: Verwendung des download-Attributs (Same-Origin-Szenario)

html
1<!-- 仅适用于同源或允许 CORS 的资源 -->
2<a href="video.mp4" download="video.mp4">下载视频</a>

Backend-Proxy-Download-Lösung

FastAPI-Proxy-Beispiel

python
1from fastapi import FastAPI, Query, Response
2from fastapi.responses import StreamingResponse
3import httpx
4
5app = FastAPI()
6
7# 各平台的请求头配置
8PLATFORM_HEADERS = {
9    "douyin": {
10        "Referer": "https://www.douyin.com/",
11        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
12    },
13    "tiktok": {
14        "Referer": "https://www.tiktok.com/",
15        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
16    },
17    "bilibili": {
18        "Referer": "https://www.bilibili.com/",
19        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
20    },
21    "xiaohongshu": {
22        "Referer": "https://www.xiaohongshu.com/",
23        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
24    },
25    "weibo": {
26        "Referer": "https://weibo.com/",
27        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
28    },
29}
30
31
32@app.get("/api/download/video")
33async def proxy_video(
34    url: str = Query(..., description="视频 URL"),
35    platform: str = Query(..., description="平台标识"),
36):
37    """
38    视频代理下载接口
39
40    解决前端跨域和防盗链问题
41    """
42    headers = PLATFORM_HEADERS.get(platform, {})
43
44    async def video_stream():
45        async with httpx.AsyncClient(follow_redirects=True, timeout=120) as client:
46            async with client.stream("GET", url, headers=headers) as response:
47                async for chunk in response.aiter_bytes(chunk_size=8192):
48                    yield chunk
49
50    return StreamingResponse(
51        video_stream(),
52        media_type="video/mp4",
53        headers={
54            "Content-Disposition": "attachment; filename=video.mp4",
55            "Access-Control-Allow-Origin": "*",  # 允许跨域
56        }
57    )
58
59
60@app.get("/api/download/image")
61async def proxy_image(
62    url: str = Query(..., description="图片 URL"),
63    platform: str = Query(..., description="平台标识"),
64):
65    """图片代理下载接口"""
66    headers = PLATFORM_HEADERS.get(platform, {})
67
68    async with httpx.AsyncClient(follow_redirects=True) as client:
69        response = await client.get(url, headers=headers)
70
71        return Response(
72            content=response.content,
73            media_type=response.headers.get("content-type", "image/jpeg"),
74            headers={
75                "Access-Control-Allow-Origin": "*",
76            }
77        )

Download-Beispiel mit Fortschritt

python
1import httpx
2from tqdm import tqdm
3
4async def download_with_progress(url: str, save_path: str, headers: dict) -> bool:
5    """带进度条的下载"""
6    async with httpx.AsyncClient(follow_redirects=True, timeout=120) as client:
7        async with client.stream("GET", url, headers=headers) as response:
8            total = int(response.headers.get("content-length", 0))
9
10            with open(save_path, "wb") as f:
11                with tqdm(total=total, unit="B", unit_scale=True, desc="下载中") as pbar:
12                    async for chunk in response.aiter_bytes(chunk_size=8192):
13                        f.write(chunk)
14                        pbar.update(len(chunk))
15
16            return True
17    return False

Zusammenfassung

Schnellübersicht der Download-Schlüsselpunkte je Plattform

PlattformRefererCookie-AnforderungBesondere BehandlungGültigkeitsdauer des Links
Douyinhttps://www.douyin.com/OptionalKeine24 Stunden
TikTok Webhttps://www.tiktok.com/Erforderlich tt_chain_tokenRegion-Proxy erforderlich1-6 Stunden
TikTok AppNicht erforderlichNicht erforderlichEmpfohlen zu verwendenLänger
Bilibilihttps://www.bilibili.com/Für HD SESSDATA erforderlichAudio/Video getrennt, Zusammenführung nötig2 Stunden
Xiaohongshuhttps://www.xiaohongshu.com/OptionalKeineLänger
Weibohttps://weibo.com/Teilweise erforderlichMehrere AuflösungenLänger
YouTubehttps://www.youtube.com/Nicht erforderlichErfordert IP aus Los Angeles + Audio/Video getrennt6 Stunden

Fehlerbehebung bei häufigen Fehlern

FehlercodeMögliche UrsacheLösung
403 ForbiddenReferer falsch oder fehltReferer-Header prüfen
403 ForbiddenTikTok fehlt tt_chain_tokenCookie hinzufügen oder App-Link verwenden
403 ForbiddenYouTube-IP-Region stimmt nicht übereinProxy aus Los Angeles, Kalifornien, USA verwenden
404 Not FoundLink abgelaufenLink neu abrufen
410 GoneYouTube-Link abgelaufenVideo-Stream-URL neu abrufen
CORS ErrorBrowser-Cross-Domain-BeschränkungBackend-Proxy verwenden
TimeoutNetzwerkproblem oder Datei zu großTimeout erhöhen, segmentiert herunterladen

Best Practices

  1. Referer immer setzen: Dies ist für die meisten Plattformen eine notwendige Voraussetzung
  2. Backend-Proxy verwenden: Die beste Lösung zur Behebung von Frontend-CORS-Problemen
  3. Ablaufzeit des Links beachten: Links rechtzeitig verwenden, nach Ablauf neu abrufen
  4. Fortsetzbares Herunterladen unterstützen: Für große Dateien segmentiert mit dem Range-Header herunterladen
  5. Fehler erneut versuchen: Bei instabilem Netzwerk einen Retry-Mechanismus implementieren

Kontakt

Wenn Sie nach Befolgung der Anweisungen in diesem Dokument das Video immer noch nicht erfolgreich herunterladen können, wenden Sie sich bitte an den Kundendienst:

Wenn Sie den Kundendienst kontaktieren, geben Sie bitte die folgenden Informationen an, damit wir Ihnen schneller helfen können:

  1. Plattformname: Douyin/TikTok/Bilibili/Xiaohongshu/Weibo/YouTube
  2. Videolink: URL der ursprünglichen Videoseite
  3. Fehlermeldung: Vollständiger Fehlercode und Fehlerbeschreibung
  4. Request-Header-Konfiguration: Die von Ihnen verwendeten Informationen zu Referer, Cookie usw.
  5. Proxy-Informationen: Falls ein Proxy verwendet wird, bitte die Proxy-Region angeben

Enjoyed this article?

Share it with your friends and colleagues!

Default
Last updated: May 15, 2026
相关文章
正在检查服务状态...
多平台视频链接下载指南 - TikHub.io