mcpField
S
StoriesFly: Instagram and TikTok data

StoriesFly: Instagram and TikTok data

远程服务
storiesfly.com社交媒体04 天前更新

关于 StoriesFly: Instagram and TikTok data

StoriesFly 提供 TypeScript 客户端,通过 API 获取公开的 Instagram 和 TikTok 数据,面向构建数据工作流的开发者。其类型化方法涵盖个人资料、媒体、社交列表、搜索和下载,无需登录平台账户。

主要功能

  1. 01获取 Instagram 个人资料和内容
  2. 02获取 TikTok 个人资料与视频
  3. 03读取评论、关注者和列表
  4. 04搜索话题标签和地点
  5. 05下载媒体文件
  6. 06分页读取列表结果

适用场景

  1. 01查看公开的 Instagram 个人资料和帖子
  2. 02获取 TikTok 视频及账户数据
  3. 03分批收集关注者或关注列表
  4. 04从帖子链接下载媒体

MCP 相关

StoriesFly MCP 服务在 `https://storiesfly.com/mcp` 向 AI 助手提供相同的 Instagram 和 TikTok 数据。ChatGPT 和 Claude 连接该地址,并通过 Telegram 登录。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://storiesfly.com/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

详细介绍

storiesfly

CI npm version

用于 StoriesFly API 的 TypeScript 客户端。它通过 HTTP 读取 Instagram 和 TikTok 的公开数据。Instagram 数据包括:个人资料、快拍、精选快拍、帖子、Reels、评论、关注者、话题标签、地点和搜索。TikTok 数据包括:个人资料、视频、快拍、关注者和关注列表、转发,以及下载无水印视频。你无需登录 Instagram 或 TikTok,也无需处理 Cookie 或会话。只需发送 API 密钥并按请求付费。同样的数据也可通过 StoriesFly MCP 服务在 ChatGPT 和 Claude 中使用:参见在 ChatGPT 和 Claude 中使用(MCP)。

此软件包没有运行时依赖。它需要 Node 18 或更高版本(使用全局 fetch),仅支持 ESM,并自带类型定义。46 个数据调用和免费的 account 调用各自都有对应方法,而且每个响应都有类型定义。

安装

npm install storiesfly

获取密钥

  1. 使用 Telegram 登录 https://storiesfly.com/developers/dashboard。
  2. 在那里创建密钥。新账户会获得 100 次免费请求,因此你可以在付费前试用所有调用。

请将密钥保存在你的服务器上。任何持有密钥的人都可以消耗你的余额。

快速开始

获取账户当前发布的快拍:

import { StoriesFly } from "storiesfly";

const client = new StoriesFly({ apiKey: process.env.STORIESFLY_API_KEY! });

const { user, stories } = await client.user.stories({ username: "instagram" });

console.log(`${stories.length} stories up from account ${user.id}`);
for (const story of stories) {
  console.log(story.media_type, story.taken_at_iso, story.media_url);
}

须知:

  • 账户通过 { username } 或 { id } 标识,不能同时使用两者。帖子通过 { url }、{ code } 或 { id } 标识。类型定义会强制执行此规则。
  • ID 是字符串。Instagram 的 ID 超过 2^53,使用 JSON 数字会导致数值被舍入。
  • 字段名采用 snake_case,与 API 返回的格式一致。响应中没有的值为 null,不会是 0 或 ""。
  • 响应中的媒体链接是经过签名的 Instagram CDN 链接。它们会在几天内过期,因此请尽快下载所需内容。

获取帖子及其图片和视频链接:

const post = await client.post.get({ url: "https://www.instagram.com/p/DcyLOLIEdy7/" });

console.log(post.caption, post.likes);
for (const item of post.media) {
  console.log(item.type, item.video_url ?? item.image_url); // one item per slide of a carousel
}

获取无水印的 TikTok 视频和 TikTok 账户的关注者:

const video = await client.tiktok.video({ url: "https://www.tiktok.com/@khaby.lame/video/7697307919943060767" });
console.log(video.caption, video.views, video.video_url); // video_url has no watermark

const profile = await client.tiktok.user.profile({ username: "khaby.lame" });
console.log(profile.followers);

for await (const page of client.paginate(client.tiktok.user.followers, { username: "khaby.lame" }, { maxPages: 2 })) {
  for (const follower of page.users) console.log(follower.username);
}
选项
new StoriesFly({
  apiKey: "...",       // required, sent as X-Api-Key
  baseUrl: "...",      // default https://storiesfly.com/api/v1
  fetch: myFetch,      // default: the global fetch
  timeoutMs: 60_000,   // per attempt; 0 turns the timeout off
  maxRetries: 2,       // for rate_limited answers; 0 turns retries off
});

