# 抖音 用户内容 API (douyin.user_posts)

- Canonical page: https://everyinfra.com/douyin-api/user_posts
- Endpoint: POST https://api.everyinfra.com/api/v1/social with {"platform": "douyin", "action": "user_posts", "params": {...}}
- Price: $0.000556 per call ($0.56 per 1,000 requests); failed calls and empty results are not charged
- Returns: list, default 20, max 100 per call
- Pagination: pass next_page_token back as page_token for the next page, other params unchanged; one call per page, tokens last 24 hours
- Mode: sync; add "mode": "async" for slow tasks

抖音用户内容按 `user_id` 列出一个账号发布的视频，每条带文案、话题、时长、互动数据和发布时间。它回答「这个账号最近在发什么、哪类视频表现好」，常用于达人评估、竞品账号监测和内容规律分析。

`user_id` 要用账号的 secUid（通常以 MS4w 开头），可以从搜索结果的 `author_id` 或主页链接里取；昵称和短数字抖音号都不行。不带 `page_token` 时取最新一批，可以用 `since` 只要某天之后发布的视频；要翻完整个作品列表，从 `page_token` 传空字符串开始，逐页传回 `next_page_token`。比较表现时别看 `view_count`，抖音不公开播放量。单次默认 20 条、最多 100 条，最新优先。

## Health

- Live health (24h percent, hourly and daily trends): https://api.everyinfra.com/api/v1/social/availability?platform=douyin&action=user_posts

## Parameters

| name | type | required | default | description |
|---|---|---|---|---|
| user_id | not declared | yes | not declared | 抖音用户的 secUid（通常以 MS4w 开头），不是昵称或短数字抖音号。用于定位 profile / user_posts 的账号；可从搜索结果的 author_id 或抖音用户主页链接取得。 |
| page_token | not declared | no | not declared | 翻页令牌（user_posts / comments）。从第一页开始翻：传空字符串 page_token=""；之后把上一页响应里的 next_page_token 原样传回取下一页，其余参数保持不变。令牌 24 小时内有效，只能在同一账户、同一组参数下使用，过期或参数变了返回 422，从第一页重新开始即可；翻到底时响应里没有 next_page_token（pagination.has_more 为 false）。user_posts 每页算一次调用，每页最多 100 条、最新优先，翻页时不按 since 过滤（需要时间窗请按 posted_at 自行过滤）。comments 每页最多 50 条顶层评论，按条数分档计费：每 20 条算一次，一页按 50 条算 3 次（传更小的 limit 按 limit 算），一条都没返回的档不扣费。不带 page_token 是单次调用：user_posts 取最新一批（可用 since）；comments 只读头部评论（含回复，同样每 20 条算一次），默认 20 条，limit 再大最多也只有约 50-60 条，一般没有 next_page_token。 |
| since | not declared | no | not declared | 频道视频的最早发布日期，格式 YYYY-MM-DD；只用于 user_posts 列表，不是账号创建日期。 |
| limit | integer (1–100) | no | 20 | 这次调用最多返回的条数，整数，1–100；不传按默认值，实际返回可能少于这个数。超过上限会在扣费前返回 422。 |

## Response fields (items in `results`)

