December 5, 2025
214 Views
Default

Руководство по загрузке видеоссылок с нескольких платформ

В этом документе подробно описывается, как правильно скачивать видеофайлы после получения ссылок на видео с платформ Douyin, TikTok, Bilibili, Xiaohongshu, Weibo и других. Основное внимание уделяется решению распространённых проблем, таких как междоменные ограничения, защита от хотлинка и проверка заголовков запросов.

Руководство по загрузке видеоссылок с нескольких платформ

В этом документе подробно описано, как правильно загружать видеофайлы после получения видеоссылок с платформ Douyin, TikTok, Bilibili, Xiaohongshu, Weibo и других. Основное внимание уделено распространённым проблемам: междоменные ограничения, защита от хотлинка, проверка заголовков запроса и т. п.

Содержание


Обзор общих проблем

После получения видеоссылки с различных платформ при прямой загрузке обычно возникают следующие проблемы:

Тип проблемыОписаниеРешение
Защита от хотлинка (Referer)Сервер проверяет источник запроса и отклоняет недопустимые источникиУстановить корректный заголовок Referer
Междоменные ограничения (CORS)Политика безопасности браузера блокирует междоменные запросыБэкенд-прокси / загрузка на стороне сервера
Проверка User-AgentСервер проверяет идентификатор клиентаЭмулировать браузерный UA
Проверка CookieДля некоторых ссылок требуется авторизованная сессияПередавать действительные Cookie
Срок действия ссылкиУ видеоссылок есть время истеченияИспользовать своевременно, после истечения получать заново
Ограничение по IPДля некоторых ссылок ограничен регион доступаИспользовать прокси соответствующего региона

抖音 (Douyin)

Особенности видеоссылок

Видеоссылки Douyin обычно имеют следующие формы:

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

Требования к загрузке

Заголовок запросаОбязательно лиЗначение
RefererОбязательноhttps://www.douyin.com/
User-AgentРекомендуетсяBrowser UA
CookieНеобязательноТребуется для некоторых ссылок HD

Пример загрузки на сервере

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

Проблема междоменных запросов на фронтенде

Видеоссылки Douyin не поддерживают CORS, поэтому прямой запрос с фронтенда будет заблокирован браузером:

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

Примечания

  1. Срок действия ссылки: видеоссылки Douyin обычно действуют в течение 24 часов
  2. Ссылка без водяного знака: используйте play_addr, а не download_addr
  3. Ссылка высокого качества: некоторые видео 4K/оригинального качества имеют большой размер; рекомендуется загружать по частям, чтобы избежать неудачи при загрузке целиком

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

Требования к загрузке

Видеоссылки веб-версии

Заголовок запросаОбязательно лиЗначение
RefererОбязательноhttps://www.tiktok.com/
User-AgentОбязательноBrowser UA
CookieОбязательноТребуется поле tt_chain_token

Важно: для загрузки видеоссылки, возвращаемой веб-версией TikTok, обязательно нужно передавать Cookie tt_chain_token, иначе будет возвращена ошибка 403.

Видеоссылки App-версии

Заголовок запросаОбязательно лиЗначение
User-AgentРекомендуетсяЛюбой UA
CookieНе требуетсяДля ссылок App-версии такого ограничения нет

Рекомендуется: если можно получить ссылку App-версии, в первую очередь используйте её — тогда не нужно решать проблему с Cookie.

Пример загрузки на сервере

Загрузка веб-версии (требуется 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

Как получить tt_chain_token

tt_chain_token — это Cookie, используемый TikTok для авторизации загрузки видео. Способы получения:

  1. Из браузера: откройте сайт TikTok, F12 Developer Tools -> Application -> Cookies -> найдите tt_chain_token

  2. Из ответа API: в заголовке Set-Cookie некоторых ответов TikTok API может содержаться это значение

  3. Использовать TikHub API: в данных, возвращаемых API, может уже содержаться доступный token

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

Региональные ограничения

У видео TikTok могут быть региональные ограничения, и некоторые видео доступны только в определённых странах:

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

Примечания

  1. Региональные ограничения: для некоторых видео требуется IP США/Европы
  2. Срок действия ссылки: срок действия ссылки составляет примерно 24 часа
  3. Без водяного знака: в первую очередь используйте поле downloadAddr

哔哩哔哩 (Bilibili)

Особенности видеоссылок

Ссылки на видео Bilibili довольно специфичны: аудио и видео разделены:

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

Требования к загрузке

Заголовок запросаОбязательно лиЗначение
RefererОбязательноhttps://www.bilibili.com/
User-AgentРекомендуетсяBrowser UA
CookieДля HD, 4K обязательноSESSDATA и т. п.
RangeРекомендуетсяЗагрузка по частям

Пример загрузки на сервере

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
КачествоТребуется ли входТребования к Cookie
360P/480PНетНет
720PДаSESSDATA
1080PДаSESSDATA + VIP
4K/HDRДаSESSDATA + VIP

Примечания

  1. Обязательно объединять: в формате DASH аудио и видео разделены, их нужно объединять с помощью FFmpeg
  2. Referer обязателен: без корректного Referer будет возвращён 403
  3. Срок действия ссылки: примерно 2 часа
  4. Загрузка по частям: для больших файлов рекомендуется использовать заголовок Range

小红书 (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

Требования к загрузке

Заголовок запросаОбязательно лиЗначение
RefererОбязательноhttps://www.xiaohongshu.com/
User-AgentРекомендуетсяBrowser UA
CookieНеобязательноТребуется для части контента

Пример загрузки на сервере

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

Загрузка изображений

У изображений Xiaohongshu также есть защита от хотлинка:

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

Примечания

  1. Строгий Referer: обязательно передавать Referer с xiaohongshu.com
  2. CDN-узлы: разные узлы, такие как bd (Baidu Cloud), hw (Huawei Cloud) и т. п.
  3. Без водяного знака: ссылки, возвращаемые API, обычно не содержат водяного знака

微博 (Weibo)

Особенности видеоссылок

У видеоссылок Weibo существует несколько форматов:

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

Требования к загрузке

Заголовок запросаОбязательно лиЗначение
RefererОбязательноhttps://weibo.com/ или https://m.weibo.cn/
User-AgentРекомендуетсяBrowser UA
CookieДля части требуетсяТребуется для приватных видео

Пример загрузки на сервере

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

Выбор нескольких качеств

Видео Weibo обычно предоставляют несколько вариантов качества:

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

Примечания

  1. Домен Referer: поддерживаются weibo.com и m.weibo.cn
  2. Несколько качеств: в возвращаемых данных доступно несколько вариантов качества
  3. Срок действия ссылки: у некоторых ссылок есть ограничение по времени действия

YouTube

Особенности видеоссылок

Видеоссылки YouTube обычно имеют следующие формы:

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

Требования к загрузке

Строгое ограничение по IP: адреса видеопотока YouTube проходят крайне строгую проверку по геолокации IP, и для успешной загрузки необходимо использовать IP из региона Лос-Анджелес, Калифорния, США, иначе будет возвращена ошибка 403 Forbidden.

Заголовок запросаОбязательно лиЗначение
User-AgentОбязательноBrowser UA
RefererРекомендуетсяhttps://www.youtube.com/
OriginРекомендуетсяhttps://www.youtube.com
IP проксиОбязательноIP Лос-Анджелеса, Калифорния, США

Описание регионального ограничения IP

Адрес видеопотока YouTube при генерации привязывается к IP-адресу запрашивающей стороны, поэтому при загрузке необходимо использовать IP того же региона:

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

Почему именно IP Лос-Анджелеса?

  1. Большинство CDN-узлов YouTube расположены на западном побережье США
  2. При генерации URL видеопотока выбирается ближайший CDN в зависимости от IP запроса
  3. Несоответствие региона IP при загрузке приводит к ошибке 403
  4. Лос-Анджелес — место расположения основных дата-центров YouTube, поэтому совместимость там лучшая

Пример загрузки на сервере

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

Обработка разделения аудио и видео

Высококачественные видео YouTube (1080p+) используют формат DASH, в котором аудио и видео разделены:

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

Пример настройки прокси

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

Таблица соответствия идентификаторов качества (itag)

itagРазрешениеФорматЕсть ли аудио
18360pMP4Да
22720pMP4Да
1371080pMP4Нет (нужно объединять)
2481080pWebMНет (нужно объединять)
2711440pWebMНет (нужно объединять)
3132160pWebMНет (нужно объединять)
140-M4A аудиоТолько аудио
251-WebM аудиоТолько аудио

Примечания

  1. Ограничение по IP очень строгое: необходимо использовать IP Лос-Анджелеса, Калифорния, США; другие регионы (включая другие штаты США) тоже могут не сработать
  2. Срок действия ссылки: URL видеопотока обычно действителен в течение 6 часов
  3. Разделение аудио и видео: для качества выше 720p нужно отдельно загружать аудио и видео, а затем объединять их
  4. Ограничение скорости: у YouTube есть ограничения на скорость загрузки, для больших файлов рекомендуется загрузка по частям
  5. Защита авторских прав: некоторые видео защищены DRM и не могут быть загружены напрямую

Решение для загрузки на фронтенде

Из-за ограничений CORS фронтенд не может напрямую загружать видео с большинства платформ. Ниже приведены рабочие решения:

Вариант 1: бэкенд-прокси (рекомендуется)

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}

Вариант 2: открыть в новом окне (доступно для некоторых платформ)

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

Вариант 3: использовать атрибут download (в сценарии same-origin)

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

Решение для загрузки через бэкенд-прокси

Пример прокси на 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        )

Пример загрузки с прогрессом

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

Итоги

Сводная таблица ключевых моментов загрузки по платформам

ПлатформаRefererТребования к CookieОсобая обработкаСрок действия ссылки
抖音https://www.douyin.com/НеобязательноНет24 часа
TikTok Webhttps://www.tiktok.com/Обязательно tt_chain_tokenТребуется региональный прокси1-6 часов
TikTok AppНе требуетсяНе требуетсяРекомендуется использоватьДольше
B站https://www.bilibili.com/Для HD обязательно SESSDATAДля разделённых аудио и видео нужно объединение2 часа
小红书https://www.xiaohongshu.com/НеобязательноНетДольше
微博https://weibo.com/Для части требуетсяНесколько качествДольше
YouTubehttps://www.youtube.com/Не требуетсяОбязательно IP Лос-Анджелеса + разделение аудио и видео6 часов

Поиск и устранение частых ошибок

Код ошибкиВозможная причинаРешение
403 ForbiddenНеверный или отсутствующий RefererПроверить заголовок Referer
403 ForbiddenВ TikTok отсутствует tt_chain_tokenДобавить Cookie или использовать ссылку App-версии
403 ForbiddenIP YouTube не соответствует регионуИспользовать прокси из Лос-Анджелеса, Калифорния, США
404 Not FoundСсылка истеклаПолучить ссылку заново
410 GoneСсылка YouTube истеклаПолучить URL видеопотока заново
CORS ErrorОграничение междоменных запросов браузераИспользовать бэкенд-прокси
Тайм-аутПроблемы с сетью или слишком большой файлУвеличить время ожидания, загружать по частям

Лучшие практики

  1. Всегда задавайте Referer: это обязательное условие для большинства платформ
  2. Используйте бэкенд-прокси: лучший способ решить проблему CORS на фронтенде
  3. Учитывайте срок действия ссылки: используйте ссылку своевременно, после истечения получайте заново
  4. Поддерживайте докачку: для больших файлов используйте заголовок Range и загрузку по частям
  5. Повторные попытки при ошибках: реализуйте механизм повторных попыток при нестабильной сети

Связаться с нами

Если после выполнения инструкций из этого документа вам всё ещё не удаётся успешно загрузить видео, обратитесь в службу поддержки за помощью:

  • Официальная документация: https://docs.tikhub.io/
  • Сообщество Discord: https://discord.gg/Pu2uKkFu6u
  • Онлайн-поддержка (Chaport): откройте окно онлайн-чата в правом нижнем углу сайта

При обращении в поддержку, пожалуйста, предоставьте следующую информацию, чтобы мы могли помочь вам быстрее:

  1. Название платформы: 抖音/TikTok/B站/小红书/微博/YouTube
  2. Ссылка на видео: URL исходной страницы видео
  3. Сообщение об ошибке: полный код ошибки и описание ошибки
  4. Настройки заголовков запроса: используемые вами Referer, Cookie и т. п.
  5. Информация о прокси: если используется прокси, укажите регион прокси

Enjoyed this article?

Share it with your friends and colleagues!

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