December 5, 2025
214 Views
Default

Guide de téléchargement de liens vidéo multi-plateformes

Ce document présente en détail comment, après avoir obtenu des liens vidéo depuis des plateformes telles que Douyin, TikTok, Bilibili, Xiaohongshu et Weibo, télécharger correctement les fichiers vidéo. Il se concentre sur la résolution des problèmes courants tels que le cross-domain, la protection contre le hotlinking et la vérification des en-têtes de requête.

Guide de téléchargement des liens vidéo multi-plateformes

Ce document présente en détail comment télécharger correctement des fichiers vidéo après avoir obtenu des liens vidéo depuis des plateformes comme Douyin, TikTok, Bilibili, Xiaohongshu, Weibo, etc. Il se concentre sur la résolution des problèmes courants tels que le cross-domain, le hotlinking et la vérification des en-têtes de requête.

Sommaire


Vue d’ensemble des problèmes généraux

Après avoir obtenu des liens vidéo depuis différentes plateformes, un téléchargement direct rencontre généralement les problèmes suivants :

Type de problèmeDescriptionSolution
Hotlinking (Referer)Le serveur vérifie l’origine de la requête et refuse les sources non autoriséesDéfinir un en-tête Referer correct
Cross-domain (CORS)La politique de sécurité du navigateur bloque les requêtes cross-domainProxy back-end / téléchargement côté serveur
Vérification du User-AgentLe serveur vérifie l’identifiant du clientSimuler un UA de navigateur
Vérification des cookiesCertains liens nécessitent une session connectéeTransmettre des cookies valides
Validité du lienLes liens vidéo ont une date d’expirationUtiliser rapidement, puis récupérer à nouveau après expiration
Restriction IPCertains liens limitent l’accès par régionUtiliser un proxy de la région correspondante

抖音 (Douyin)

Caractéristiques des liens vidéo

Les liens vidéo Douyin se présentent généralement sous les formes suivantes :

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

Exigences de téléchargement

En-tête de requêteObligatoireValeur
RefererObligatoirehttps://www.douyin.com/
User-AgentRecommandéUA du navigateur
CookieFacultatifRequis pour certains liens HD

Exemple de téléchargement côté serveur

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

Problème de cross-domain côté front-end

Les liens vidéo Douyin ne prennent pas en charge CORS ; une requête directe depuis le front-end sera bloquée par le navigateur :

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  });

Remarques

  1. Validité du lien : les liens vidéo Douyin sont généralement valides pendant 24 heures
  2. Lien sans filigrane : utiliser play_addr plutôt que download_addr
  3. Lien HD : certaines vidéos 4K / qualité originale sont volumineuses ; il est recommandé d’utiliser un téléchargement par segments pour éviter un échec de téléchargement unique

TikTok

Caractéristiques des liens vidéo

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

Exigences de téléchargement

Liens vidéo côté Web

En-tête de requêteObligatoireValeur
RefererObligatoirehttps://www.tiktok.com/
User-AgentObligatoireUA du navigateur
CookieObligatoireNécessite le champ tt_chain_token

Important : les liens vidéo renvoyés par TikTok côté Web doivent inclure le cookie tt_chain_token pour pouvoir être téléchargés, sinon une erreur 403 sera renvoyée.

Liens vidéo côté App

En-tête de requêteObligatoireValeur
User-AgentRecommandéUA quelconque
CookieNon requisLes liens côté App n’ont pas cette restriction

Recommandation : si vous pouvez obtenir un lien côté App, privilégiez-le ; il n’est pas nécessaire de gérer le problème des cookies.

Exemple de téléchargement côté serveur