每个调用还接受一个最后位置参数,其中包含 signal(一个 AbortSignal)、timeoutMs、maxRetries 和 withMeta。

分页

返回列表的调用会返回一页数据,其中包含 next_cursor 和 has_more。client.paginate 会为你获取后续列表页。它是一个异步迭代器:调用方法、返回页面,然后使用上一页的 next_cursor 再次调用,直到 has_more 为 false:

for await (const page of client.paginate(client.user.followers, { username: "instagram" }, { maxPages: 4 })) {
  for (const follower of page.users) console.log(follower.username);
}
  • 每一页都是一次调用,并按一次请求计费。大型账户会有很多页,因此除非你打算读取整个列表,否则请设置 maxPages。
  • paginate 接受方法本身(client.user.followers)、其参数和选项:maxPages、signal 和 withMeta。在参数中传入 cursor,即可从已有页面开始遍历。
  • 只有接受 cursor 的方法才能分页,编译器会拒绝其他方法。方法表中的 Paged 列会标明哪些方法支持分页;导出的 ENDPOINTS 中每个端点也都有一个 paged 标志。
  • 手动分页时,将 next_cursor 作为 cursor 传回,并保持其他参数不变。游标是不透明的。若传入的游标并非由 API 返回,则会得到 bad_request。
  • 每页大小遵循 Instagram 的设定,并因端点而异。规范为三个方法固定了大小:user.posts 每页最多返回 9 个项目,user.followers 和 user.following 每页最多返回 25 个项目。方法表中的 Paged 列会在规范给出页大小的地方显示该值。

TikTok

TikTok 调用位于 client.tiktok 下。账号由 { username } 指定。

await client.tiktok.video({ url });                          // one video or photo post, short links too
await client.tiktok.user.profile({ username });              // followers, following, likes, video count
await client.tiktok.user.videos({ username });               // newest first, paged
await client.tiktok.user.stories({ username });              // stories up now
await client.tiktok.user.followers({ username });            // paged
await client.tiktok.user.following({ username });            // paged
await client.tiktok.user.reposts({ username });              // paged
  • videos、followers、following 和 reposts 接受 cursor,并返回 next_cursor,因此可以使用 client.paginate 对它们进行分页。每页大小由 TikTok 决定,且因端点而异。
  • 隐藏粉丝或关注列表的账号会返回一个带有 hidden: true 的空页面。
  • 数字在不精确时为 null。文件链接是临时的:请立即保存文件。
  • 在 tiktok.user.videos 的后续页面中,video_url 为 null。要获取单个视频的文件,请调用 tiktok.video,或使用其 url 调用 download。

下载

client.download({ url }) 接受 Instagram 帖子、Reel 或 IGTV 的链接,或 TikTok 视频或图片帖子的链接(也支持短链接),并返回文件链接:视频(TikTok 视频不带水印)、轮播帖或图片帖中的所有图片、封面,以及 TikTok 视频的配乐。它只返回文件;数字请使用 post.get 或 tiktok.video 获取。费用按每次调用固定收取:Instagram 链接每 1,000 次收费 $0.50,TikTok 链接每 1,000 次收费 $0.20。

const { platform, media } = await client.download({ url: "https://www.instagram.com/reel/DdY3MUJCfby/" });
for (const file of media) console.log(file.type, file.url);

文件链接是临时的,请立即下载。client.account() 也会通过 download_price_usd 显示下载价格。

在 ChatGPT 和 Claude 中使用(MCP)

AI 助手也可以通过 https://storiesfly.com/mcp 获取相同的数据,无需编写代码。详情:https://storiesfly.com/developers/mcp。

  • 在 Claude Code 中:claude mcp add --transport http storiesfly https://storiesfly.com/mcp
  • ChatGPT 和 Claude 连接到同一地址,并使用 Telegram 登录。

调用费用:响应元数据

调用会解析为已解析的响应正文。要同时查看计费标头,请将 { withMeta: true } 作为最后一个参数传入,调用将解析为 { data, meta }:

const { data, meta } = await client.user.profile({ username: "instagram" }, { withMeta: true });

