跳转至

Twitter API 详细规格

本文档详细说明 Twitter 私信、图片上传和用户采集 API 的规格和使用要求。

目录


私信 API

API 端点

  • URL: https://x.com/i/api/1.1/dm/new2.json
  • 方法: POST
  • Content-Type: application/json

必需的 HTTP 请求头

Host: x.com
Authorization: Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA
X-Csrf-Token: {从 cookies 提取 ct0}
X-Client-Uuid: {随机生成的 UUID v4}
X-Client-Transaction-Id: {Base64 编码的随机字符串}
Cookie: {完整的 cookies 字符串}
Content-Type: application/json
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36...

URL 查询参数

必需的查询参数:

ext=mediaColor,altText,mediaStats,highlightedLabel,voiceInfo,birdwatchPivot,superFollowMetadata,unmentionInfo,editControl,article
include_ext_alt_text=true
include_ext_limited_action_results=true
include_reply_count=1
tweet_mode=extended
include_ext_views=true
include_groups=true
include_inbox_timelines=true
include_ext_media_color=true
supports_reactions=true
supports_edit=true

请求体格式

纯文本私信

{
    "conversation_id": "{user_id}-{current_user_id}",
    "recipient_ids": false,
    "request_id": "{UUID v4}",
    "text": "{message}",
    "cards_platform": "Web-12",
    "include_cards": 1,
    "include_quote_count": true,
    "dm_users": true
}

带图片私信

{
    "conversation_id": "{user_id}-{current_user_id}",
    "recipient_ids": false,
    "request_id": "{UUID v4}",
    "text": "{message}",
    "cards_platform": "Web-12",
    "include_cards": 1,
    "include_quote_count": true,
    "dm_users": true,
    "attachment": {
        "type": "media",
        "media": {
            "id": "{media_id_string from upload}"
        }
    }
}

注意media_id 来自图片上传接口返回的 media_id_string 字段。

成功响应

HTTP 200,JSON 包含 entries 字段表示成功。

认证信息提取

从 cookies 字符串中提取认证信息:

  1. CSRF Token (ct0): 正则匹配 ct0=([^;]+)
  2. Auth Token: 正则匹配 auth_token=([^;]+)
  3. User ID: 从 twid 提取,支持三种格式:
  4. twid=u%3D{user_id} (URL 编码)
  5. twid="u={user_id}" (带引号)
  6. twid=u={user_id} (不带引号)

图片上传 API

三阶段上传流程

Twitter 图片上传采用三阶段流程:INIT → APPEND → FINALIZE

每个阶段都是独立的 HTTP 请求,必须按顺序执行。


INIT 阶段 - 初始化上传

API 端点: - URL: https://upload.x.com/i/media/upload.json?command=INIT&total_bytes={size}&media_type=image/jpeg&media_category={category} - 方法: POST - 状态码: 200 (成功)

请求头:

Host: upload.x.com
Authorization: Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA
X-Csrf-Token: {从 cookies 提取 ct0}
X-Twitter-Auth-Type: OAuth2Session
Accept: */*
Origin: https://x.com
Referer: https://x.com/
Accept-Language: zh-CN,zh;q=0.9
Priority: u=1, i
Cookie: {完整的 cookies 字符串}

响应格式:

{
    "media_id": 1234567890,
    "media_id_string": "1234567890",
    "expires_after_secs": 86400
}


APPEND 阶段 - 上传图片数据

API 端点: - URL: https://upload.x.com/i/media/upload.json?command=APPEND&media_id={media_id}&segment_index=0 - 方法: POST - Content-Type: multipart/form-data - 状态码: 204 (成功)

Multipart 字段: - field name: media - filename: blob - content-type: application/octet-stream - 数据: 图片二进制内容

请求头: 与 INIT 阶段相同


FINALIZE 阶段 - 完成上传

API 端点: - URL: https://upload.x.com/i/media/upload.json?command=FINALIZE&media_id={media_id}&original_md5={md5} - 方法: POST - 状态码: 201 (成功)

请求头: 与 INIT 阶段相同

重试策略: - 500 错误时自动重试,最多 2 次 - 重试等待时间: 第 1 次 2 秒,第 2 次 4 秒


支持的媒体类别

pub enum MediaCategory {
    BannerImage,  // "banner_image" - 横幅图片
    TweetImage,   // "tweet_image" - 推文图片
    DmImage,      // "dm_image" - 私信图片
}

选择建议: - 发送私信图片 → 使用 DmImage - 发布推文图片 → 使用 TweetImage - 更新个人资料横幅 → 使用 BannerImage


错误处理

常见错误码

HTTP 状态码 含义 处理方式
401 认证失败 检查 cookies 是否有效
403 无权限 检查账号状态
429 请求过于频繁 实施速率限制
500 服务器错误 自动重试(仅限 FINALIZE 阶段)

重试建议

  • INIT 阶段:失败后立即停止,不重试
  • APPEND 阶段:失败后立即停止,不重试
  • FINALIZE 阶段:500 错误自动重试 2 次,其他错误不重试

安全性约束

  1. 不在日志中输出完整的 cookies 或 token
  2. 验证消息长度 ≤ 10000 字符
  3. 验证 user_id 非空
  4. 使用 HTTPS 确保传输安全
  5. 定期刷新 cookies 避免过期

性能考虑

  1. 批量发送默认无并发限制 - 可根据账号限制自行调整
  2. 请求超时设置为 30 秒
  3. 使用连接池复用 HTTP 连接
  4. 图片上传前计算 MD5,避免重复上传

用户采集 API

获取粉丝列表

获取指定用户的粉丝列表,支持分页获取。

API 端点: - URL: https://x.com/i/api/graphql/{query_id}/Followers - 方法: GET - 认证: 需要 Bearer Token 和 CSRF Token

URL 参数: - variables: JSON 编码的查询参数 - userId: 目标用户的 REST ID(必需) - count: 每页返回的数量(默认 20,最大 200) - cursor: 分页游标(可选,获取下一页时使用) - includePromotedContent: 是否包含推广内容(布尔值) - features: JSON 编码的特性标志

必需的 HTTP 请求头:

Host: x.com
Authorization: Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA
X-Csrf-Token: {从 cookies 提取 ct0}
Cookie: {完整的 cookies 字符串}
Content-Type: application/json

成功响应: - HTTP 200,包含 data.user.result.timeline 对象 - 响应头包含 x-rate-limit-* 限流信息

分页逻辑: - 首次请求不传 cursor 参数 - 响应中的 next_cursor 用于获取下一页 - 当 next_cursor"0" 或不存在时,表示没有更多数据

异常情况: - 私密账号:返回特定错误标记,is_abnormal = true - 用户不存在:HTTP 404 - 认证失败:HTTP 401


获取关注列表

获取指定用户的关注列表,支持分页获取。

API 端点: - URL: https://x.com/i/api/graphql/{query_id}/Following - 方法: GET - 认证: 需要 Bearer Token 和 CSRF Token

URL 参数: 与获取粉丝列表相同,使用相同的 variablesfeatures 结构。

必需的 HTTP 请求头: 与获取粉丝列表相同。

成功响应: - HTTP 200,包含 data.user.result.timeline 对象 - 响应结构与粉丝列表相同

分页逻辑: 与获取粉丝列表相同。


关注

关注指定用户。

API 端点: - URL: https://x.com/i/api/1.1/friendships/create.json - 方法: POST - Content-Type: application/x-www-form-urlencoded

必需的 HTTP 请求头:

Host: x.com
Authorization: Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA
X-Csrf-Token: {从 cookies 提取 ct0}
Cookie: {完整的 cookies 字符串}
Content-Type: application/x-www-form-urlencoded

请求体格式:

include_profile_interstitial_type=1&include_blocking=1&include_blocked_by=1&include_followed_by=1&include_want_retweets=1&include_mute_edge=1&include_can_dm=1&include_can_media_tag=1&include_ext_is_blue_verified=1&include_ext_verified_type=1&include_ext_profile_image_shape=1&skip_status=1&user_id={target_user_id}

成功响应: - HTTP 200,返回目标用户完整信息(JSON 对象,包含 id_str 字段)

错误响应: - 400: 参数错误(如 user_id 无效) - 401: 认证失败 - 403: 无权限(如被对方拉黑)


取消关注

取消关注指定用户。

API 端点: - URL: https://x.com/i/api/1.1/friendships/destroy.json - 方法: POST - Content-Type: application/x-www-form-urlencoded

必需的 HTTP 请求头:

Host: x.com
Authorization: Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA
X-Csrf-Token: {从 cookies 提取 ct0}
Cookie: {完整的 cookies 字符串}
Content-Type: application/x-www-form-urlencoded

请求体格式:

user_id={target_user_id}

成功响应: - HTTP 200,表示成功取消关注

错误响应: - 400: 参数错误(如 user_id 无效) - 401: 认证失败 - 403: 无权限(如尝试取消关注不存在的关系)


API 限流信息

Twitter API 响应头包含限流信息:

x-rate-limit-limit: 500        # 时间窗口内的总请求限制
x-rate-limit-remaining: 498    # 剩余可用请求数
x-rate-limit-reset: 1705401234 # 限制重置的 Unix 时间戳

限流策略: - 获取粉丝/关注列表:每 15 分钟 500 次请求 - 关注/取消关注:每 15 分钟 1000 次请求 - 超出限制后返回 HTTP 429(Too Many Requests)

最佳实践: 1. 检查 x-rate-limit-remaining,接近 0 时暂停请求 2. 使用 x-rate-limit-reset 计算等待时间 3. 实施指数退避策略处理 429 错误


数据类型

FollowUser - 粉丝/关注用户信息

pub struct FollowUser {
    pub rest_id: String,              // 用户 REST ID
    pub name: String,                 // 用户显示名称
    pub screen_name: String,          // 用户名(@username)
    pub location: Option<String>,     // 地理位置
    pub can_dm: bool,                 // 是否可以发私信
    pub followers_count: u64,         // 粉丝数
    pub following_count: u64,         // 关注数
    pub media_count: u64,             // 媒体数
    pub protected: bool,              // 是否为私密账号
    pub profile_image_url: Option<String>,  // 头像 URL
    pub description: Option<String>,  // 个人简介
}

ApiLimit - API 限流信息

pub struct ApiLimit {
    pub limit: Option<u32>,       // 时间窗口内的总请求限制
    pub remaining: Option<u32>,   // 剩余可用请求数
    pub reset: Option<u64>,       // 限制重置的 Unix 时间戳
}

FollowListResult - 粉丝/关注列表响应

pub struct FollowListResult {
    pub success: bool,                  // 请求是否成功
    pub users: Vec<FollowUser>,         // 用户列表
    pub next_cursor: Option<String>,    // 下一页游标
    pub is_abnormal: bool,              // 是否为异常状态(如私密账号)
    pub api_limit: Option<ApiLimit>,    // API 限流信息
    pub error_msg: String,              // 错误消息
    pub http_status: u16,               // HTTP 状态码
}

辅助方法:

impl FollowListResult {
    /// 检查是否有更多数据可以获取
    pub fn has_more(&self) -> bool {
        self.next_cursor.is_some()
            && self.next_cursor.as_deref() != Some("0")
    }
}

FollowResult - 关注结果

pub struct FollowResult {
    pub success: bool,      // 是否成功
    pub user_id: String,    // 目标用户 ID
    pub error_msg: String,  // 错误消息
    pub http_status: u16,   // HTTP 状态码
}

UnfollowResult - 取消关注结果

pub struct UnfollowResult {
    pub success: bool,      // 是否成功
    pub user_id: String,    // 目标用户 ID
    pub error_msg: String,  // 错误消息
    pub http_status: u16,   // HTTP 状态码
}

相关文档