Téléchargement côté Web (nécessite 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

Téléchargement côté App (sans restriction de cookies)

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

Comment obtenir tt_chain_token

tt_chain_token est le cookie utilisé par TikTok pour l’authentification du téléchargement vidéo ; méthodes d’obtention :

  1. Depuis le navigateur : ouvrez le site TikTok, outils de développement F12 -> Application -> Cookies -> trouvez tt_chain_token

  2. Depuis la réponse API : certains en-têtes Set-Cookie des réponses API TikTok contiennent cette valeur

  3. Utiliser l’API TikHub : les données renvoyées par l’API peuvent déjà inclure un token utilisable

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 ""

Restriction géographique

Les vidéos TikTok peuvent être soumises à des restrictions régionales ; certaines ne sont accessibles que dans des pays spécifiques :

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    # ...

Remarques

  1. Restriction géographique : certaines vidéos nécessitent une IP américaine/européenne pour être accessibles
  2. Validité du lien : la durée de validité est d’environ 24 heures
  3. Sans filigrane : privilégier le champ downloadAddr

哔哩哔哩 (Bilibili)

Caractéristiques des liens vidéo

Les liens vidéo de Bilibili sont particuliers, l’audio et la vidéo sont séparés :

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

Exigences de téléchargement

En-tête de requêteObligatoireValeur
RefererObligatoirehttps://www.bilibili.com/
User-AgentRecommandéUA du navigateur
CookieHD, 4K obligatoiresSESSDATA, etc.
RangeRecommandéTéléchargement par segments

Exemple de téléchargement côté serveur

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éConnexion requiseExigence de cookie
360P/480PNonAucune
720POuiSESSDATA
1080POuiSESSDATA + abonnement premium
4K/HDROuiSESSDATA + abonnement premium

Remarques

  1. Fusion obligatoire : le format DASH sépare l’audio et la vidéo, il faut les fusionner avec FFmpeg
  2. Referer obligatoire : sans Referer correct, une erreur 403 sera renvoyée
  3. Validité du lien : environ 2 heures
  4. Téléchargement par segments : pour les gros fichiers, il est recommandé d’utiliser l’en-tête Range pour télécharger par segments

小红书 (Xiaohongshu)

Caractéristiques des liens vidéo

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

Exigences de téléchargement

En-tête de requêteObligatoireValeur
RefererObligatoirehttps://www.xiaohongshu.com/
User-AgentRecommandéUA du navigateur
CookieFacultatifRequis pour certains contenus

Exemple de téléchargement côté serveur

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

Téléchargement d’images

Les images Xiaohongshu ont également une protection anti-hotlinking :

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

Remarques

  1. Referer strict : il faut impérativement un Referer de xiaohongshu.com
  2. Nœuds CDN : bd (Baidu Cloud), hw (Huawei Cloud), etc., selon les différents nœuds
  3. Sans filigrane : les liens renvoyés par l’API sont généralement sans filigrane

微博 (Weibo)

Caractéristiques des liens vidéo

Les formats de liens vidéo Weibo sont variés :

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

Exigences de téléchargement

En-tête de requêteObligatoireValeur
RefererObligatoirehttps://weibo.com/ ou https://m.weibo.cn/
User-AgentRecommandéUA du navigateur
CookieRequis pour certains casRequis pour les vidéos privées

Exemple de téléchargement côté serveur

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

Choix de plusieurs définitions

Les vidéos Weibo proposent généralement plusieurs niveaux de qualité :

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")

Remarques

  1. Domaine du Referer : prend en charge weibo.com et m.weibo.cn
  2. Plusieurs qualités : plusieurs qualités sont disponibles dans les données renvoyées
  3. Validité du lien : certains liens ont une durée de validité limitée

YouTube

Caractéristiques des liens vidéo

Les liens vidéo YouTube se présentent généralement sous les formes suivantes :

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/...

Exigences de téléchargement

Restriction IP stricte : l’adresse du flux vidéo YouTube fait l’objet d’une vérification extrêmement stricte de la géolocalisation IP ; il faut impérativement utiliser une IP située à Los Angeles, Californie, États-Unis pour réussir le téléchargement, sinon une erreur 403 Forbidden sera renvoyée.

En-tête de requêteObligatoireValeur
User-AgentObligatoireUA du navigateur
RefererRecommandéhttps://www.youtube.com/
OriginRecommandéhttps://www.youtube.com
IP proxyObligatoireIP de Los Angeles, Californie, États-Unis

Explication de la restriction géographique IP

L’adresse du flux vidéo YouTube est liée à l’adresse IP du demandeur lors de sa génération ; au téléchargement, il faut utiliser une IP de la même région :

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    &...

Pourquoi une IP de Los Angeles est-elle obligatoire ?

  1. La plupart des nœuds CDN de YouTube sont situés sur la côte ouest des États-Unis
  2. Lors de la génération de l’URL du flux vidéo, le CDN le plus proche est choisi selon l’IP de la requête
  3. Une incohérence de région IP au téléchargement entraîne une erreur 403
  4. Los Angeles est le principal emplacement des centres de données de YouTube, avec la meilleure compatibilité

Exemple de téléchargement côté serveur

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

Traitement de la séparation audio/vidéo

Les vidéos YouTube en haute définition (1080p+) utilisent le format DASH, avec audio et vidéo séparés :

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

Exemple de configuration du proxy

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

Tableau de correspondance des identifiants de qualité (itag)

itagRésolutionFormatContient l’audio
18360pMP4Oui
22720pMP4Oui
1371080pMP4Non (fusion requise)
2481080pWebMNon (fusion requise)
2711440pWebMNon (fusion requise)
3132160pWebMNon (fusion requise)
140-Audio M4AAudio uniquement
251-Audio WebMAudio uniquement

Remarques

  1. Restriction IP extrêmement stricte : il faut impérativement utiliser une IP de Los Angeles, Californie, États-Unis ; les autres régions (y compris les autres États américains) peuvent échouer
  2. Validité du lien : l’URL du flux vidéo est généralement valide pendant 6 heures
  3. Séparation audio/vidéo : les qualités supérieures à 720p nécessitent de télécharger séparément l’audio et la vidéo puis de les fusionner
  4. Limitation de débit : YouTube limite la vitesse de téléchargement ; pour les gros fichiers, il est recommandé de télécharger par segments
  5. Protection des droits d’auteur : certaines vidéos sont protégées par DRM et ne peuvent pas être téléchargées directement

Solution de téléchargement côté front-end

En raison des restrictions CORS, le front-end ne peut pas télécharger directement les vidéos de la plupart des plateformes. Voici les solutions possibles :

Solution 1 : proxy back-end (recommandé)

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}