console.log(data.followers);
console.log(meta.unitsCharged, meta.balanceRemaining, meta.freeUnitsRemaining);
meta 字段标头含义
statusHTTP 状态。
requestIdX-Request-Id调用的 ID。联系支持团队时请提供此 ID。
unitsChargedX-Units-Charged此次调用扣除的单位数。免费或已退款时为 0。
balanceRemainingX-Balance-Remaining调用后的余额,以美元计,精确到小数点后四位。该值是字符串,不会因浮点数运算而被舍入。
freeUnitsRemainingX-Free-Units-Remaining剩余免费单位数。
rateLimitLimitX-RateLimit-Limit账号每秒可发送的请求数。
rateLimitRemainingX-RateLimit-Remaining当前秒内剩余的请求数。

响应中未包含的标头值为 null。元数据按调用返回,不会保存在客户端上(没有 lastResponse),因此同时运行的调用不会覆盖彼此的数值。使用 paginate 时,{ withMeta: true } 会为每一页返回 { data, meta }。

错误及计费说明

每次未返回数据的调用都会抛出 StoriesFlyError。请检查 code,而非 message:

import { StoriesFly, StoriesFlyError } from "storiesfly";

try {
  await client.user.stories({ username: "some_private_account" });
} catch (err) {
  if (!(err instanceof StoriesFlyError)) throw err;

  console.log(err.status);       // HTTP status; 0 when no answer came
  console.log(err.code);         // "private_account"
  console.log(err.requestId);    // quote it to support
  console.log(err.retryAfterMs); // from Retry-After, when the API sent one
  console.log(err.meta?.unitsCharged); // what this failed call was charged
}

其他字段:fields(当 code 为 bad_request 时,包含被拒绝参数的名称)、linkUrl(当 code 为 telegram_required 时,包含用于将账户关联到 Telegram 的链接)、url(调用的 URL;其中不含密钥)和 body(解析后的错误响应体)。

答案会计费:200、not_found 和 private_account。参数错误、速率限制和余额不足均不收费;我方故障会退款。err.meta.unitsCharged 和 X-Units-Charged 会说明一次调用扣除了多少单位。

状态code是否计费说明
200是数据。
404not_found是未找到与此请求对应的内容。
403private_account是调用已到达一个私密账户。
400bad_request否缺少参数或参数无效。fields 会指出具体参数。
401unauthorized否缺少密钥或密钥错误。
402credits_exhausted否积分已用完。请充值。
403telegram_required否密钥对应的账户尚未关联 Telegram。linkUrl 中包含关联链接。
404unknown_endpoint否不存在此端点。
429rate_limited否每秒请求过多。
500internal_error已退款我方故障。
503upstream_unavailable已退款数据暂时不可用。请稍后重试。

客户端还会自行添加三个错误代码。当未收到响应时,status 为 0:timeout(在 timeoutMs 内未收到响应)、network_error(fetch 失败;错误中包含 cause)和 invalid_response(响应不符合文档规定的格式,例如代理返回的错误页面;会保留 status 和响应体)。

重试
  • 429 最多重试 maxRetries 次(默认值为 2)。客户端会等待 API 返回的 Retry-After 指定的时间;如果 API 未提供该值,则等待半秒,并在之后逐渐延长等待时间。若 Retry-After 超过 30 秒,则不会等待:会立即抛出错误,并设置 retryAfterMs。
  • 402 永不重试:再次调用也不会改变结果。
  • 其他错误、超时和网络错误均不会重试。500 或 503 会退款,因此你可以自行重试。

定价

预付费,每 1,000 次请求 $1.50 起。详见 https://storiesfly.com/developers/pricing。

一个单位对应一次请求。每次调用扣除 1 个单位,包括列表的一页。解析分享链接扣除 2 个单位,account 不扣费。download 按每次调用的固定价格收费(见下载),且只要你有可用单位,就会使用 1 个免费单位。免费单位会优先于余额使用。每个账户的每秒请求数均有限制。

方法

每个方法都是一次 API v1 调用。此表由 OpenAPI 规范(openapi.json)生成,并由测试验证。

