MCPcopy Index your code
hub / github.com/jiji262/douyin-downloader

github.com/jiji262/douyin-downloader @desktop-v0.5.0 sqlite

repository ↗ · DeepWiki ↗ · release desktop-v0.5.0 ↗
1,142 symbols 5,219 edges 108 files 212 documented · 19%
README

抖音下载器 V2.0(Douyin Downloader)

douyin-downloader

一个面向实用场景的抖音下载工具,支持视频、图文、合集、音乐、收藏夹等多种类型下载,以及作者主页批量下载,默认带进度展示、重试、数据库去重、下载完整性校验和浏览器兜底能力。

桌面版(Douzy)

基于同一套后端打造的桌面客户端——粘贴链接即刻开始,同步关注列表,可视化跟踪下载进度。

内测中: 桌面版目前处于内测期,如需使用,请到 Releases 页面下载安装文件。

下载 — 粘贴链接即刻开始 下载 · 粘贴链接即刻开始 关注同步 关注 · 同步博主列表 任务中心 任务中心 · 逐任务状态
作品档案与筛选 作品档案 · SQLite 历史与筛选 设置与命名模板 设置 · 文件命名模板 实时下载进度 实时进度 · 逐任务事件日志

功能概览

已支持

功能 说明
单个视频下载 /video/{aweme_id}
单个图文下载 /note/{note_id}/gallery/{note_id}
单个合集下载 /collection/{mix_id}/mix/{mix_id}
单个音乐下载 /music/{music_id}(优先原声文件,缺失时回退到该音乐下首条作品)
短链自动解析 https://v.douyin.com/...v.iesdouyin.com,含裸 host
用户主页批量下载 /user/{sec_uid} + mode: [post, like, mix, music]
当前登录账号收藏夹下载 /user/self?showTab=favorite_collection + mode: [collect, collectmix]
无水印优先 自动选择无水印视频源
最高清自动挑选 基于 video.bit_rate 数组自动选最高码率(视频 + 实况图生效)
直播录制 live.douyin.com/{room_id} → FLV/HLS,主播下播时保留已录数据
评论采集 按作品抓评论(可含二级回复),输出 *_comments.json
热搜榜 + 关键词搜索 --hot-board [N] / --search "关键词",结果落 JSONL
REST API 服务模式 --serve --serve-port 8000(可选 fastapi + uvicorn
完成通知推送 下载完成后推 Bark / Telegram / Webhook
附加资源下载 封面、音乐、头像、JSON 元数据
视频转写 可选功能,调用 OpenAI Transcriptions API
并发下载 可配置并发数,默认 5
失败重试 指数退避重试(1s, 2s, 5s)
速率限制 默认 2 请求/秒
SQLite 去重 数据库 + 本地文件双重去重
增量下载 increase.post/like/mix/music
时间过滤 start_time / end_time
浏览器兜底 翻页受限时启动浏览器,支持人工过验证码
下载完整性校验 Content-Length 比对,不完整文件自动清理并重试
进度条展示 Rich 进度条,支持 progress.quiet_logs 静默模式
Docker 部署 提供 Dockerfile
CI/CD GitHub Actions 自动测试和 lint

限制说明

  • 浏览器兜底当前仅针对 post 完整验证,like/mix/music 主要依赖 API 正常分页
  • number.allmix / increase.allmix 作为兼容别名保留,运行时会归一化到 mix
  • collect / collectmix 当前仅支持当前已登录 Cookie 对应账号
  • collect / collectmix 必须单独使用,不能和 post / like / mix / music 混用
  • increase 当前仅支持 post / like / mix / music;收藏夹模式不支持增量截断
  • 直播录制 FLV 可直接播放;HLS 源只保存 playlist 文件(需要用 ffmpeg 后处理)
  • webcast 直播接口未覆盖所有场景,视为 experimental

快速开始

1) 环境准备

  • Python 3.8+
  • macOS / Linux / Windows

2) 安装依赖

pip install -r requirements.txt

如需浏览器兜底或自动获取 Cookie:

pip install playwright
python -m playwright install chromium

3) 复制配置

cp config.example.yml config.yml

4) 获取 Cookie(推荐自动方式)

python -m tools.cookie_fetcher --config config.yml

登录抖音后回到终端按 Enter,程序会自动写入配置。

5) Docker 部署(可选)

docker build -t douyin-downloader .
docker run -v $(pwd)/config.yml:/app/config.yml -v $(pwd)/Downloaded:/app/Downloaded douyin-downloader