| field | meaning |
|---|---|
| next_page_token | 翻页令牌（search / user_posts / comments / comment_replies / billboard_video_hot / billboard_low_fan_explosion / billboard_high_completion / billboard_account_search / music_search / billboard_rise_list / billboard_topic_hot）：作为下一次请求的 page_token 原样传回取下一页（其余参数不变，24 小时内有效）；同一页每行的值相同，响应顶层也有同一个 next_page_token。没有该字段即到底。评论翻页逐页覆盖全部顶层评论。 |
| id | 该记录在原平台上的唯一标识。仅在同一平台内唯一，跨平台可能重复。 |
| url | 该记录在原平台上的可访问链接。 |
| text | 正文内容，已去除 HTML 标签，全文返回、不截断（个别平台的列表结果本身只有摘要，以该平台的字段说明为准）。 |
| media_type | 媒体类型。 |
| video_url | 视频播放地址（带签名、会过期，要留存请及时下载）；图文笔记或来源没给时为 null。 |
| like_count | 点赞数。null 表示该平台或该接口不公开此数据，不等于 0。 |
| comment_count | 评论数。null 表示不公开，不等于 0。 |
| share_count | 分享/转发数。null 表示不公开，不等于 0。 |
| collect_count | 收藏数。null 表示不公开，不等于 0。 |
| view_count | 此字段不是真实播放量。抖音不对外公开视频播放量，多数结果里没有这个字段，有时为 0；判断视频热度请用 like_count（点赞）、comment_count（评论）、share_count（分享）、collect_count（收藏）。 |
| author_name | 作者昵称（显示名）。 |
| author_id | 作者在原平台的唯一 ID。 |
| author_douyin_id | 作者抖音号。 |
| author_uid | 作者（评论里是评论者）的数字用户 ID；author_id 是 secUid，两者是同一个人的两种 ID。 |
| author_bio | 作者主页简介（search / user_posts / video 行上）。 |
| author_avatar_url | 作者头像链接：search / user_posts / video 行上是博主的，comments 行上是评论者的。 |
| author_follower_count | 作者粉丝数。null 表示不公开。 |
| cover_image_url | 封面图链接：search / user_posts 是作品封面，music_search / music_detail 是音乐封面，billboard_topic_hot 是话题配图。 |
| video_width | 视频画面宽度（像素）。 |
| video_height | 视频画面高度（像素）。 |
| duration_seconds | 时长，单位秒。非视频/音频内容为 null。 |
| region | 地区。 |
| hashtags | 正文里的话题标签数组，按出现顺序；没有时不出现这个字段。 |
| posted_at | 发布时间，ISO 8601 格式、UTC 时区（如 2026-08-07T12:34:56+00:00）。平台只给非标准字符串时原样透传，解析前建议做容错。null 表示平台未公开。 |
| platform | 数据来源平台标识，与请求里的 platform 一致（如 xiaohongshu、tiktok）。 |
| image_urls | 图片链接数组，按平台展示顺序；没有图片时不出现这个字段。 |
| duration_sec | 视频时长（秒）。 |
| hashtag_ids | 作品话题 ID 列表，与 hashtags 同序一一对应（search / user_posts / video）。 |
| search_rank | 在这次关键词搜索结果里的名次（从 1 开始）：product_search 行是商品，search 行是作品，hashtag_search 行是话题。 |
| author_is_verified | 作者是否认证（search / user_posts / video 行上）。 |
| author_following_count | 作者关注数（search / user_posts / video 行上）。 |
| author_like_count | 作者主页获赞总数（search / user_posts / video / transcript）。 |
| author_video_count | 作者作品总数（search / user_posts / video 行上）。 |
| author_ip_location | 作者 IP 属地（平台强制展示）。 |
| title | 标题。平台无标题概念时（如纯文本帖）为 null。 |
| music | 作品背景音乐：id、title（曲名）、author（演唱/作者）、is_original（是否原声）、duration_sec（秒）、cover_url、play_url（音频地址，可能会过期）；没有音乐信息时没有这个键。 |
| download_count | 作品下载数。 |
| forward_count | 作品转发数。 |
| is_pinned | 是否置顶（作品行：作者主页置顶作品；trending：榜单置顶词）。 |
| is_ad | 是否为广告作品。 |
| video_tags | 平台给作品打的内容分类标签（如「美食」「探店」）。 |
| video_resolution | 视频清晰度档位原文（如 720p）。 |
| animated_cover_url | 动态封面链接。 |
| city | 城市：作品行（search / user_posts / video）是作品发布城市，平台给的是拼音写法（如 Suzhou）；xingtu_creator_rankings 是达人所在城市。 |
| city_code | 作品发布城市的行政区划代码（如 320500）。 |
| location | 作品定位的地点（POI）：id、name、category（地点分类）、address、district、city、province、country、city_code、latitude、longitude、cover_url、popularity_text（如 327人想去）、view_count、post_count（该地点下的作品数）、collect_count、visitor_count；作品没带定位时没有这个键。 |
| text_language | 作品文案语言代码（如 zh；un 表示未识别）。 |
| video_bitrates | 各清晰度播放地址：[{quality（清晰度名）, bitrate（码率，bps）, fps, is_h265（是否 H.265 编码）, url}]；地址带签名、会过期（见 video_url_expires_at）。 |
| download_url | 作品视频的下载地址（带签名、会过期）。 |
| has_watermark | 平台对这条作品视频文件的水印标记（true 表示带水印）。 |
| video_url_expires_at | 播放与下载地址的失效时间（ISO 8601，UTC）；之后要重新取。 |
| permissions | 作者给作品设的权限：can_comment（可评论）、can_download（可下载）、can_duet（可合拍）、can_stitch（可拼接）、can_share（可分享）、can_repost（可转发）、can_save（可保存）；只含平台给了的项。 |
| author_gender | 作者性别（male / female / unknown，作者自己填的）。 |
| author_age | 作者年龄（作者公开了才有）。 |

## Example

```bash
curl -X POST 'https://api.everyinfra.com/api/v1/social' \
  -H "Authorization: Bearer $EVERYINFRA_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "platform": "douyin",
  "action": "user_posts",
  "params": {
    "user_id": "https://www.douyin.com/user/MS4wLjABAAAAk1tZ-L085zZf2yW_H5dnVFZWyk8Rt8v4RAvf9KhTyPoVdMDxTs7Q_rvgTJGWXezS"
  }
}'
```

