@ikenxuan/xhshow-ts
v1.1.0
Published
XHS API signature generator
Readme
xhshow-ts
小红书请求签名生成库的 TypeScript 实现,支持 GET/POST 请求的 x-s 和 x-s-common 签名。
本项目基于 Cloxl/xhshow 的 Python 实现移植而来,感谢原作者的无私奉献!
⚠️ 声明:本 Fork 代码由 AI 辅助生成,仅供学习研究使用,不保证与上游仓库行为完全一致。
致谢
特别感谢 Cloxl 开源的 xhshow 项目,本项目的核心算法逻辑均来源于此。
系统要求
- Node.js 16+
- TypeScript 5.0+(可选,用于开发)
安装
npm install @ikenxuan/xhshow-ts或使用其他包管理器:
# yarn
yarn add @ikenxuan/xhshow-ts
# pnpm
pnpm add @ikenxuan/xhshow-ts快速开始
ESM(推荐)
import { Xhshow } from '@ikenxuan/xhshow-ts'
const client = new Xhshow()
// GET 请求签名
const getSignature = client.signXsGet(
'/api/sns/web/v1/user_posted',
'your_a1_cookie_value',
'xhs-pc-web',
{ num: '30', cursor: '', user_id: '123' }
)
// POST 请求签名
const postSignature = client.signXsPost(
'/api/sns/web/v1/login',
'your_a1_cookie_value',
'xhs-pc-web',
{ username: 'test', password: '123456' }
)
// x-s-common 签名
const xsCommon = client.signXsc({
a1: 'your_a1_cookie_value',
web_session: 'your_web_session'
})
// 一次性生成所有请求头
const headers = client.signHeadersGet(
'/api/sns/web/v1/user_posted',
{ a1: 'your_a1_cookie_value', web_session: '...' },
'xhs-pc-web',
{ num: '30' }
)
// headers 包含: x-s, x-s-common, x-t, x-b3-traceid, x-xray-traceid, x-mns, xy-directionXYW 签名格式(数据接口绕过 HTTP 406)
自 2026 年 3 月起,数据获取类接口(如 user_posted、user/otherinfo 等)会以
HTTP 406 拒绝传统的 XYS_ 格式签名,需改用基于 AES-128-CBC 的 XYW_ 格式。通过
signFormat: 'xyw' 启用:
// 直接生成 XYW_ 签名
const xyw = client.signXyw(
'GET',
'/api/sns/web/v1/user_posted',
'your_a1_cookie_value',
'xhs-pc-web',
{ num: '30', cursor: '' }
)
// 或在请求头中通过 signFormat 启用(第 7 个参数)
const headers = client.signHeadersGet(
'/api/sns/web/v1/user_posted',
{ a1: 'your_a1_cookie_value', web_session: '...' },
'xhs-pc-web',
{ num: '30' },
undefined, // timestamp
undefined, // session
'xyw' // signFormat: 'xys'(默认)| 'xyw'
)
// 此时 headers['x-s'] 以 XYW_ 开头x-rap-param(feed / 搜索 / 发布类接口)
feed、搜索、笔记发布等接口需要额外的 x-rap-param 请求头,通过 xRap: true 启用:
const headers = client.signHeadersPost(
'/api/sns/web/v1/feed',
{ a1: 'your_a1_cookie_value', web_session: '...' },
'xhs-pc-web',
{ source_note_id: '...' },
undefined, // timestamp
undefined, // session
'xys', // signFormat
'你的_user_id', // userId(用于 xy-direction 分片,可选)
true // xRap:生成 x-rap-param
)
// headers 额外包含 x-rap-param生成 Cookie 与辅助参数
// 生成 a1 与 web_id
const a1 = Xhshow.generateA1() // 52 字符
const webId = Xhshow.generateWebId(a1) // 32 字符 hex
// 搜索接口参数
const searchId = client.getSearchId() // base36
const requestId = client.getSearchRequestId() // "{random}-{timestamp_ms}"使用会话管理(推荐)
会话管理器可以模拟真实用户在同一页面中的连续操作,生成更真实的签名,提高长期稳定性:
import { Xhshow, SessionManager } from '@ikenxuan/xhshow-ts'
const client = new Xhshow()
const session = new SessionManager()
// 使用会话管理器进行多次请求
const headers1 = client.signHeadersGet(
'/api/sns/web/v1/user_posted',
{ a1: 'your_a1_cookie_value', web_session: '...' },
'xhs-pc-web',
{ num: '30' },
undefined,
session // 传入会话管理器
)
// 第二次请求,会话状态会自动更新
const headers2 = client.signHeadersGet(
'/api/sns/web/v1/user_posted',
{ a1: 'your_a1_cookie_value', web_session: '...' },
'xhs-pc-web',
{ num: '30', cursor: 'next_page' },
undefined,
session // 使用同一个会话管理器
)
// 会话管理器的工作原理:
// - 无 Session:每次请求生成随机参数,可能被识别为机器人
// - 有 Session:维护固定的页面加载时间戳和单调递增的计数器,模拟真实用户行为CommonJS
const { Xhshow } = require('@ikenxuan/xhshow-ts')
const client = new Xhshow()
const getSignature = client.signXsGet(
'/api/sns/web/v1/user_posted',
'your_a1_cookie_value',
'xhs-pc-web',
{ num: '30', cursor: '', user_id: '123' }
)API 参考
签名方法
| 方法 | 说明 |
|------|------|
| signXs(method, uri, a1Value, xsecAppid?, payload?, timestamp?, session?) | 通用签名(XYS_ 格式) |
| signXsGet(uri, a1Value, xsecAppid?, params?, timestamp?, session?) | GET 请求签名 |
| signXsPost(uri, a1Value, xsecAppid?, payload?, timestamp?, session?) | POST 请求签名 |
| signXyw(method, uri, a1Value, xsecAppid?, payload?, timestamp?) | XYW_ 格式签名(AES-128-CBC,绕过数据接口 406) |
| signXsc(cookieDict) | 生成 x-s-common 签名 |
请求头生成
| 方法 | 说明 |
|------|------|
| signHeaders(method, uri, cookies, xsecAppid?, params?, payload?, timestamp?, session?, signFormat?, userId?, xRap?) | 生成完整请求头 |
| signHeadersGet(uri, cookies, xsecAppid?, params?, timestamp?, session?, signFormat?, userId?, xRap?) | GET 请求头 |
| signHeadersPost(uri, cookies, xsecAppid?, payload?, timestamp?, session?, signFormat?, userId?, xRap?) | POST 请求头 |
参数说明:
signFormat:'xys'(默认)或'xyw'(数据接口需用,绕过 HTTP 406)userId:可选,提供后按 user_id 计算xy-direction分片值,否则随机xRap:是否生成x-rap-param请求头(feed、搜索、发布类接口需要)
生成的请求头包含:x-s、x-s-common、x-t、x-b3-traceid、x-xray-traceid、x-mns、xy-direction(xRap: true 时额外包含 x-rap-param)。
会话管理
| 类/方法 | 说明 |
|------|------|
| SessionManager | 会话管理器类 |
| session.getCurrentState(content) | 获取当前签名状态 |
| session.updateState() | 更新会话状态 |
工具方法
| 方法 | 说明 |
|------|------|
| decodeXs(xsSignature) | 解密 XYS 签名 |
| decodeX3(x3Signature) | 解密 x3 签名 |
| buildUrl(baseUrl, params?) | 构建带参数的 URL |
| buildJsonBody(payload) | 构建 JSON body |
| getB3TraceId() | 生成 x-b3-traceid |
| getXrayTraceId(timestamp?, seq?) | 生成 x-xray-traceid |
| getXT(timestamp?) | 生成 x-t 时间戳 |
| getSearchId() | 生成搜索接口 search_id(base36) |
| getSearchRequestId() | 生成搜索接口 request_id |
| Xhshow.generateA1() | 生成 a1 Cookie 值(52 字符,静态方法) |
| Xhshow.generateWebId(a1) | 由 a1 生成 web_id(32 字符 hex,静态方法) |
类型定义
type Method = 'GET' | 'POST'
type Payload = Record<string, any> | null
type SignFormat = 'xys' | 'xyw'
interface SignState {
pageLoadTimestamp: number
sequenceValue: number
windowPropsLength: number
uriLength: number
}
class SessionManager {
constructor(config?: CryptoConfig)
updateState(): void
getCurrentState(content: string): SignState
}
interface Xhshow {
signXs(method: Method, uri: string, a1Value: string, xsecAppid?: string, payload?: Payload, timestamp?: number, session?: SessionManager): string
signXsGet(uri: string, a1Value: string, xsecAppid?: string, params?: Payload, timestamp?: number, session?: SessionManager): string
signXsPost(uri: string, a1Value: string, xsecAppid?: string, payload?: Payload, timestamp?: number, session?: SessionManager): string
signXyw(method: Method, uri: string, a1Value: string, xsecAppid?: string, payload?: Payload, timestamp?: number, session?: SessionManager): string
signXsc(cookieDict: Record<string, any> | string): string
signHeaders(method: Method, uri: string, cookies: Record<string, any> | string, xsecAppid?: string, params?: Payload, payload?: Payload, timestamp?: number, session?: SessionManager, signFormat?: SignFormat, userId?: string | null, xRap?: boolean): Record<string, string>
signHeadersGet(uri: string, cookies: Record<string, any> | string, xsecAppid?: string, params?: Payload, timestamp?: number, session?: SessionManager, signFormat?: SignFormat, userId?: string | null, xRap?: boolean): Record<string, string>
signHeadersPost(uri: string, cookies: Record<string, any> | string, xsecAppid?: string, payload?: Payload, timestamp?: number, session?: SessionManager, signFormat?: SignFormat, userId?: string | null, xRap?: boolean): Record<string, string>
decodeXs(xsSignature: string): Record<string, any>
decodeX3(x3Signature: string): Uint8Array
buildUrl(baseUrl: string, params?: Record<string, any> | null): string
buildJsonBody(payload: Record<string, any>): string
getB3TraceId(): string
getXrayTraceId(timestamp?: number, seq?: number): string
getXT(timestamp?: number): number
getSearchId(): string
getSearchRequestId(): string
}
// 静态方法
Xhshow.generateA1(): string
Xhshow.generateWebId(a1: string): string开发
# 克隆项目
git clone https://github.com/ikenxuan/xhshow-ts
cd xhshow-ts
# 安装依赖
pnpm install
# 开发模式
pnpm dev
# 构建
pnpm build项目结构
src/
├── client.ts # 主客户端类
├── session.ts # 会话管理器
├── core/ # 核心加密处理
├── config/ # 配置
├── data/ # 指纹数据
├── generators/ # 指纹生成器
├── utils/ # 工具函数
└── validators.ts # 参数验证相关项目
- Cloxl/xhshow - 原版 Python 实现(本项目上游)