最小可用配置

link:
  - https://www.douyin.com/user/MS4wLjABAAAAxxxx

path: ./Downloaded/
mode:
  - post

number:
  post: 0
  collect: 0
  collectmix: 0

thread: 5
retry_times: 3
proxy: ""
database: true
database_path: dy_downloader.db

progress:
  quiet_logs: true

cookies:
  msToken: ""
  ttwid: YOUR_TTWID
  odin_tt: YOUR_ODIN_TT
  passport_csrf_token: YOUR_CSRF_TOKEN
  sid_guard: ""

browser_fallback:
  enabled: true
  headless: false
  max_scrolls: 240
  idle_rounds: 8
  wait_timeout_seconds: 600

transcript:
  enabled: false
  model: gpt-4o-mini-transcribe
  output_dir: ""
  response_formats: ["txt", "json"]
  api_url: https://api.openai.com/v1/audio/transcriptions
  api_key_env: OPENAI_API_KEY
  api_key: ""

使用方式

使用配置文件运行

python run.py -c config.yml

命令行追加参数

python run.py -c config.yml \
  -u "https://www.douyin.com/video/7604129988555574538" \
  -t 8 \
  -p ./Downloaded

参数说明

参数 说明
-u, --url 追加下载链接(可重复传入)
-c, --config 指定配置文件(默认 config.yml
-p, --path 指定下载目录
-t, --thread 指定并发数
--show-warnings 显示 warning/error 日志
-v, --verbose 显示 info/warning/error 日志
--hot-board [N] 拉取抖音热搜榜并导出 JSONL,可选上限 N
--search KEYWORD 按关键词搜索作品并导出 JSONL
--search-max N --search 场景下最多拉取条数(默认 50)
--serve 以 REST API 服务模式运行(需要 pip install fastapi uvicorn
--serve-host HOST REST 服务监听地址(默认 127.0.0.1)
--serve-port PORT REST 服务监听端口(默认 8000)
--version 显示版本号

典型场景

下载单个视频

link:
  - https://www.douyin.com/video/7604129988555574538

下载单个图文

link:
  - https://www.douyin.com/note/7341234567890123456

下载单个合集

link:
  - https://www.douyin.com/collection/7341234567890123456

下载单个音乐

link:
  - https://www.douyin.com/music/7341234567890123456

批量下载作者主页作品

link:
  - https://www.douyin.com/user/MS4wLjABAAAAxxxx
mode:
  - post
number:
  post: 50

批量下载作者点赞作品

link:
  - https://www.douyin.com/user/MS4wLjABAAAAxxxx
mode:
  - like
number:
  like: 0    # 0 表示全量下载

同时下载多种模式

link:
  - https://www.douyin.com/user/MS4wLjABAAAAxxxx
mode:
  - post
  - like
  - mix
  - music

跨模式自动去重:同一个 aweme_id 在不同模式下不会重复下载。

批量下载当前登录账号收藏夹作品

link:
  - https://www.douyin.com/user/self?showTab=favorite_collection
mode:
  - collect
number:
  collect: 0

批量下载当前登录账号收藏合集

link:
  - https://www.douyin.com/user/self?showTab=favorite_collection
mode:
  - collectmix
number:
  collectmix: 0

录制直播(实验性)

link:
  - https://live.douyin.com/123456789   # 也支持 /follow/live/{room_id}
live:
  max_duration_seconds: 3600   # 0 = 录到主播下播
  chunk_size: 65536
  idle_timeout_seconds: 30

录制的 FLV 会保存在 Downloaded/{作者}/live/ 下,并附带 *_room.json 直播间元数据快照。 主播下播、网络空闲或 Ctrl+C 中断时,已录制的字节会被保留(.tmp 文件自动提升为正式文件)。

采集作品评论

comments:
  enabled: true
  include_replies: false   # 设为 true 会多拉每条评论的二级回复(额外请求量)
  max_comments: 500        # 0 = 不限
  page_size: 20

会在媒体文件旁生成 {date}_{title}_{aweme_id}_comments.json

导出热搜榜快照

python run.py --hot-board 30 -p ./Downloaded
# 输出:./Downloaded/hot_board/20260424_221530.jsonl

关键词搜索

python run.py --search "猫咪" --search-max 100 -p ./Downloaded
# 输出:./Downloaded/search/猫咪_20260424_221530.jsonl

以 REST API 服务模式运行

pip install fastapi uvicorn       # 一次性可选依赖
python run.py --serve --serve-port 8000

接口:

Method Path 说明
POST /api/v1/download 提交 {"url": "..."},返回 {job_id, status}
GET /api/v1/jobs/{job_id} 查询指定 job 的状态/计数
GET /api/v1/jobs 列出最近的 job(按 TTL + 容量剪裁)
GET /api/v1/health 健康探针

完成态的 job 会按 TTL(默认 24 小时)+ 最大数量(默认 500)自动剪裁;in-flight 的 job 永不被裁掉。 可通过 server.max_jobs / server.job_ttl_seconds 调整。

完成后发送通知

notifications:
  enabled: true
  on_success: true
  on_failure: true
  providers:
    - type: bark
      url: https://api.day.app/YOUR_DEVICE_KEY
      sound: bell
    - type: telegram
      bot_token: "123456:ABC..."
      chat_id: "987654321"
    - type: webhook                 # 企业微信/飞书/钉钉 bot URL 同样可用
      url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
      extra_body:
        msgtype: text

所有启用的 provider 会并发推送;单个 provider 失败不会阻塞主下载流程。

增量下载(只下载新作品)

increase:
  post: true
database: true    # 增量模式依赖数据库记录

全量抓取(不限制数量)

number:
  post: 0

可选功能:视频转写(transcript)

当前实现仅对视频作品生效(图文不会生成转写)。

1) 开启方式

transcript:
  enabled: true
  model: gpt-4o-mini-transcribe
  output_dir: ""        # 留空: 与视频同目录;非空: 镜像到指定目录
  response_formats:
    - txt
    - json
  api_key_env: OPENAI_API_KEY
  api_key: ""           # 可直接填,或使用环境变量

推荐通过环境变量提供密钥:

export OPENAI_API_KEY="sk-xxxx"

2) 输出文件