调用端点单位数分页返回内容
client.user.profile()GET /user/profile1个人资料,包含认证徽章、简介、链接和计数
client.user.about()GET /user/about1国家、加入月份和曾用用户名
client.user.posts()GET /user/posts1是,最多 9 页帖子及其点赞数、评论数、浏览量、分享数、收藏数和转发数
client.user.reels()GET /user/reels1是Reels,包含说明文字、视频和播放次数
client.user.tagged()GET /user/tagged1是账号被标记的帖子
client.user.pinned()GET /user/pinned1置顶在个人资料顶部的帖子
client.user.stories()GET /user/stories1当前有效的快拍,以及每段视频的时长
client.user.highlights()GET /user/highlights1是精选集封面和标题
client.user.followers()GET /user/followers1是,最多 25 页关注者,逐页显示
client.user.following()GET /user/following1是,最多 25 页已关注的账号,逐页显示
client.user.followersSearch()GET /user/followers/search1在关注者中查找某人
client.user.followingSearch()GET /user/following/search1在已关注的账号中查找某人
client.user.reposts()GET /user/reposts1是该账号转发的帖子和 Reels
client.user.suggested()GET /user/suggested1Instagram 推荐的相似账号
client.post.get()GET /post1单条帖子:媒体链接、说明文字、浏览量、点赞数、评论数、分享数、收藏数和转发数
client.post.comments()GET /post/comments1是评论及其点赞数和回复数
client.post.commentReplies()GET /post/comment-replies1是对评论的回复
client.post.likers()GET /post/likers1点赞该帖子的账号
client.post.usertags()GET /post/usertags1帖子中标记的人
client.post.music()GET /post/music1Reels 使用的曲目
client.comment.likers()GET /comment/likers1是点赞评论的账号
client.story.get()GET /story1通过链接或 ID 获取单条快拍
client.highlight.get()GET /highlight1通过链接或 ID 获取精选集中的所有快拍
client.hashtag.get()GET /hashtag1话题标签及其帖子数
client.hashtag.posts()GET /hashtag/posts1是话题标签下的帖子:热门、最新或 Reels
client.location.get()GET /location1地点名称、地址、城市和坐标
client.location.posts()GET /location/posts1是在某地点标记的帖子:热门或最新
client.location.search()GET /location/search1按名称或某个坐标点附近查找地点
client.search.users()GET /search/users1是按名称或用户名查找账号
client.search.hashtags()GET /search/hashtags1是查找话题标签及其帖子数
client.search.places()GET /search/places1按名称查找地点
client.search.music()GET /search/music1是按曲名或艺术家查找曲目
client.search.reels()GET /search/reels1是按文本查找 Reels
client.search.top()GET /search/top1是与文本相关的热门帖子
client.track.get()GET /track1曲目标题、艺术家、时长和音频链接
client.resolve()GET /resolve1,分享链接为 2将帖子、Reels 或分享链接转换为数据
client.shop.storefront()GET /shop/storefront1账号商店:系列和首批商品
client.shop.products()GET /shop/products1是商店系列中的商品
client.tiktok.video()GET /tiktok/video1单条 TikTok 视频,无水印,包含浏览量、点赞数、评论数和分享数
client.tiktok.user.profile()GET /tiktok/user/profile1TikTok 个人资料,包含关注者数、关注数、点赞数和视频数
client.tiktok.user.videos()GET /tiktok/user/videos1是TikTok 账号的视频及其数据,逐页显示;文件链接位于第一页
client.tiktok.user.stories()GET /tiktok/user/stories1当前有效的 TikTok 快拍
client.tiktok.user.followers()GET /tiktok/user/followers1是TikTok 关注者,逐页显示;列表设为隐藏时会返回空页
client.tiktok.user.following()GET /tiktok/user/following1是TikTok 已关注的账号,逐页显示;列表设为隐藏时会返回空页
client.tiktok.user.reposts()GET /tiktok/user/reposts1是TikTok 账号转发的视频,逐页显示,并包含视频作者
client.download()GET /download1通过链接获取 Instagram 帖子或 Reels 的文件,或 TikTok 视频文件
client.account()GET /account0你的套餐、余额、免费单位数和使用情况
参数简述:
  • TikTok 调用(tiktok.user.*)接收 { username },tiktok.video 和 download 接收 { url }。分页的 TikTok 调用还接收 cursor。
  • 账号调用(user.*、shop.storefront)接收 { username } 或 { id }。带游标的调用还接收 cursor。user.followersSearch 和 user.followingSearch 还接收 q。
  • 帖子调用(post.*)接收 { url }、{ code }(链接中 /p/ 或 /reel/ 后面的部分)或 { id }。post.comments 接收 cursor。post.commentReplies 还接收 comment_id。
  • story.get 和 highlight.get 接收 { url } 或 { id }。
  • hashtag.posts 接收 name、sort(top、recent 或 reels;翻页时保持一致)和 cursor。location.posts 接收 id、sort(top 或 recent)和 cursor。
  • location.search 接收 q,或 lat 和 lng。search.* 调用接收长度为 1 到 100 个字符的 q。
  • post.get 返回完整帖子:media(帖子图片和视频的链接,轮播中的每张幻灯片对应一个条目)、标题、所有者、时间和各项数据。其结构与 user.posts、user.reels、hashtag.posts 及其他帖子列表中的条目相同;对于帖子链接,resolve 也会返回该内容。

