douyin-mcp-server
抖音リンクの文字起こしとナレーション原稿の整理
抖音の共有リンクからメディアを自動解析し、ローカルで逐語稿を生成して、使えるナレーション原稿に整理します。

本プロジェクトは yzfly/douyin-mcp-server をベースに継続メンテナンスしています。元プロジェクトの Apache-2.0 ライセンスを保持します。
✨ 機能
🎬 透かしなし動画 - 高画質・透かしなし動画のダウンロードリンクを取得
🛟 自動フォールバック - HTTP 解析失敗時は共有 Playwright を使用して署名付き音声を取得
🎙️ ローカル音声認識 -
faster-whisper-medium / CPU int8、ASR API を消費しない✍️ ナレーション原稿の整理 - DeepSeek が重複を除去し、句読点と構造を補完、元の意味を保持
🌐 WebUI - モダンなブラウザインターフェース、コマンドライン不要
🔌 MCP 統合 - Claude Desktop などの AI アプリに対応
Related MCP server: Douyin Video Analysis MCP
プロジェクト構成
assets/ 预览图和发布用 skill 包
douyin_mcp_server/ Python 核心包
scripts/ 命令行入口
skills/douyin-video/ 可复用的工作流说明
tests/ 单元测试
web/ FastAPI WebUI📦 利用方法
方法 | 適用シーン | 特徴 |
一般ユーザー | ブラウザ操作で最も簡単 | |
Claude Desktop ユーザー | AI 対話内で直接呼び出し | |
開発者 | バッチ処理、スクリプト連携 |
🌐 WebUI (推奨)
最も簡単な利用方法です。ブラウザを開くだけで使えます。
クイックスタート
# 1. 克隆你自己的仓库
git clone <your-repository-url>
cd douyin-mcp-server
# 2. 安装依赖
uv sync --extra web
# 3. 启动服务
uv run python web/app.pyブラウザを開いて http://localhost:8080 にアクセスします
DeepSeek API Key の設定
API Key の設定方法は2つあります:
方法1:ブラウザ内で設定
WebUI ページを開く
上部の「API 未配置」ボタンをクリック
ポップアップで API Key を入力して保存
API Key はブラウザのローカルに保存され、抽出リクエストのときだけローカルサービスに送信されます
方法2:環境変数
export DOUYIN_DEEPSEEK_API_KEY="<your-deepseek-api-key>"
uv run python web/app.pyローカル ASR にキーは不要です。DeepSeek Key は最後のナレーション原稿の整理にのみ使用します。
機能説明
操作 | 説明 | API 必要 |
情報取得 | 動画タイトル・ID を解析し、透かしなしダウンロードリンクを取得 | ❌ |
テキスト抽出 | HTTP/Playwright → 音声 → ローカル ASR → DeepSeek | ✅(整理のみ) |
動画ダウンロード | ダウンロードリンクをクリックして透かしなし動画を保存 | ❌ |
テキストのコピー/ダウンロード | Markdown 形式のテキストをワンクリックでコピーまたはダウンロード | - |
利用手順
リンクを貼り付け - 共有リンクを入力欄に貼り付け
ボタンをクリック - 「情報取得」または「テキスト抽出」を選択
結果を確認 - 右側に動画情報と抽出されたテキストが表示
エクスポート - テキストをコピーするか Markdown ファイルをダウンロード
🚀 MCP Server
Claude Desktop、Cherry Studio など MCP 対応アプリで使用します。
設定方法
MCP 設定ファイルを編集して、次を追加します:
{
"mcpServers": {
"douyin-mcp": {
"command": "uvx",
"args": ["douyin-mcp-server"],
"env": {
"DOUYIN_DEEPSEEK_API_KEY": "<your-deepseek-api-key>"
}
}
}
}DOUYIN_DEEPSEEK_API_KEY は実行環境にのみ置き、リポジトリ・出力ファイル・実行レポートには書き込まないでください。
利用可能なツール
ツール名 | 機能 | API 必要 |
| 動画情報を解析 | ❌ |
| ダウンロードリンクを取得 | ❌ |
| 自動フォールバック、ローカル文字起こし、ナレーション原稿の整理 | ✅(整理のみ) |
| ローカル faster-whisper で音声を認識 | ❌ |
| オンライン音声リンクを認識 | ✅ (百炼) |
対話例
用户:帮我提取这个视频的文案 https://v.douyin.com/xxxxx/
Claude:我来帮你提取视频文案...
[调用 extract_douyin_text 工具]
提取完成,文案内容如下:
...🛠️ コマンドラインツール
開発者やバッチ処理のシーンに適しています。
インストール
git clone https://github.com/yzfly/douyin-mcp-server.git
cd douyin-mcp-server
uv syncコマンド説明
# 查看帮助
uv run python scripts/douyin_downloader.py --help
# 获取视频信息(无需 API)
uv run python scripts/douyin_downloader.py -l "分享链接" -a info
# 下载无水印视频
uv run python scripts/douyin_downloader.py -l "分享链接" -a download -o ./videos
# 提取文案(本地 ASR;整理阶段需要 DOUYIN_DEEPSEEK_API_KEY)
export DOUYIN_DEEPSEEK_API_KEY="<your-deepseek-api-key>"
uv run python scripts/douyin_downloader.py -l "分享链接" -a extract -o ./output
出力形式
output/
└── 7600361826030865707/
├── audio.m4a # 已校验的完整音频
├── transcript-raw.md # 本地 ASR 原始逐字稿
├── copy.md # DeepSeek 整理后的口播
├── metadata.json
└── run-report.json # 五阶段状态和验证证据📋 システム要件
依存 | 説明 | インストール方法 |
uv | Python パッケージ管理 |
|
Python | 3.10–3.13(推奨 3.12) |
|
FFmpeg | 音声・動画処理 |
|
faster-whisper medium | ローカル ASR 重み | デフォルトで |
Playwright | HTTP 解析失敗時のブラウザフォールバック | Windows では |
🔧 技術説明
固定ワークフロー
HTTP で共有リンクを解析。失敗時は自動で Playwright にフォールバック。
HTTP ブランチは動画をダウンロード。ブラウザブランチは Range で署名付き音声をダウンロード。
HTTP ブランチは FFmpeg で音声を抽出。ブラウザブランチは ffprobe で完全な音声を検証。
ローカルの
faster-whisper-medium / CPU int8でタイムスタンプ付き逐語稿を生成。DeepSeek でナレーション原稿に整理し、
run-report.jsonに書き込む。
📝 更新履歴
v1.5.0(現在のワークステーション版)
HTTP 解析失敗時に共有 Playwright へ自動フォールバック
ローカルの
faster-whisper-medium / CPU int8を使用し、ASR はクラウド API に依存しないDeepSeek V4 Flash でナレーション原稿を整理
音声、元の逐語稿、整理済み原稿、メタデータ、実行レポートを固定出力
v1.4.1
🔧 MCP Server 修正 -
API_KEYがドキュメントどおり硅基流动のキーに正しく対応し、旧版のDASHSCOPE_API_KEY設定とも互換性があります♻️ ツール復元 -
recognize_audio_file/recognize_audio_urlツールとextract_douyin_textのcontextパラメータを復元🛡️ WebUI セキュリティ強化 - ダウンロード API は任意の URL をプロキシせず、デフォルトでローカルのみをリッスン
⚡ WebUI パフォーマンス - テキスト抽出が他のリクエストをブロックしない
📦 依存関係の簡素化 - WebUI 依存をオプションインストールに変更(
pip install "douyin-mcp-server[web]")
v1.4.0
🌐 WebUI - ブラウザのビジュアルインターフェースを追加
🔑 ブラウザで API Key を設定 - 環境変数不要
📑 大容量ファイル対応 - 長い音声を自動分割して処理
v1.3.0
✨ Claude Code Skill 対応
📄 Markdown 形式での出力
v1.2.0
🔄 API アップグレード
v1.0.0
🎉 初回リリース
⚠️ 免責事項
本プロジェクトは学習・研究目的のみで使用
利用者は関連する法令を遵守する必要があります
知的財産権を侵害する行為への使用は禁止
本プロジェクトの使用によって生じた損害について、作者は責任を負いません
📄 ライセンス
Apache License 2.0
🤝 コントリビューション
Issue または Pull Request を送る前に CONTRIBUTING.md をお読みください。セキュリティ問題は SECURITY.md の方法に従って非公開で報告してください。
自分の GitHub リポジトリに公開する前に、pyproject.toml の project.urls を自分のリポジトリ URL に設定し、必要に応じてプロジェクト名と作者情報を変更してください。
アップストリーム
元プロジェクト作者:yzfly(GitHub)。
Available Tools
5 toolsextract_douyin_textA
从抖音分享链接提取视频中的文本内容
参数:
share_link: 抖音分享链接或包含链接的文本
model: 本地 faster-whisper 模型(可选,默认 medium)
context: 口播整理用途或额外要求(可选)
返回:
提取的文本内容
注意: 本地 ASR 不消耗 API;最后整理口播需要 DOUYIN_DEEPSEEK_API_KEY
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | ||
| context | No | ||
| share_link | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden. It usefully discloses that local ASR does not consume API quota and that final organization requires a DeepSeek API key. It does not mention failure modes, rate limits, video length constraints, or whether the tool downloads the video, so transparency is partial.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a one-sentence purpose, a parameter list, a return note, and an important API-key note. It is concise and front-loaded, with no significant redundancy, though the return line adds little beyond the output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers inputs, key dependencies, and a basic return value, which is enough for simple invocations. However, it lacks guidance on choosing between sibling tools, expected output format details, and operational constraints, so completeness is only moderate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates by explaining all three parameters: share_link can contain the link or surrounding text, model defaults to medium and is optional, and context defines the organization purpose or extra requirements. It adds meaningful semantics beyond the bare schema, though model choices and context format remain underspecified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear action: extracting text content from a Douyin video via a share link. It implies differentiation from siblings like get_douyin_download_link and recognize_audio_file/url by targeting share links and extracted text, though it does not explicitly name those alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when a Douyin share link is provided and text/口播 content is desired, and notes when DOUYIN_DEEPSEEK_API_KEY is required. However, it does not explicitly state when to prefer this tool over siblings such as recognize_audio_file, recognize_audio_url, or parse_douyin_video_info.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_douyin_download_linkA
获取抖音视频的无水印下载链接
参数:
share_link: 抖音分享链接或包含链接的文本
返回:
包含下载链接和视频信息的JSON字符串
| Name | Required | Description | Default |
|---|---|---|---|
| share_link | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It does disclose the return format (JSON string with download link and video info) and the watermark-free promise, but it omits any caveats about invalid links, request failures, or underlying network behavior. That is a moderate but not complete level of transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tightly written: a one-line purpose, a one-line parameter explanation, and a one-line return summary. No filler or repetition is present, and the key information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple and an output schema exists, so the return contract is already defined. However, the description does not explain how this download-link tool relates to siblings or what preconditions apply to the share_link, leaving some context gaps for an agent choosing among similar tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only provides the parameter name and type, while the description adds important meaning: the share_link can be a share link or any text containing the link. This materially helps the agent construct a valid invocation and justifies a score above the 0%-coverage baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('获取'/fetch) and a clear resource ('抖音视频的无水印下载链接'/watermark-free Douyin video download link), which differentiates it from siblings that extract text, recognize audio, or parse video info.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given about when to prefer this tool over the listed siblings such as parse_douyin_video_info or extract_douyin_text. The description only says what the tool does and the required parameter, leaving the selection decision entirely to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parse_douyin_video_infoB
解析抖音分享链接,获取视频基本信息
参数:
share_link: 抖音分享链接或包含链接的文本
返回:
视频信息(JSON格式字符串)
| Name | Required | Description | Default |
|---|---|---|---|
| share_link | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It only states the return format (JSON string) and omits network dependency, error behavior, rate limits, link-expiration handling, or behavior for invalid/ambiguous inputs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-organized into purpose, parameters, and return sections. Every sentence adds value, and the main action is front-loaded with no redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter parsing tool with an output schema available, the description covers the essential input and return contract. However, it lacks behavioral context such as error handling, network requirements, and link validity assumptions, making it only minimally complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates by explaining that share_link can be either a Douyin share link or text containing a link. This adds meaningful semantics beyond the bare schema property title 'Share Link' and clearly documents the only parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (parse a Douyin share link) and the outcome (retrieve basic video information), which distinguishes it from the download/text/audio sibling tools by resource and purpose. However, it does not explicitly contrast itself with those siblings, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The intended use is implied: when the agent receives a Douyin share link and needs basic video info, this tool is appropriate. But there is no explicit guidance about when not to use it or when to prefer siblings like get_douyin_download_link or extract_douyin_text.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recognize_audio_fileA
识别本地音频文件中的文本
参数:
file_path: 本地音频文件路径
context: 上下文文本,用于提高识别准确率(可选)
language: 指定语言代码(如 'zh', 'en'),可选,默认自动检测
model: 语音识别模型(可选,默认使用qwen3-asr-flash)
返回:
识别的文本内容
注意: 使用本机 faster-whisper,默认 medium / CPU int8,不消耗 API
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | ||
| context | No | ||
| language | No | ||
| file_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and delivers: it discloses local inference via faster-whisper, the default 'medium / CPU int8' engine, and zero API consumption. A minor flaw is the internal inconsistency between the model parameter's stated default 'qwen3-asr-flash' and the faster-whisper medium default, but the core safety/cost behavior is clearly revealed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is cleanly organized—purpose, parameters, returns, and a behavioral note—with the purpose statement front-loaded. The parameter block earns its place because the schema has no descriptions at all, so it is not redundant, though the layout is conventional rather than exceptionally tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter tool with no annotations, the description is largely complete: it covers purpose, all parameters, the return value ('识别的文本内容'), and operational context in one place. It omits supported audio formats, file-size/duration limits, and error behavior, which would round it out for a local ASR tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description fully compensates by documenting every parameter: file_path as a local path, context as an accuracy-improving optional text, language with 'zh'/'en' examples and auto-detection default, and model with its default. This is exactly the semantic meaning the bare input schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line '识别本地音频文件中的文本' states a specific verb (识别/recognize), a resource (audio files), and a scope qualifier (本地/local), so an agent knows immediately this transcribes local audio. The '本地' qualifier also distinguishes it from the sibling recognize_audio_url, which targets remote audio.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: it operates on local file paths via '本机 faster-whisper' with CPU int8 and notes '不消耗 API', signaling an offline, no-cost transcription use case. However, it never explicitly names the alternative (recognize_audio_url) or states when not to use this tool, leaving sibling routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recognize_audio_urlA
识别在线音频URL中的文本
参数:
audio_url: 音频URL链接
context: 上下文文本,用于提高识别准确率(可选)
language: 指定语言代码(如 'zh', 'en'),可选,默认自动检测
model: 语音识别模型(可选,默认使用qwen3-asr-flash)
返回:
识别的文本内容
注意: 需要设置环境变量 DASHSCOPE_API_KEY
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | ||
| context | No | ||
| language | No | ||
| audio_url | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavior disclosure burden. It discloses the DASHSCOPE_API_KEY environment variable requirement, the default model, the auto-detect behavior for language, and the return type. It stops short of mentioning external data transmission, rate limits, or failure behavior, so it isn't perfect.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a concise structured list with a one-line purpose, parameter definitions, return value, and a single operational note. No sentence is wasted, and the most important info is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema and the description, the agent knows all parameters, defaults, the required API key, and what is returned. It lacks explicit usage-contrast guidance and format constraints for the URL, but those are minor for a straightforward transcription tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description compensates by explaining every parameter: audio_url is the link, context is optional textual context for improved accuracy, language accepts codes like 'zh'/'en', and model defaults to qwen3-asr-flash. The defaults and optionality are explicitly stated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the verb 'recognize' and resource 'online audio URL' and result 'text' in the first line, making the tool's purpose unambiguous. It is naturally distinguished from sibling recognize_audio_file because it targets URLs rather than files.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for online audio URLs through its name and opening phrase, but does not explicitly contrast it with the sibling recognize_audio_file or other alternatives. There is no when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v1.5.0- First observed
extract_douyin_text - First observed
get_douyin_download_link - First observed
parse_douyin_video_info - First observed
recognize_audio_file - First observed
recognize_audio_url
TDQS
Scored across 5 tools
每个工具的功能明确区分:下载链接、提取文本、识别音频(文件/URL)、解析信息,无重叠或模糊之处。
所有工具均使用动词+名词的snake_case命名,但动词不统一(get, extract, recognize, parse),不过每个名称都清晰描述了操作,整体可接受。
5个工具覆盖了抖音视频处理的核心功能,规模适中,既不过度也不精简。
涵盖了链接获取、文本提取、音频识别和视频信息解析等主要操作,但缺少例如搜索或评论等扩展功能,不过对当前领域而言已较完整。
Maintenance
Related MCP Connectors
MCP server for RiverScript, an AI transcription platform - fetches transcripts shared via a link.
MCP server for Kling AI video generation
An MCP server that gives any LLM or agent clean YouTube transcripts on demand: a single video, a whole channel, or a playlist, plus AI cleanup of auto-generated captions. API-key auth, credit-based, same backend as the public v1 API. Get a free API key with 25 free credits at youtubetranscriptdownload.com/account.
MCP server: AI-agent access to Chinese social & trend signals — Douyin, Weibo, Xiaohongshu/RedNote,
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP server that downloads videos/extracts audio from various platforms like YouTube, Bilibili, and TikTok, then transcribes them to text using OpenAI's Whisper model.12MIT
- AlicenseAqualityCmaintenanceAn MCP server that parses Douyin share links and performs intelligent content analysis using the Doubao video understanding model. It provides structured outputs including video summaries, categorized outlines, and step-by-step tutorial information.12MIT
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that downloads watermark-free videos from Douyin (TikTok China) share links, extracts audio, and transcribes speech to text using ASR APIs.2MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for fetching YouTube video transcripts without an API key.GPL 3.0