项目从单体结构重构为 pnpm monorepo (shared/backend/frontend), 新增 YouTube、Instagram、Twitter/X、哔哩哔哩、微博 5 个平台适配器, 包含完整的单元测试和 E2E 测试覆盖。 - 完成 T-031~T-044: 5 个适配器实现、注册、配置和测试 - 重构前后端分离: Hono 后端 + Next.js 前端 - 151 个单元测试 + 21 个 Mock E2E + 25 个真实 E2E - 适配器基于真实 TikHub API 响应结构实现 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
25 KiB
TikHub API 参考文档
版本:V5.2.9(2025-03-08) Swagger UI:https://api.tikhub.io ReDoc:https://api.tikhub.io/docs Apifox 文档:https://docs.tikhub.io
基础信息
| 项目 | 说明 |
|---|---|
| Base URL(国际) | https://api.tikhub.io |
| Base URL(中国大陆) | https://api.tikhub.dev(路径和参数完全相同,仅域名不同) |
| 认证方式 | Authorization: Bearer {API_TOKEN} |
| 计费 | $0.001 / 请求(按量付费,支持批量折扣) |
| 速率限制 | 令牌桶 10 req/s(本项目在 src/lib/tikhub.ts 中已实现) |
| 超时 | 15s(本项目已配置) |
所有端点均为 GET 请求(除特别标注),返回 JSON。
错误码
| HTTP 状态码 | 含义 |
|---|---|
| 400 | 参数错误 |
| 401 | API Key 无效或未提供 |
| 402 | 余额不足 |
| 403 | 无权限访问该端点 |
| 404 | 内容不存在 |
| 429 | 请求过于频繁 |
| 500 | 服务器内部错误 |
抖音(Douyin)
抖音网页版 API — /api/v1/douyin/web/
★ GET /api/v1/douyin/web/fetch_hot_search_result
本项目使用 · 抖音热搜榜
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 无 | — | — | 无需参数 |
响应结构:
{
"data": {
"data": {
"trending_list": [
{
"sentence_id": "string", // 热搜词 ID(用作 ContentItem.id)
"word": "string", // 热搜词文本
"word_cover": {
"url_list": ["string"] // 封面图列表
},
"hot_value": 10000, // 热度值(→ like_count)
"view_count": 500000, // 阅读量(→ play_count)
"discuss_video_count": 200, // 讨论视频数(→ comment_count)
"event_time": 1709000000 // Unix 时间戳(秒)
}
],
"word_list": [/* 同上格式,普通热词 */]
}
}
}
注意:
trending_list为置顶热搜,word_list为普通热词。本项目合并两者并按sentence_id去重。
★ GET /api/v1/douyin/web/fetch_one_video
本项目使用 · 抖音视频详情
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
aweme_id |
string | 是 | 视频 ID |
响应结构:
{
"data": {
"aweme_detail": {
"aweme_id": "string",
"desc": "string", // 视频标题/描述
"video": {
"cover": { "url_list": ["string"] },
"play_addr": { "url_list": ["string"] }
},
"author": {
"nickname": "string",
"avatar_thumb": { "url_list": ["string"] }
},
"statistics": {
"play_count": 100000,
"digg_count": 5000, // 点赞数(→ like_count)
"comment_count": 200,
"share_count": 300
},
"create_time": 1709000000,
"text_extra": [{ "hashtag_name": "string" }]
}
}
}
其他常用端点
| 端点 | 说明 | 关键参数 |
|---|---|---|
GET /api/v1/douyin/web/fetch_user_profile |
获取用户信息 | unique_id(用户名)或 sec_user_id |
GET /api/v1/douyin/web/fetch_user_post |
获取用户作品 | sec_user_id, cursor(分页), count |
GET /api/v1/douyin/web/fetch_general_search_result |
综合搜索 | keyword, count, offset |
GET /api/v1/douyin/web/fetch_video_search_result |
视频搜索 | keyword, count, offset |
GET /api/v1/douyin/web/fetch_user_search_result_v2 |
用户搜索 | keyword |
GET /api/v1/douyin/web/fetch_post_comment |
获取评论 | aweme_id, cursor, count |
GET /api/v1/douyin/app/v3/fetch_hot_search_list |
App 热搜榜(App V3 推荐) | 无 |
GET /api/v1/douyin/billboard/* |
各类榜单(热门/音乐/挑战等) | 参见 Swagger |
TikTok
TikTok 网页版 API — /api/v1/tiktok/web/
★ GET /api/v1/tiktok/web/fetch_explore_post
本项目使用 · TikTok 探索/热门视频列表
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
count |
integer | 否 | 返回数量,默认 20 |
响应结构:
{
"data": {
"itemList": [
{
"id": "string", // 视频 ID
"desc": "string", // 视频描述/标题
"video": {
"cover": "string", // 封面图 URL(直接字符串)
"playAddr": "string" // 播放地址
},
"author": {
"nickname": "string",
"avatarThumb": "string", // 头像 URL
"uniqueId": "string" // 用户名(用于构建主页链接)
},
"stats": {
"playCount": 500000,
"diggCount": 25000, // 点赞数(→ like_count)
"commentCount": 1000,
"shareCount": 500
},
"createTime": 1709000000, // Unix 时间戳(秒)
"challenges": [{ "title": "string" }] // 话题标签(→ tags)
}
]
}
}
注意:
video.cover是直接字符串,不是数组(与抖音不同)。
★ GET /api/v1/tiktok/web/fetch_post_detail
本项目使用 · TikTok 视频详情
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
itemId |
string | 是 | 视频 ID |
响应结构:
{
"data": {
"itemInfo": {
"itemStruct": { /* 同 itemList 中的单条格式 */ }
}
}
}
其他常用端点
| 端点 | 说明 | 关键参数 |
|---|---|---|
GET /api/v1/tiktok/web/fetch_user_profile |
用户信息 | uniqueId 或 secUid |
GET /api/v1/tiktok/web/fetch_user_post |
用户作品 | secUid, cursor, count, post_item_list_request_type(0=默认/1=热门/2=最旧) |
GET /api/v1/tiktok/web/fetch_user_like |
用户喜欢(需公开) | secUid, cursor, count |
GET /api/v1/tiktok/web/fetch_post_comment |
视频评论 | aweme_id, cursor, count |
GET /api/v1/tiktok/web/fetch_search_video |
视频搜索 | keyword, count, offset, search_id |
GET /api/v1/tiktok/web/fetch_search_user |
用户搜索 | keyword, cursor, search_id |
GET /api/v1/tiktok/web/fetch_tag_detail |
话题详情 | tag_name |
GET /api/v1/tiktok/web/fetch_user_fans |
粉丝列表 | secUid, count(默认30) |
GET /api/v1/tiktok/web/fetch_user_follow |
关注列表 | secUid, count(默认30) |
POST /api/v1/tiktok/web/fetch_home_feed |
首页推荐 | count, cookie |
小红书(Xiaohongshu)
小红书 Web V2 API — /api/v1/xiaohongshu/web_v2/
★ GET /api/v1/xiaohongshu/web_v2/fetch_hot_list
本项目使用 · 获取热榜关键词列表(第一步)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 无 | — | — | 无需参数 |
响应结构:
{
"data": {
"data": {
"items": [
{ "title": "string" } // 热词标题,取第一个作为搜索关键词
]
}
}
}
小红书 App V2 API — /api/v1/xiaohongshu/app_v2/(推荐)
★ GET /api/v1/xiaohongshu/app_v2/search_notes
本项目使用 · 按关键词搜索笔记(第二步)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
keyword |
string | 是 | 搜索关键词 |
page |
integer | 否 | 页码,默认 1 |
响应结构:
{
"data": {
"data": {
"items": [
{
"model_type": "note", // 只处理 model_type==='note' 的条目
"note": {
"id": "string",
"title": "string",
"desc": "string",
"type": "normal | video",
"timestamp": 1709000000,
"images_list": [
{
"url": "string",
"url_size_large": "string" // 优先使用大图
}
],
"user": {
"nickname": "string",
"images": "string", // 头像 URL
"user_id": "string"
},
"liked_count": 5000, // 点赞数(数字类型)
"comments_count": 200, // 评论数(注意:有 's')
"shared_count": 100,
"collected_count": 300,
"tag_info": [{ "name": "string" }]
}
}
]
}
}
}
注意:
model_type不为"note"的条目(如广告)需过滤掉- 搜索结果中视频笔记的
video_url不可用,仅详情接口可获取视频链接
★ GET /api/v1/xiaohongshu/app_v2/get_mixed_note_detail
本项目使用 · 获取笔记详情
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
note_id |
string | 是 | 笔记 ID |
响应结构:
{
"data": {
"id": "string",
"title": "string",
"name": "string", // 备用标题字段
"desc": "string",
"type": "normal | video",
"timestamp": 1709000000,
"likes": 5000, // 点赞数(注意:详情与搜索字段名不同)
"comments_count": 200,
"shared_count": 100,
"collected_count": 300,
"images_list": [
{ "url": "string", "url_size_large": "string" }
],
"user": {
"nickname": "string",
"images": "string"
},
"tag_info": [{ "name": "string" }],
"video_info_v2": {
"url": "string" // 仅视频笔记有此字段
}
}
}
其他常用端点
| 端点 | 说明 | 关键参数 |
|---|---|---|
GET /api/v1/xiaohongshu/app_v2/fetch_note_detail |
笔记详情(旧版) | note_id |
GET /api/v1/xiaohongshu/web_v2/fetch_user_info |
用户信息 | user_id 或 username |
GET /api/v1/xiaohongshu/web_v2/fetch_user_notes |
用户笔记列表 | user_id, cursor |
GET /api/v1/xiaohongshu/app_v2/fetch_feed |
推荐信息流 | count |
哔哩哔哩(Bilibili)
Bilibili 网页版 API — /api/v1/bilibili/web/
★ GET /api/v1/bilibili/web/fetch_popular_video_list
本项目使用 · 综合热门视频列表
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
pn |
integer | 否 | 页码,默认 1 |
ps |
integer | 否 | 每页数量,默认 20 |
响应结构:
{
"data": {
"list": [
{
"bvid": "string", // 视频 BV 号(主要 ID)
"aid": 123456, // av 号(备用)
"title": "string",
"pic": "string", // 封面图 URL(直接字符串)
"desc": "string",
"owner": {
"mid": 123456,
"name": "string",
"face": "string" // UP 主头像
},
"stat": {
"view": 100000, // 播放量(→ play_count)
"like": 5000, // 点赞数
"reply": 200, // 评论数(→ comment_count)
"share": 300,
"danmaku": 500, // 弹幕数(未映射)
"favorite": 1000, // 收藏数(未映射)
"coin": 800 // 投币数(未映射)
},
"pubdate": 1709000000, // Unix 时间戳(秒)
"duration": 300, // 时长(秒)
"tname": "string", // 分区名(→ tags[0])
"tags": [{ "tag_id": 1, "tag_name": "string" }]
}
]
}
}
★ GET /api/v1/bilibili/web/fetch_video_detail
本项目使用 · 视频详情
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
bvid |
string | 是 | 视频 BV 号(如 BV1xx411c7mD) |
响应结构:
{
"data": { /* 同 list 中单条格式 */ }
}
其他常用端点
| 端点 | 说明 | 关键参数 |
|---|---|---|
GET /api/v1/bilibili/web/fetch_hot_search |
热搜词 | 无 |
GET /api/v1/bilibili/web/fetch_user_info |
UP 主信息 | mid(用户 ID) |
GET /api/v1/bilibili/web/fetch_user_videos |
UP 主视频列表 | mid, pn, ps |
GET /api/v1/bilibili/web/fetch_video_comment |
视频评论 | oid(aid), pn, ps |
GET /api/v1/bilibili/web/fetch_ranking |
全站排行榜(每日更新) | tid(分区ID), day(1/3/7) |
微博(Weibo)
微博 App API — /api/v1/weibo/app/
★ GET /api/v1/weibo/app/fetch_hot_search
本项目使用 · 微博热搜榜
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 无 | — | — | 无需参数 |
响应结构(两种格式,取其一):
格式 1:实际微博状态
{
"data": {
"statuses": [
{
"id": "string | number",
"mid": "string",
"text": "string", // HTML 格式,需 stripHtml 处理
"raw_text": "string",
"user": {
"screen_name": "string",
"profile_image_url": "string",
"avatar_hd": "string",
"avatar_large": "string"
},
"pic_ids": ["string"], // 图片 ID 列表
"pic_infos": {
"PIC_ID": {
"url": "string",
"large": { "url": "string" }
}
},
"attitudes_count": 5000, // 点赞数(→ like_count)
"comments_count": 200,
"reposts_count": 300, // 转发数(→ share_count)
"reads_count": 100000, // 阅读数(→ play_count)
"created_at": "Mon Jan 01 00:00:00 +0800 2024"
}
]
}
}
格式 2:热搜话题
{
"data": {
"band_list": [
{
"word": "string", // 热搜词
"num": 10000, // 热度(→ play_count)
"label_name": "string", // 标签(热、沸)
"mid": "string",
"rank": 1
}
],
"realtime": [/* 同上 */]
}
}
注意:
text字段含 HTML 标签(<a>,<span>等),需 strip 处理- 图片 URL 构建:
https://ww1.sinaimg.cn/large/{pic_id}.jpg- 时间格式:
"Mon Jan 01 00:00:00 +0800 2024",可直接用new Date()解析
★ GET /api/v1/weibo/app/fetch_post_detail
本项目使用 · 微博详情
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
mid |
string | 是 | 微博 ID |
响应结构:
{
"data": { /* 同 statuses 中单条格式 */ }
}
其他常用端点
| 端点 | 说明 | 关键参数 |
|---|---|---|
GET /api/v1/weibo/web/fetch_hot_search |
网页版热搜榜 | 无 |
GET /api/v1/weibo/web_v2/fetch_hot_search |
网页版 V2 热搜榜 | 无 |
GET /api/v1/weibo/web/fetch_user_info |
用户信息 | uid 或 screen_name |
GET /api/v1/weibo/web/fetch_user_statuses |
用户微博列表 | uid, page, count |
YouTube
YouTube 网页版 API — /api/v1/youtube/web/
★ GET /api/v1/youtube/web/fetch_trending_video
本项目使用 · YouTube 热门视频列表
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
count |
integer | 否 | 返回数量,默认 20 |
响应结构:
{
"data": {
"items": [
{
"id": "string | { videoId: string }", // 视频 ID(可能是字符串或对象)
"snippet": {
"title": "string",
"description": "string",
"channelTitle": "string",
"publishedAt": "2024-01-15T10:00:00Z", // ISO 8601
"thumbnails": {
"maxres": { "url": "string" },
"high": { "url": "string" },
"medium": { "url": "string" },
"default": { "url": "string" }
},
"tags": ["string"]
},
"statistics": {
"viewCount": "100000", // 注意:YouTube 统计字段是字符串类型
"likeCount": "5000", // 需 parseInt() 转换
"commentCount": "200"
}
}
]
}
}
注意:
statistics.viewCount等字段为字符串类型,需用parseInt()转换id字段可能是字符串或{ videoId: string }对象,需兼容处理- 缩略图优先级:
maxres > high > medium > default
★ GET /api/v1/youtube/web/fetch_video_detail
本项目使用 · YouTube 视频详情
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
video_id |
string | 是 | 视频 ID(如 dQw4w9WgXcQ) |
响应结构:
{
"data": {
"items": [{ /* 同 trending 中单条格式 */ }]
}
}
其他常用端点
| 端点 | 说明 | 关键参数 |
|---|---|---|
GET /api/v1/youtube/web/fetch_channel_info |
频道信息 | channel_id 或 username |
GET /api/v1/youtube/web/fetch_channel_videos |
频道视频列表 | channel_id, count, page_token |
GET /api/v1/youtube/web/fetch_search_results |
视频搜索 | keyword, count, page_token |
GET /api/v1/youtube/web/fetch_playlist_videos |
播放列表视频 | playlist_id, count, page_token |
Instagram 网页版 API — /api/v1/instagram/web/
★ GET /api/v1/instagram/web/fetch_explore_feed
本项目使用 · Instagram 探索页内容
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
count |
integer | 否 | 返回数量,默认 20 |
响应结构(两种格式,需同时处理):
格式 1:扁平 items 数组
{
"data": {
"items": [
{
"media": { /* InstagramMediaItem */ }
}
]
}
}
格式 2:分区 sectional_items
{
"data": {
"sectional_items": [
{
"layout_content": {
"medias": [
{ "media": { /* InstagramMediaItem */ } }
]
}
}
]
}
}
InstagramMediaItem 结构:
{
"pk": "string",
"id": "string",
"code": "string", // shortcode(用于构建 URL 和作为 ID)
"media_type": 1, // 1=图片, 2=视频, 8=轮播
"caption": { "text": "string" } | "string" | null,
"image_versions2": {
"candidates": [
{ "url": "string", "width": 1080, "height": 1080 }
]
},
"thumbnail_url": "string", // 视频封面(备用)
"video_url": "string", // 仅 media_type=2 时有值
"user": {
"username": "string",
"full_name": "string",
"profile_pic_url": "string"
},
"like_count": 5000,
"comment_count": 200,
"taken_at": 1709000000 // Unix 时间戳(秒)
}
注意:
- 以
code(shortcode)作为内容 ID,URL 格式:https://www.instagram.com/p/{code}/caption字段格式不固定,可能是对象、字符串或 null,需兼容处理
★ GET /api/v1/instagram/web/fetch_post_detail
本项目使用 · Instagram 帖子详情
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
shortcode |
string | 是 | 帖子 shortcode(即内容 ID) |
响应结构:
{
"data": {
"items": [{ /* InstagramMediaItem */ }]
}
}
其他常用端点
| 端点 | 说明 | 关键参数 |
|---|---|---|
GET /api/v1/instagram/web/fetch_user_info |
用户信息 | username |
GET /api/v1/instagram/web/fetch_user_posts |
用户帖子 | username, cursor, count |
GET /api/v1/instagram/web/fetch_search_result |
搜索用户/标签 | keyword |
GET /api/v1/instagram/web/fetch_hashtag_posts |
标签内容 | hashtag, cursor |
Twitter / X
Twitter 网页版 API — /api/v1/twitter/web/
★ GET /api/v1/twitter/web/fetch_trending_topics
本项目使用 · Twitter 热门话题和趋势推文
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
count |
integer | 否 | 返回数量,默认 20 |
响应结构(三种格式,需全部处理):
格式 1:推文数组
{
"data": {
"tweets": [
{
"id_str": "string",
"full_text": "string", // 优先使用
"text": "string", // 备用
"user": {
"name": "string",
"screen_name": "string", // 用户名(@后面的部分)
"profile_image_url_https": "string"
},
"favorite_count": 5000, // 点赞数(→ like_count)
"reply_count": 200, // 回复数(→ comment_count)
"retweet_count": 300, // 转推数(→ share_count)
"created_at": "Mon Jan 01 00:00:00 +0000 2024",
"entities": {
"media": [
{ "media_url_https": "string", "type": "photo | video" }
],
"hashtags": [{ "text": "string" }]
},
"extended_entities": {
"media": [/* 同上,优先使用 */]
}
}
]
}
}
格式 2:GraphQL 时间线(Timeline Instructions)
{
"data": {
"timeline": {
"instructions": [
{
"entries": [
{
"content": {
"itemContent": {
"tweet_results": {
"result": {
"legacy": { /* 同 TwitterTweet 格式 */ },
"core": {
"user_results": {
"result": {
"legacy": { /* TwitterUser 格式 */ }
}
}
}
}
}
}
}
}
]
}
]
}
}
}
格式 3:热门话题列表
{
"data": {
"trends": [
{
"name": "string", // 话题名称
"tweet_volume": 10000, // 推文量(→ play_count)
"query": "string" // URL 编码的搜索查询
}
]
}
}
注意:
- 时间格式:
"Mon Jan 01 00:00:00 +0000 2024",可直接用new Date()解析- 封面图来自
extended_entities.media(优先)或entities.media,找type === 'photo'的条目- 原帖 URL 格式:
https://x.com/{screen_name}/status/{id_str}
★ GET /api/v1/twitter/web/fetch_tweet_detail
本项目使用 · 推文详情
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
tweet_id |
string | 是 | 推文 ID |
响应结构(两种格式):
// 格式 1(GraphQL)
{
"data": {
"tweetResult": {
"result": {
"legacy": { /* TwitterTweet */ },
"core": { "user_results": { "result": { "legacy": { /* TwitterUser */ } } } }
}
}
}
}
// 格式 2(直接对象)
{
"data": {
"tweet": { /* TwitterTweet */ }
}
}
其他常用端点
| 端点 | 说明 | 关键参数 |
|---|---|---|
GET /api/v1/twitter/web/fetch_user_info |
用户信息 | screen_name |
GET /api/v1/twitter/web/fetch_user_tweets |
用户推文 | screen_name, cursor, count |
GET /api/v1/twitter/web/fetch_search_timeline |
搜索推文 | keyword, cursor, count |
GET /api/v1/twitter/web/fetch_tweet_replies |
推文回复 | tweet_id, cursor |
通用说明
本项目中使用的端点汇总
| 平台 | fetchHotList 端点 | fetchDetail 端点 |
|---|---|---|
| 抖音 | douyin/web/fetch_hot_search_result |
douyin/web/fetch_one_video → 回退 fetch_hot_search_result |
| TikTok | tiktok/web/fetch_explore_post |
tiktok/web/fetch_post_detail |
| 小红书 | xiaohongshu/web_v2/fetch_hot_list + xiaohongshu/app_v2/search_notes |
xiaohongshu/app_v2/get_mixed_note_detail |
| YouTube | youtube/web/fetch_trending_video |
youtube/web/fetch_video_detail |
instagram/web/fetch_explore_feed |
instagram/web/fetch_post_detail |
|
twitter/web/fetch_trending_topics |
twitter/web/fetch_tweet_detail |
|
| 哔哩哔哩 | bilibili/web/fetch_popular_video_list |
bilibili/web/fetch_video_detail |
| 微博 | weibo/app/fetch_hot_search |
weibo/app/fetch_post_detail |
时间戳处理
| 平台 | 时间格式 | 处理方式 |
|---|---|---|
| 抖音、TikTok、小红书、B站、微博、Instagram | Unix 时间戳(秒) | new Date(timestamp * 1000).toISOString() |
| YouTube | ISO 8601 字符串 | 直接使用 |
"Mon Jan 01 00:00:00 +0000 2024" |
new Date(dateStr).toISOString() |
|
| 微博 | "Mon Jan 01 00:00:00 +0800 2024" |
new Date(dateStr).toISOString() |
图片 URL 类型
| 平台 | 图片字段类型 |
|---|---|
| 抖音 | url_list: string[](取 [0]) |
| TikTok | cover: string(直接字符串) |
| 小红书 | images_list[0].url_size_large || url |
| B站 | pic: string(直接字符串) |
| YouTube | thumbnails.maxres.url(对象嵌套) |
image_versions2.candidates[0].url |
|
entities/extended_entities.media[0].media_url_https |
|
| 微博 | pic_infos[id].large.url 或 https://ww1.sinaimg.cn/large/{id}.jpg |
文档基于项目实际使用端点 + TikHub OpenAPI 规范整理。完整端点列表(700+)请访问 https://api.tikhub.io