文档

从 0.x 迁移

1.0 是针对 API v1 的重写版本。旧方法已移除,基础 URL 已更改,旧版套餐和每日配额在 v1 中也不复存在。

0.x1.0
getStories(username)user.stories({ username })。它会返回 { user, stories }。个人资料和精选动态需要分别调用(user.profile、user.highlights),且每次调用都会扣费。
getProfile(username)user.profile({ username })。它还会提供 id、bio、verified 和 external_url。
getHighlights(id)highlight.get({ id }),会返回精选动态中的所有快拍。user.highlights 会列出账号的精选动态。
getMedia(url)post.get({ url })。它会返回完整帖子:media 包含图片和视频链接(image_url、video_url,轮播中的每张图片各占一项),以及说明文字、所有者、时间和各项计数。
download(url)1.1 中的 download({ url }) 会返回帖子、短视频或 TikTok 视频的文件链接。post.get 也会提供媒体链接。
getTrackerEvents、listTrackedAccounts、addTrackedAccount、removeTrackedAccount、checkShadowban、getOutboundEngagement不属于 API v1,因此 1.0 中不提供。

其他变更:

  • baseUrl 现在默认设为 https://storiesfly.com/api/v1。bearerToken 选项已移除:v1 只接受通过 X-Api-Key 传入的密钥,不接受其他方式。
  • 方法按资源分组:client.user.profile()、client.post.get()、client.search.users()。每个方法都接收一个参数对象。
  • 响应使用 API 自身的 snake_case 名称;缺失的值以 null 表示:fullName 现在是 full_name,profilePicUrl 是 profile_pic_url,isPrivate 是 is_private,takenAt 是 taken_at。
  • StoriesFlyError 包含 code、requestId 和 retryAfterMs。0.x 中的 rateLimit、retryAfterSec、requiresUpgrade、isRateLimited 和 method 字段已移除。请将 err.code 与 rate_limited、credits_exhausted 等值进行比较。现在遇到 429 时会自动重试。
  • 旧版套餐(DEV、Starter、Growth、Scale 和 Tracker 套餐)、每日配额以及每分钟 60 次请求的突发限制均已移除。v1 按请求计费,从预付余额中扣除;新账号可免费请求 100 次。请参阅定价。
  • 将密钥对应的账号关联到 Telegram 后,旧密钥即可用于 v1。在此之前,v1 会返回 telegram_required,且 err.linkUrl 中包含关联链接。
  • Tracker、影子封禁和对外互动分析端点仍可通过 HTTP 响应,但 1.0 不会封装这些端点。如需继续使用,请保留 storiesfly@0 或自行调用这些端点。0.x 调用的旧版 /api/stories、/api/profile、/api/highlights、/api/media 和 /api/download 端点,将继续为现有免费密钥提供服务,直至 2026-12-31。详情:https://storiesfly.com/developers/docs/legacy。

常见问题

需要登录 Instagram 或 TikTok 吗? 不需要。你只需提供 StoriesFly API 密钥,无需其他信息。无需管理 Cookie 或会话。

可以获取 TikTok 账号的粉丝列表吗? 可以。client.tiktok.user.followers({ username }) 会分页返回列表,client.paginate 可自动遍历各页。隐藏粉丝列表的账号会返回一个包含 hidden: true 的空页面。

可以下载无水印的 TikTok 视频吗? 可以。client.tiktok.video({ url }) 会返回无水印的 video_url,而 client.download({ url }) 会返回 Instagram 或 TikTok 链接对应的文件链接。

可以通过 ChatGPT 或 Claude 使用吗? 可以,通过 MCP 服务 https://storiesfly.com/mcp 使用。请参阅通过 ChatGPT 和 Claude 使用(MCP)。

如何计费? 按请求计费,从预付余额中扣除。新账号可免费请求 100 次,仅限一次。请参阅定价。

无关联关系

这是 StoriesFly API 的客户端。它只读取公开数据;对于私密账号,会返回 private_account。它不是 Instagram 或 Meta 的产品,也与其无关联或背书关系。

开发

npm install
npm test               # clean, build, compile the tests and run them
npm run openapi:check  # validate openapi.json and openapi.yaml, and check that they match
npm run readme:check   # check the method table above against the spec

要更新规范:将 openapi.json 替换为新文件,运行 npm run openapi:sync 和 npm run readme:sync,然后运行测试。

许可证

MIT。请参阅 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。