```python
import os
import requests

response = requests.post(
    "https://api.everyinfra.com/api/v1/social",
    headers={"Authorization": f"Bearer {os.environ['EVERYINFRA_API_KEY']}"},
    json={
        "platform": "douyin",
        "action": "user_posts",
        "params": {
            "user_id": "https://www.douyin.com/user/MS4wLjABAAAAk1tZ-L085zZf2yW_H5dnVFZWyk8Rt8v4RAvf9KhTyPoVdMDxTs7Q_rvgTJGWXezS",
        },
    },
    timeout=120,
)
print(response.status_code)
print(response.json())
```

## Response example

Real response to the example request above, captured 2026-09-26T08:56:04Z. `results` and `count` are real with personal information (names, handles, avatars, profile links, contact details) removed; the list keeps the first 2 of 20. `id`, `billing` and `quota` differ on every call, so only their shape is shown.

```text
{
  "id": "req_…",
  "platform": "douyin",
  "action": "user_posts",
  "results": [
    {
      "id": "•••",
      "url": "https://www.douyin.com/video/7534316807973260587",
      "text": "10个实用技巧，告别说英语时忘词！ #英语学习视频 #英语学习分享 #英语听力磨耳朵 #零基础学英语口语",
      "media_type": "video",
      "like_count": 7310,
      "comment_count": 80,
      "share_count": 1378,
      "collect_count": 6115,
      "view_count": 0,
      "author_name": "•••",
      "author_id": "MS4wLjABAAAAk1tZ-L085zZf2yW_H5dnVFZWyk8Rt8v4RAvf9KhTyPoVdMDxTs7Q_rvgTJGWXezS",
      "author_douyin_id": "•••",
      "author_follower_count": 48341,
      "region": "河北",
      "posted_at": "2025-08-04T00:10:00+00:00",
      "platform": "douyin",
      "duration_sec": 244,
      "hashtags": [
        "英语学习视频",
        "英语学习分享",
        "英语听力磨耳朵"
      ]
    },
    {
      "id": "•••",
      "url": "https://www.douyin.com/video/7524662531407793447",
      "text": "英语磨耳朵：春节中国最重要的传统节日 #英语学习视频 #英语听力训练 #四六级翻译 #英语短文",
      "media_type": "video",
      "like_count": 602,
      "comment_count": 19,
      "share_count": 206,
      "collect_count": 474,
      "view_count": 0,
      "author_name": "•••",
      "author_id": "MS4wLjABAAAAk1tZ-L085zZf2yW_H5dnVFZWyk8Rt8v4RAvf9KhTyPoVdMDxTs7Q_rvgTJGWXezS",
      "author_douyin_id": "•••",
      "author_follower_count": 48341,
      "region": "河北",
      "posted_at": "2025-07-09T00:12:00+00:00",
      "platform": "douyin",
      "duration_sec": 40,
      "hashtags": [
        "英语学习视频",
        "英语听力训练",
        "四六级翻译"
      ]
    }
  ],
  "next_page_token": …,
  "pagination": { … },
  "count": 20,
  "billing": {
    "charged": …,
    "charged_usd": …,
    "balance_after_usd": …,
    …
  },
  "quota": { … }
}
```

## FAQ

### secUid 从哪里找？

打开账号的抖音主页，链接里 /user/ 后面以 MS4w 开头的那一长串就是 secUid；搜索结果和视频结果里的 `author_id` 也是它，可以直接传给 `user_id`。昵称和短数字抖音号定位不到账号。注意 `user_id` 要的是 secUid：同一个人的数字用户 ID 在 `author_uid`，抖音号在 `author_douyin_id`，两个都不能填进来。页面示例直接填的是完整的用户主页链接。拿到 secUid 后存下来，以后读这个账号都用它。

### 怎么翻完一个账号的全部作品？

第一次把 `page_token` 传空字符串，之后把每页响应里的 `next_page_token` 原样传回，其他参数不变；每页最多 100 条、最新优先，没有 `next_page_token` 就是到底，pagination.has_more 也会是 false。令牌 24 小时内有效；翻页时不按 `since` 过滤，需要时间窗请按 `posted_at` 自己筛。令牌绑定账户和参数组合，换了参数或过期会返回 422，从第一页重来即可。每页算一次调用，作品多的账号调用次数会累积。

### 怎么只拿新发布的视频？

不带 `page_token` 的单次调用可以传 `since`，格式 YYYY-MM-DD，只返回这天及之后发布的视频。定期跑任务时，把上一次拿到的最新发布日期作为下一次的 `since`，就能做增量同步。`since` 是视频的最早发布日期，不是账号创建日期。一次最多取 100 条，默认 20 条，用 `limit` 调整。`posted_at` 是 UTC 时间，平台未公开时为 null，同步时先单独处理这类行。每条还带 `author_follower_count`，可顺便记粉丝数。

## Also

- Capability catalog (no key): https://api.everyinfra.com/api/v1/social/catalog?platform=douyin
- OpenAPI: https://everyinfra.com/openapi.json · Agents guide: https://everyinfra.com/agents.md