Solution 2 : ouvrir dans une nouvelle fenêtre (disponible pour certaines plateformes)

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

Solution 3 : utiliser l’attribut download (scénario même origine)

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

Solution de téléchargement via proxy côté back-end

Exemple de proxy FastAPI

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        )

Exemple de téléchargement avec progression

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

Résumé

Tableau de référence rapide des points clés de téléchargement par plateforme

PlateformeRefererExigence de cookieTraitement spécialValidité du lien
抖音https://www.douyin.com/FacultatifAucun24 heures
TikTok Webhttps://www.tiktok.com/Obligatoire tt_chain_tokenNécessite un proxy régional1-6 heures
TikTok AppNon requisNon requisRecommandéPlus longue
B站https://www.bilibili.com/Pour la HD, SESSDATA obligatoireLa séparation audio/vidéo nécessite une fusion2 heures
小红书https://www.xiaohongshu.com/FacultatifAucunPlus longue
微博https://weibo.com/Requis pour certains casPlusieurs qualitésPlus longue
YouTubehttps://www.youtube.com/Non requisIP de Los Angeles obligatoire + séparation audio/vidéo6 heures

Dépannage des erreurs courantes

Code d’erreurCause possibleSolution
403 ForbiddenReferer incorrect ou manquantVérifier l’en-tête Referer
403 ForbiddenTikTok sans tt_chain_tokenAjouter le cookie ou utiliser un lien côté App
403 ForbiddenIP YouTube non conforme à la régionUtiliser un proxy de Los Angeles, Californie, États-Unis
404 Not FoundLien expiréRécupérer à nouveau le lien
410 GoneLien YouTube expiréRécupérer à nouveau l’URL du flux vidéo
CORS ErrorRestriction cross-domain du navigateurUtiliser un proxy back-end
TimeoutProblème réseau ou fichier trop volumineuxAugmenter le délai d’attente, télécharger par segments

Bonnes pratiques

  1. Définir systématiquement le Referer : c’est une condition nécessaire pour la plupart des plateformes
  2. Utiliser un proxy back-end : la meilleure solution pour résoudre les problèmes CORS côté front-end
  3. Gérer la validité des liens : utiliser les liens rapidement et les récupérer à nouveau après expiration
  4. Prendre en charge la reprise sur interruption : pour les gros fichiers, utiliser l’en-tête Range pour télécharger par segments
  5. Réessayer en cas d’erreur : mettre en place un mécanisme de retry lorsque le réseau est instable

Nous contacter

Si, après avoir suivi les instructions de ce document, vous ne parvenez toujours pas à télécharger la vidéo, veuillez contacter le service client pour obtenir de l’aide :

Lorsque vous contactez le service client, veuillez fournir les informations suivantes afin que nous puissions vous aider plus rapidement :

  1. Nom de la plateforme : 抖音/TikTok/B站/小红书/微博/YouTube
  2. Lien vidéo : URL de la page vidéo originale
  3. Message d’erreur : code d’erreur complet et description de l’erreur
  4. Configuration des en-têtes de requête : informations sur le Referer, les cookies, etc. que vous utilisez
  5. Informations sur le proxy : si vous utilisez un proxy, veuillez indiquer la région du proxy

Enjoyed this article?

Share it with your friends and colleagues!

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