[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-71061":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":25,"hasPages":23,"topics":26,"createdAt":10,"pushedAt":10,"updatedAt":27,"readmeContent":28,"aiSummary":29,"trendingCount":16,"starSnapshotCount":16,"syncStatus":30,"lastSyncTime":31,"discoverSource":32},71061,"douyin-downloader","jiji262\u002Fdouyin-downloader","jiji262","A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖音批量下载工具，去水印，支持视频、图集、合集、音乐(原声)。免费！免费！免费！","",null,"Python",7934,1275,51,11,0,45,118,317,135,40.32,"MIT License",false,"main",true,[],"2026-06-12 02:02:47","# Douyin Downloader V2.0\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fsocialify.git.ci\u002Fjiji262\u002Fdouyin-downloader\u002Fimage?custom_description=Douyin+batch+download+tool%2C+remove+watermarks%2C+support+batch+download+of+videos%2C+gallery%2C+and+author+homepages.&description=1&font=Source+Code+Pro&forks=1&owner=1&pattern=Circuit+Board&stargazers=1&theme=Light\" alt=\"douyin-downloader\" width=\"820\" \u002F>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n    \u003Ca href=\"https:\u002F\u002Flinux.do\" alt=\"LINUX DO\">\n        \u003Cimg\n            src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLINUX-DO-FFB003.svg?logo=data:image\u002Fsvg%2bxml;base64,DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiPjxwYXRoIGQ9Ik00Ni44Mi0uMDU1aDYuMjVxMjMuOTY5IDIuMDYyIDM4IDIxLjQyNmM1LjI1OCA3LjY3NiA4LjIxNSAxNi4xNTYgOC44NzUgMjUuNDV2Ni4yNXEtMi4wNjQgMjMuOTY4LTIxLjQzIDM4LTExLjUxMiA3Ljg4NS0yNS40NDUgOC44NzRoLTYuMjVxLTIzLjk3LTIuMDY0LTM4LjAwNC0yMS40M1EuOTcxIDY3LjA1Ni0uMDU0IDUzLjE4di02LjQ3M0MxLjM2MiAzMC43ODEgOC41MDMgMTguMTQ4IDIxLjM3IDguODE3IDI5LjA0NyAzLjU2MiAzNy41MjcuNjA0IDQ2LjgyMS0uMDU2IiBzdHlsZT0ic3Ryb2tlOm5vbmU7ZmlsbC1ydWxlOmV2ZW5vZGQ7ZmlsbDojZWNlY2VjO2ZpbGwtb3BhY2l0eToxIi8+PHBhdGggZD0iTTQ3LjI2NiAyLjk1N3EyMi41My0uNjUgMzcuNzc3IDE1LjczOGE0OS43IDQ5LjcgMCAwIDEgNi44NjcgMTAuMTU3cS00MS45NjQuMjIyLTgzLjkzIDAgOS43NS0xOC42MTYgMzAuMDI0LTI0LjM4N2E2MSA2MSAwIDAgMSA5LjI2Mi0xLjUwOCIgc3R5bGU9InN0cm9rZTpub25lO2ZpbGwtcnVsZTpldmVub2RkO2ZpbGw6IzE5MTkxOTtmaWxsLW9wYWNpdHk6MSIvPjxwYXRoIGQ9Ik03Ljk4IDcwLjkyNmMyNy45NzctLjAzNSA1NS45NTQgMCA4My45My4xMTNRODMuNDI2IDg3LjQ3MyA2Ni4xMyA5NC4wODZxLTE4LjgxIDYuNTQ0LTM2LjgzMi0xLjg5OC0xNC4yMDMtNy4wOS0yMS4zMTctMjEuMjYyIiBzdHlsZT0ic3Ryb2tlOm5vbmU7ZmlsbC1ydWxlOmV2ZW5vZGQ7ZmlsbDojZjlhZjAwO2ZpbGwtb3BhY2l0eToxIi8+PC9zdmc+\" \u002F>\u003C\u002Fa>\n\u003C\u002Fp>\n中文文档 (Chinese): [README.zh-CN.md](.\u002FREADME.zh-CN.md)\n\n\nA practical Douyin downloader supporting videos, image-notes, collections, music, favorites collections, and profile batch downloads, with progress display, retries, SQLite deduplication, download integrity checks, and browser fallback support.\n\n> This document targets **V2.0 (`main` branch)**.  \n> For the legacy version, switch to **V1.0**: `git fetch --all && git switch V1.0`\n\n## Feature Overview\n\n### Supported\n\n| Feature | Description |\n|---------|-------------|\n| Single video download | `\u002Fvideo\u002F{aweme_id}` |\n| Single image-note download | `\u002Fnote\u002F{note_id}` and `\u002Fgallery\u002F{note_id}` |\n| Single collection download | `\u002Fcollection\u002F{mix_id}` and `\u002Fmix\u002F{mix_id}` |\n| Single music download | `\u002Fmusic\u002F{music_id}` (prefers direct audio, fallback to first related aweme) |\n| Short link parsing | `https:\u002F\u002Fv.douyin.com\u002F...`, `v.iesdouyin.com`, bare hosts |\n| Profile batch download | `\u002Fuser\u002F{sec_uid}` + `mode: [post, like, mix, music]` |\n| Logged-in favorites collections | `\u002Fuser\u002Fself?showTab=favorite_collection` + `mode: [collect, collectmix]` |\n| No-watermark preferred | Automatically selects watermark-free video source |\n| Highest-quality selection | Auto-picks highest bitrate from `video.bit_rate` ladder (video + live-photo) |\n| **Live stream recording** | `live.douyin.com\u002F{room_id}` → FLV\u002FHLS, preserves partial data on stream end |\n| **Comments collection** | Per-aweme comments (+ optional replies) saved as `*_comments.json` |\n| **Hot search + keyword search** | `--hot-board [N]` \u002F `--search \"keyword\"` dumps to JSONL |\n| **REST API server mode** | `--serve --serve-port 8000` (optional `fastapi + uvicorn`) |\n| **Notification push** | Bark \u002F Telegram \u002F Webhook on download completion |\n| Extra assets | Cover, music, avatar, JSON metadata |\n| Video transcription | Optional, using OpenAI Transcriptions API |\n| Concurrent downloads | Configurable concurrency, default 5 |\n| Retry with backoff | Exponential backoff (1s, 2s, 5s) |\n| Rate limiting | Default 2 req\u002Fs |\n| SQLite deduplication | Database + local file dual dedup |\n| Incremental downloads | `increase.post\u002Flike\u002Fmix\u002Fmusic` |\n| Time filters | `start_time` \u002F `end_time` |\n| Browser fallback | Launches browser when pagination is blocked, manual CAPTCHA supported |\n| Download integrity check | Content-Length validation, auto-cleanup of incomplete files |\n| Progress display | Rich progress bars, supports `progress.quiet_logs` quiet mode |\n| Docker deployment | Dockerfile included |\n| CI\u002FCD | GitHub Actions for testing and linting |\n\n### Current Limitations\n\n- Browser fallback is fully validated for `post`; `like\u002Fmix\u002Fmusic` currently relies on API pagination\n- `number.allmix` \u002F `increase.allmix` are retained as compatibility aliases and normalized to `mix`\n- `collect` \u002F `collectmix` currently work for the account represented by the logged-in cookies only\n- `collect` \u002F `collectmix` must be used alone and cannot be combined with `post` \u002F `like` \u002F `mix` \u002F `music`\n- `increase` currently applies to `post` \u002F `like` \u002F `mix` \u002F `music`; favorites collection modes do not support incremental stop\n- Live stream recording saves FLV natively; HLS sources only save the playlist (use ffmpeg for playable output)\n- The webcast room endpoint is not verified against every live scenario — treat as experimental\n\n## Quick Start\n\n### 1) Requirements\n\n- Python 3.8+\n- macOS \u002F Linux \u002F Windows\n\n### 2) Install dependencies\n\n```bash\npip install -r requirements.txt\n```\n\nFor browser fallback and automatic cookie capture:\n\n```bash\npip install playwright\npython -m playwright install chromium\n```\n\n### 3) Copy config file\n\n```bash\ncp config.example.yml config.yml\n```\n\n### 4) Get cookies (recommended: automatic)\n\n```bash\npython -m tools.cookie_fetcher --config config.yml\n```\n\nAfter logging into Douyin, return to the terminal and press Enter. Cookies will be written to your config automatically.\n\n### 5) Docker deployment (optional)\n\n```bash\ndocker build -t douyin-downloader .\ndocker run -v $(pwd)\u002Fconfig.yml:\u002Fapp\u002Fconfig.yml -v $(pwd)\u002FDownloaded:\u002Fapp\u002FDownloaded douyin-downloader\n```\n\n## Minimal Working Config\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fuser\u002FMS4wLjABAAAAxxxx\n\npath: .\u002FDownloaded\u002F\nmode:\n  - post\n\nnumber:\n  post: 0\n  collect: 0\n  collectmix: 0\n\nthread: 5\nretry_times: 3\nproxy: \"\"\ndatabase: true\ndatabase_path: dy_downloader.db\n\nprogress:\n  quiet_logs: true\n\ncookies:\n  msToken: \"\"\n  ttwid: YOUR_TTWID\n  odin_tt: YOUR_ODIN_TT\n  passport_csrf_token: YOUR_CSRF_TOKEN\n  sid_guard: \"\"\n\nbrowser_fallback:\n  enabled: true\n  headless: false\n  max_scrolls: 240\n  idle_rounds: 8\n  wait_timeout_seconds: 600\n\ntranscript:\n  enabled: false\n  model: gpt-4o-mini-transcribe\n  output_dir: \"\"\n  response_formats: [\"txt\", \"json\"]\n  api_url: https:\u002F\u002Fapi.openai.com\u002Fv1\u002Faudio\u002Ftranscriptions\n  api_key_env: OPENAI_API_KEY\n  api_key: \"\"\n```\n\n## Usage\n\n### Run with a config file\n\n```bash\npython run.py -c config.yml\n```\n\n### Append CLI arguments\n\n```bash\npython run.py -c config.yml \\\n  -u \"https:\u002F\u002Fwww.douyin.com\u002Fvideo\u002F7604129988555574538\" \\\n  -t 8 \\\n  -p .\u002FDownloaded\n```\n\n### Arguments\n\n| Argument | Description |\n|----------|-------------|\n| `-u, --url` | Append download link(s), can be repeated |\n| `-c, --config` | Specify config file (default: `config.yml`) |\n| `-p, --path` | Specify download directory |\n| `-t, --thread` | Specify concurrency |\n| `--show-warnings` | Show warning\u002Ferror logs |\n| `-v, --verbose` | Show info\u002Fwarning\u002Ferror logs |\n| `--hot-board [N]` | Fetch Douyin hot search board and write JSONL; optional top-N |\n| `--search KEYWORD` | Search videos by keyword, write JSONL |\n| `--search-max N` | Max items for `--search` (default 50) |\n| `--serve` | Run as REST API server (requires `pip install fastapi uvicorn`) |\n| `--serve-host HOST` | REST server listen host (default 127.0.0.1) |\n| `--serve-port PORT` | REST server listen port (default 8000) |\n| `--version` | Show version number |\n\n## Typical Scenarios\n\n### Download one video\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fvideo\u002F7604129988555574538\n```\n\n### Download one image-note\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fnote\u002F7341234567890123456\n```\n\n### Download a collection\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fcollection\u002F7341234567890123456\n```\n\n### Download a music track\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fmusic\u002F7341234567890123456\n```\n\n### Batch download a creator's posts\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fuser\u002FMS4wLjABAAAAxxxx\nmode:\n  - post\nnumber:\n  post: 50\n```\n\n### Batch download a creator's liked posts\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fuser\u002FMS4wLjABAAAAxxxx\nmode:\n  - like\nnumber:\n  like: 0    # 0 means download all\n```\n\n### Download multiple modes at once\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fuser\u002FMS4wLjABAAAAxxxx\nmode:\n  - post\n  - like\n  - mix\n  - music\n```\n\nCross-mode deduplication: the same aweme_id won't be downloaded twice across different modes.\n\n### Download logged-in favorites collection items\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fuser\u002Fself?showTab=favorite_collection\nmode:\n  - collect\nnumber:\n  collect: 0\n```\n\n### Download logged-in collected mixes\n\n```yaml\nlink:\n  - https:\u002F\u002Fwww.douyin.com\u002Fuser\u002Fself?showTab=favorite_collection\nmode:\n  - collectmix\nnumber:\n  collectmix: 0\n```\n\n### Record a live stream (experimental)\n\n```yaml\nlink:\n  - https:\u002F\u002Flive.douyin.com\u002F123456789   # or \u002Ffollow\u002Flive\u002F{room_id}\nlive:\n  max_duration_seconds: 3600   # 0 = record until broadcaster ends\n  chunk_size: 65536\n  idle_timeout_seconds: 30\n```\n\nThe recorder saves an FLV file under `Downloaded\u002F{author}\u002Flive\u002F` plus a `*_room.json`\nmetadata snapshot. If the broadcaster ends the stream, network goes idle, or you\nCtrl+C, any already-recorded bytes are preserved (the `.tmp` file is promoted to\nthe final file).\n\n### Collect comments per aweme\n\n```yaml\ncomments:\n  enabled: true\n  include_replies: false   # true will fetch each comment's second-level replies (extra API calls)\n  max_comments: 500        # 0 = no cap\n  page_size: 20\n```\n\nGenerates a `{date}_{title}_{aweme_id}_comments.json` next to the media file.\n\n### Dump the hot search board\n\n```bash\npython run.py --hot-board 30 -p .\u002FDownloaded\n# Output: .\u002FDownloaded\u002Fhot_board\u002F20260424_221530.jsonl\n```\n\n### Search by keyword\n\n```bash\npython run.py --search \"猫咪\" --search-max 100 -p .\u002FDownloaded\n# Output: .\u002FDownloaded\u002Fsearch\u002F猫咪_20260424_221530.jsonl\n```\n\n### Run as REST API server\n\n```bash\npip install fastapi uvicorn       # one-time optional dep\npython run.py --serve --serve-port 8000\n```\n\nEndpoints:\n\n| Method | Path | Description |\n|--------|------|-------------|\n| POST | `\u002Fapi\u002Fv1\u002Fdownload` | Submit `{\"url\": \"...\"}`, returns `{job_id, status}` |\n| GET | `\u002Fapi\u002Fv1\u002Fjobs\u002F{job_id}` | Get a specific job's status\u002Fcounts |\n| GET | `\u002Fapi\u002Fv1\u002Fjobs` | List recent jobs (TTL + capacity capped) |\n| GET | `\u002Fapi\u002Fv1\u002Fhealth` | Health probe |\n\nFinished jobs are pruned by TTL (default 24h) and max-jobs (default 500) — in-flight jobs are never pruned. Configure via `server.max_jobs` \u002F `server.job_ttl_seconds`.\n\n### Send a notification on completion\n\n```yaml\nnotifications:\n  enabled: true\n  on_success: true\n  on_failure: true\n  providers:\n    - type: bark\n      url: https:\u002F\u002Fapi.day.app\u002FYOUR_DEVICE_KEY\n      sound: bell\n    - type: telegram\n      bot_token: \"123456:ABC...\"\n      chat_id: \"987654321\"\n    - type: webhook                 # works with 企业微信\u002F飞书\u002F钉钉 bot URLs too\n      url: https:\u002F\u002Fqyapi.weixin.qq.com\u002Fcgi-bin\u002Fwebhook\u002Fsend?key=xxx\n      extra_body:\n        msgtype: text\n```\n\nAll enabled providers are notified in parallel; a failing provider never blocks the download flow.\n\n\n### Incremental download (only new items)\n\n```yaml\nincrease:\n  post: true\ndatabase: true    # incremental mode requires database\n```\n\n### Full crawl (no item limit)\n\n```yaml\nnumber:\n  post: 0\n```\n\n## Optional Feature: Video Transcription (`transcript`)\n\nCurrent behavior applies to **video items only** (image-note items do not generate transcripts).\n\n### 1) Enable in config\n\n```yaml\ntranscript:\n  enabled: true\n  model: gpt-4o-mini-transcribe\n  output_dir: \"\"        # empty: same folder as video; non-empty: mirrored to target dir\n  response_formats:\n    - txt\n    - json\n  api_key_env: OPENAI_API_KEY\n  api_key: \"\"           # can be set directly, or via environment variable\n```\n\nRecommended to provide key through environment variable:\n\n```bash\nexport OPENAI_API_KEY=\"sk-xxxx\"\n```\n\n### 2) Output files\n\nWhen enabled, it generates:\n\n- `xxx.transcript.txt`\n- `xxx.transcript.json`\n\nIf `database: true`, job status is also recorded in SQLite table `transcript_job` (`success\u002Ffailed\u002Fskipped`).\n\n## Testing\n\nRecommended:\n\n```bash\npython3 -m pytest -q\n```\n\nPlain `pytest` is also supported now:\n\n```bash\npytest -q\n```\n\n## Key Config Fields\n\n| Field | Description |\n|-------|-------------|\n| `mode` | Supports `post`\u002F`like`\u002F`mix`\u002F`music`; logged-in favorites mode additionally supports standalone `collect`\u002F`collectmix` |\n| `number.post\u002Flike\u002Fmix\u002Fmusic\u002Fcollect\u002Fcollectmix` | Per-mode download limit, 0 = unlimited |\n| `increase.post\u002Flike\u002Fmix\u002Fmusic` | Per-mode incremental toggle |\n| `start_time` \u002F `end_time` | Time filter (format: `YYYY-MM-DD`) |\n| `folderstyle` | Create per-item subdirectories |\n| `browser_fallback.*` | Browser fallback for `post` when pagination is restricted |\n| `progress.quiet_logs` | Quiet logs during progress stage |\n| `transcript.*` | Optional transcription after video download |\n| `comments.*` | Per-aweme comments collection (opt-in) |\n| `live.*` | Live stream recording options (max_duration_seconds \u002F chunk_size \u002F idle_timeout_seconds) |\n| `notifications.*` | Bark\u002FTelegram\u002FWebhook push on completion |\n| `server.*` | REST API server tuning (max_jobs, job_ttl_seconds) |\n| `proxy` | HTTP\u002FHTTPS proxy for API requests and media downloads, e.g. `http:\u002F\u002F127.0.0.1:7890` |\n| `database` | Enable SQLite deduplication and history |\n| `database_path` | SQLite path, default is `dy_downloader.db` in the current working directory |\n| `thread` | Concurrent download count |\n| `retry_times` | Retry count on failure |\n\n## Output Structure\n\nDefault with `folderstyle: true` and `database_path: dy_downloader.db`:\n\n```text\nworkspace\u002F\n├── config.yml\n├── dy_downloader.db          # default location when database: true\n└── Downloaded\u002F\n    ├── download_manifest.jsonl\n    ├── hot_board\u002F                # when --hot-board is used\n    │   └── 20260424_221530.jsonl\n    ├── search\u002F                   # when --search is used\n    │   └── 猫咪_20260424_221530.jsonl\n    └── AuthorName\u002F\n        ├── post\u002F\n        │   └── 2024-02-07_Title_aweme_id\u002F\n        │       ├── ...mp4\n        │       ├── ..._cover.jpg\n        │       ├── ..._music.mp3\n        │       ├── ..._data.json\n        │       ├── ..._avatar.jpg\n        │       ├── ..._comments.json    # when comments.enabled\n        │       ├── ...transcript.txt\n        │       └── ...transcript.json\n        ├── like\u002F\n        │   └── ...\n        ├── mix\u002F\n        │   └── ...\n        ├── music\u002F\n        │   └── ...\n        ├── collect\u002F\n        │   └── ...\n        ├── collectmix\u002F\n        │   └── ...\n        └── live\u002F                 # when recording live streams\n            └── 2026-04-24_2215_LiveTitle_RoomId\u002F\n                ├── ...flv\n                └── ..._room.json\n```\n\n## Re-downloading Content\n\nThe program uses a **database record + local file** dual check to decide whether to skip already-downloaded content. To force re-download, you need to clean up accordingly:\n\n### Re-download a specific item\n\n```bash\n# Delete local files (folder name contains the aweme_id)\nrm -rf Downloaded\u002FAuthorName\u002Fpost\u002F*_\u003Caweme_id>\u002F\n\n# Delete database record\nsqlite3 dy_downloader.db \"DELETE FROM aweme WHERE aweme_id = '\u003Caweme_id>';\"\n```\n\n### Re-download all items from a specific author\n\n```bash\nrm -rf Downloaded\u002FAuthorName\u002F\nsqlite3 dy_downloader.db \"DELETE FROM aweme WHERE author_name = 'AuthorName';\"\n```\n\n### Full reset (re-download everything)\n\n```bash\nrm -rf Downloaded\u002F\nrm dy_downloader.db\n```\n\n> **Note:** Deleting only the database but keeping files will NOT trigger re-download — the program scans local filenames for aweme_id to detect existing downloads. Deleting only files but keeping the database WILL trigger re-download (the program treats \"in DB but missing locally\" as needing retry).\n\n## FAQ\n\n### 1) Why do I only get around 20 posts?\n\nThis is a common pagination risk-control behavior. Make sure:\n\n- `browser_fallback.enabled: true`\n- `browser_fallback.headless: false`\n- complete verification manually in the browser popup, and do not close it too early\n\n### 2) Why is the progress output noisy\u002Frepeated?\n\nBy default, `progress.quiet_logs: true` suppresses logs during progress stage.  \nUse `--show-warnings` or `-v` temporarily when debugging.\n\n### 3) What if cookies are expired?\n\nRun:\n\n```bash\npython -m tools.cookie_fetcher --config config.yml\n```\n\n### 4) Why are transcript files not generated?\n\nCheck in order:\n\n- whether `transcript.enabled` is `true`\n- whether downloaded items are videos (image-notes are not transcribed)\n- whether `OPENAI_API_KEY` (or `transcript.api_key`) is valid\n- whether `response_formats` includes `txt` or `json`\n\n### 5) How to view download history?\n\n```bash\nsqlite3 dy_downloader.db \"SELECT aweme_id, title, author_name, datetime(download_time, 'unixepoch', 'localtime') FROM aweme ORDER BY download_time DESC LIMIT 20;\"\n```\n\n## Legacy Version (V1.0)\n\nIf you prefer the legacy script style (V1.0):\n\n```bash\ngit fetch --all\ngit switch V1.0\n```\n\n## Community Group\n\n\u003Cimg src=\".\u002Fimg\u002Ffuye.jpg\" alt=\"qun\" width=\"360\" \u002F>\n\n点击链接加入群聊【QQ群】：[https:\u002F\u002Fqm.qq.com\u002Fq\u002FGDCzZCO3mM](https:\u002F\u002Fqm.qq.com\u002Fq\u002FGDCzZCO3mM)\n\n## Disclaimer\n\nThis project is for technical research, learning, and personal data management only. Please use it legally and responsibly:\n\n- Do not use it to infringe others' privacy, copyright, or other legal rights\n- Do not use it for any illegal purpose\n- Users are solely responsible for all risks and liabilities arising from usage\n- If platform policies or interfaces change and features break, this is a normal technical risk\n\nBy continuing to use this project, you acknowledge and accept the statements above.\n\n## License\n\nThis project is licensed under the MIT License. See [LICENSE](.\u002FLICENSE) for details.\n","这是一个实用的抖音下载工具，支持无水印视频、图集、合集、音乐等单个内容及用户主页批量下载。其核心功能包括进度显示、重试机制、SQLite去重以及浏览器回退支持，确保下载过程稳定高效。该工具采用Python编写，适用于需要保存抖音平台上的各类多媒体内容到本地的场景，如个人收藏、数据分析等。MIT许可证下免费使用。",2,"2026-06-11 03:35:43","high_star"]