启用后会生成:

  • xxx.transcript.txt
  • xxx.transcript.json

database: true,会在数据库 transcript_job 表记录状态(success/failed/skipped)。

测试

推荐使用:

python3 -m pytest -q

当前也支持直接运行:

pytest -q

关键配置项

配置项 说明
mode 支持 post/like/mix/music;当前登录收藏夹模式额外支持单独使用的 collect/collectmix
number.post/like/mix/music/collect/collectmix 各模式下载数量限制,0 为不限
increase.post/like/mix/music 各模式增量开关
start_time / end_time 时间过滤(格式 YYYY-MM-DD
folderstyle 按作品维度创建子目录
browser_fallback.* post 翻页受限时启用浏览器兜底
progress.quiet_logs 进度阶段静默日志,减少刷屏
transcript.* 视频下载后的可选转写
proxy 为 API 请求和媒体下载设置 HTTP/HTTPS 代理,例如 http://127.0.0.1:7890
comments.* 按作品采集评论(默认关闭)
live.* 直播录制参数(max_duration_seconds / chunk_size / idle_timeout_seconds)
notifications.* 下载完成后 Bark/Telegram/Webhook 推送
server.* REST API 服务调优(max_jobs、job_ttl_seconds)
database 启用 SQLite 去重和历史记录
database_path SQLite 文件路径,默认在当前工作目录生成 dy_downloader.db
thread 并发下载数
retry_times 失败重试次数

输出目录

默认 folderstyle: truedatabase_path: dy_downloader.db 时:

工作目录/
├── config.yml
├── dy_downloader.db          # database: true 时默认生成在这里
└── Downloaded/
    ├── download_manifest.jsonl
    └── 作者名/
        ├── post/
        │   └── 2024-02-07_作品标题_aweme_id/
        │       ├── ...mp4
        │       ├── ..._cover.jpg
        │       ├── ..._music.mp3
        │       ├── ..._data.json
        │       ├── ..._avatar.jpg
        │       ├── ...transcript.txt
        │       └── ...transcript.json
        ├── like/
        │   └── ...
        ├── mix/
        │   └── ...
        ├── music/
        │   └── ...
        ├── collect/
        │   └── ...
        └── collectmix/
            └── ...
Downloaded/
├── download_manifest.jsonl
├── dy_downloader.db          # database: true 时生成
├── hot_board/                # 使用 --hot-board 时生成
│   └── 20260424_221530.jsonl
├── search/                   # 使用 --search 时生成
│   └── 猫咪_20260424_221530.jsonl
└── 作者名/
    ├── post/
    │   └── 2024-02-07_作品标题_aweme_id/
    │       ├── ...mp4
    │       ├── ..._cover.jpg
    │       ├── ..._music.mp3
    │       ├── ..._data.json
    │       ├── ..._avatar.jpg
    │       ├── ..._comments.json    # comments.enabled 时生成
    │       ├── ...transcript.txt
    │       └── ...transcript.json
    ├── like/
    │   └── ...
    ├── mix/
    │   └── ...
    ├── music/
    │   └── ...
    └── live/                 # 录制直播时生成
        └── 2026-04-24_2215_直播标题_房间号/
            ├── ...flv
            └── ..._room.json

重新下载

程序通过数据库记录 + 本地文件双重检查判断是否跳过已下载内容。要重新下载,需要按以下方式清理数据:

重新下载特定作品

# 删除本地文件(文件名中包含 aweme_id)
rm -rf Downloaded/作者名/post/*_<aweme_id>/

# 删除数据库记录
sqlite3 dy_downloader.db "DELETE FROM aweme WHERE aweme_id = '<aweme_id>';"

重新下载某个作者的全部作品

rm -rf Downloaded/作者名/
sqlite3 dy_downloader.db "DELETE FROM aweme WHERE author_name = '作者名';"

全部从零重新下载

rm -rf Downloaded/
rm dy_downloader.db

注意: 只删数据库不删文件不会触发重新下载——程序会扫描本地文件名中的 aweme_id 进行去重。只删文件不删数据库会触发重新下载(数据库中有记录但文件不存在时视为需要重新下载)。

常见问题

1) 只能抓到 20 条作品怎么办?

这是翻页风控的常见现象。确保:

  • browser_fallback.enabled: true
  • browser_fallback.headless: false
  • 浏览器弹窗出现后手动完成验证,不要立即关闭窗口

2) 进度条出现重复刷屏怎么办?

默认 progress.quiet_logs: true 会在进度阶段静默日志。
调试时再临时加 --show-warnings-v

3) Cookie 失效怎么办?

重新执行:

python -m tools.cookie_fetcher --config config.yml

4) 为什么没有生成 transcript 文件?

请依次检查:

  • transcript.enabled 是否为 true
  • 是否下载的是视频(图文不转写)
  • OPENAI_API_KEY(或 transcript.api_key)是否有效
  • response_formats 是否包含 txtjson

5) 如何查看下载历史?

sqlite3 dy_downloader.db "SELECT aweme_id, title, author_name, datetime(download_time, 'unixepoch', 'localtime') FROM aweme ORDER BY download_time DESC LIMIT 20;"

沟通群

qun

点击链接加入群聊【QQ群】:https://qm.qq.com/q/9xoNt8Wzv4

免责声明

本项目仅用于技术研究、学习交流与个人数据管理。请在合法合规前提下使用:

  • 不得用于侵犯他人隐私、版权或其他合法权益
  • 不得用于任何违法违规用途
  • 使用者应自行承担因使用本项目产生的全部风险与责任
  • 如平台规则、接口策略变更导致功能失效,属于正常技术风险

如果你继续使用本项目,即视为已阅读并同意上述声明。

许可证

本项目采用 MIT License,详见 LICENSE

Core symbols most depended-on inside this repo

get
called by 366
core/user_mode_registry.py
warning
called by 103
cli/whisper_transcribe.py
get
called by 99
server/jobs.py
update
called by 74
config/config_loader.py
get
called by 46
config/config_loader.py
error
called by 41
cli/whisper_transcribe.py
close
called by 35
storage/database.py
initialize
called by 34
storage/database.py

Shape

Method 524
Function 489
Class 123
Route 6

Languages

Python100%

Modules by API surface

tests/test_api_client.py56 symbols
core/api_client.py50 symbols
core/downloader_base.py48 symbols
tests/test_live_downloader.py42 symbols
tests/test_video_downloader.py40 symbols
tests/test_transcript_manager_audio.py35 symbols
tests/test_user_mode_strategies.py33 symbols
tests/test_user_downloader.py32 symbols
tests/test_audio_extraction.py31 symbols
utils/abogus.py29 symbols
tests/test_user_downloader_modes.py28 symbols
cli/whisper_transcribe.py26 symbols

Dependencies from manifests, versioned

aiofiles23.2.1 · 1×
aiohttp3.9.0 · 1×
aiosqlite0.19.0 · 1×
gmssl3.2.2 · 1×
imageio-ffmpeg0.6.0 · 1×
python-dateutil2.8.2 · 1×
pyyaml6.0.1 · 1×
rich13.7.0 · 1×

For agents

$ claude mcp add douyin-downloader \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact