用 Node.js / TypeScript 获取 A 股数据:npm install ashareapi
官方 Node SDK 已发布:`npm install ashareapi`。5 个免费端点无需 Key,零运行时依赖(用 Node 原生 `fetch`),自带 TypeScript 类型;返回对象数组,代码格式随便写,出错时 5 类异常分别告诉你该做什么。
安装
npm install ashareapi
# 或:pnpm add ashareapi / yarn add ashareapi- 要求 Node.js ≥ 18(依赖原生 `fetch`;建议 20 LTS 或更高)
- 零运行时依赖 —— 安装体积约 12 KB,没有供应链风险
- ESM 与 CommonJS 都支持(`import` / `require` 都行),并自带 `.d.ts` 类型
- ⚠️ 只在服务端使用(Node 脚本 / Next.js 服务端 / 后端服务)—— 浏览器里会暴露你的 API Key,本包刻意不提供浏览器构建
30 秒上手(免费端点不需要 Key)
5 个免费数据端点:`quote` / `kline` / `hot` / `marketOverview` / `changedist` —— 无需注册、无需 Key,装上就能调。
import { AShareAPI } from "ashareapi";
const cli = new AShareAPI(); // 免费端点无需 Key
const bars = await cli.quote("sh600667"); // 实时行情
console.log(bars[0]); // { date, open, last, high, low, volume, amount, turnover }
console.log(await cli.kline("600667.SH", "day", 5)); // 代码格式随便写(自动归一化)
console.log(await cli.hot(10)); // 热搜榜
console.log(await cli.changedist()); // 涨跌分布(市场广度)CommonJS 写法(`require`)
const { AShareAPI } = require("ashareapi");
(async () => {
const cli = new AShareAPI();
const rows = await cli.kline("sh600667", "day", 3);
console.log(rows[0].date, rows[0].last);
})();- `package.json` 的 `exports` 同时声明了 `import` 与 `require` 入口 —— 不需要为了用这个包改模块系统
方法名两种写法都认(从 Python 版迁过来不用改)
多词方法提供 snake_case 别名(与 Python SDK 方法名一致)—— 两种写法是同一个方法,从 Python 版或文档里直接抄过来即可。
| camelCase(JS 惯例) | snake_case(与 Python SDK 一致) | 端点 |
|---|---|---|
| `marketOverview(type)` | `market_overview(type)` | `/v1/market-overview` |
| `marginTrade(code, date)` | `margin_trade(code, date)` | `/v1/margin-trade` |
| `blockTrade(code, date)` | `block_trade(code, date)` | `/v1/block-trade` |
| `sectorValuation(code)` | `sector_valuation(code)` | `/v1/sector-valuation` |
| `industryChain(mode, topic, code)` | `industry_chain(mode, topic, code)` | `/v1/industry-chain` |
代码格式:三种写法都认
| 你写的 | 会被归一化为 | 说明 |
|---|---|---|
| `sh600667` | `sh600667` | 原生格式(市场前缀 + 代码) |
| `600667.SH` | `sh600667` | 常见后缀写法,自动转换 |
| `600667` | `sh600667` | 纯 6 位按首位推断:5/6 → 沪、0/3 → 深、4/8 → 北 |
付费端点:带 Key 调用
import { AShareAPI } from "ashareapi";
const cli = new AShareAPI({ apiKey: "ct-你的Key" }); // 或设环境变量 ASHARE_API_KEY
const rows = await cli.screen("", "low_pe", 10, "ROETTM"); // expr, preset, limit, orderby
console.table(rows);
console.log(await cli.fund("sh600667")); // 资金流 + 龙虎榜 + 大宗 + 两融
console.log(await cli.finance("sh600667")); // 三大报表
console.log(await cli.lhb("institution")); // 龙虎榜机构榜- Key 从 [定价页](https://ashareapi.com/pricing/) 获取(¥9.9 起)
- 32 个端点 = 32 个方法,命名与端点一一对应(`/v1/margin-trade` → `marginTrade()`)
- 完整清单见 [端点文档](https://ashareapi.com/endpoints/)
返回形态:对象数组(不是 DataFrame)
需要完整信封(含 `elapsed_ms` / `source` / `tier`)时用 `new AShareAPI({ raw: true })` —— 方法会返回原始响应对象而不是数组。
const rows = await cli.kline("sh600667", "day", 3);
// [
// { date: '2026-09-23', open: '20.10', last: '20.59', high: '20.72', low: '19.45', ... },
// { date: '2026-09-22', open: '20.63', last: '19.87', ... },
// { date: '2026-09-21', ... }
// ]| Python SDK | Node.js SDK | |
|---|---|---|
| 默认返回 | `pandas.DataFrame`(无 pandas → `list[dict]`) | `Row[]`(对象数组) —— 但 `finance` 是 `Row[][]`(表列表)、`shareholder`/`calendar` 是 `{ tables, data }`(多段) |
| 取值 | `df["last"]` / `df.head()` | `rows[0].last` / `rows.map(...)` |
| 同步性 | 同步调用 | 全部返回 Promise(`await`) |
错误处理:5 类异常各说各的
import { AShareAPI, AuthError, RateLimitError,
UpstreamError, EmptyResultError } from "ashareapi";
const cli = new AShareAPI();
try {
const rows = await cli.fund("sh600667");
} catch (e) {
if (e instanceof AuthError) console.log(e.message); // 401 → 这是付费端点,去拿 Key
else if (e instanceof RateLimitError) console.log(e.message); // 429 → 降频 / 解一次 PoW 提额 / 升级档位
else if (e instanceof UpstreamError) console.log(e.message); // 上游取数失败(已自动换源、不扣次数)→ 重试一次
else if (e instanceof EmptyResultError) console.log(e.message); // 当前无数据(如当天无大宗交易)→ 不计费,换条件
else throw e;
}- SDK 内置重试:`429` / `5xx` / 网络错误 → 指数退避 3 次(0.5s / 1.5s / 4s)
- `ok:false`(上游取数失败)不重试 —— 后端已经自动换源,重试无意义
| 异常 | 什么时候抛 | 你该做什么 |
|---|---|---|
| `AuthError` | 401 / 缺 Key 调了付费端点 | 去拿 Key,或改用免费端点 |
| `RateLimitError` | 429 超出档位频率 | 降频;或解 PoW 挑战提额;或升级 |
| `UpstreamError` | 上游取数失败(已自动换源、不扣次数) | 重试一次通常就好 |
| `EmptyResultError` | 请求成功但当前无数据(如当天无大宗交易) | 换条件或稍后再试,不计费 |
| `APIError` | 其他(网络 / 5xx 重试耗尽) | 看异常信息 |
在 Next.js 服务端用(示范"只在服务端")
import { NextResponse } from "next/server";
import { AShareAPI, AuthError, RateLimitError } from "ashareapi";
const cli = new AShareAPI(); // 读 process.env.ASHARE_API_KEY
export async function GET(request: Request) {
const code = new URL(request.url).searchParams.get("code") ?? "sh600667";
try {
const [quote, technical] = await Promise.all([cli.quote(code), cli.technical(code)]);
return NextResponse.json({ ok: true, code, quote: quote[0], technical: technical[0] });
} catch (e) {
if (e instanceof AuthError) return NextResponse.json({ ok: false, error: "缺少或无效的 Key" }, { status: 401 });
if (e instanceof RateLimitError) return NextResponse.json({ ok: false, error: "触发限流" }, { status: 429 });
throw e;
}
}- 把 Key 放在服务端环境变量里(`.env.local`)—— 不要放进 `NEXT_PUBLIC_*`,那会打进浏览器包
- `Promise.all` 并发取多个端点,比串行快得多
常见错误与边界
- `401` 调付费端点 → 没带 Key:免费端点只有 5 个,其余需要 Key
- `429` → 匿名限额较低(5 次/分);解一次 PoW(`cli.challenge()`)可提到 60 次/分,或升级档位
- `EmptyResultError` 不是失败:是"当前确实没有这类数据"(例如当天没有大宗交易)—— 不计费,别当异常处理
- 忘了 `await`:所有方法返回 Promise,直接 `console.log(cli.quote(...))` 会打印一个 Promise 对象而不是数据
- 数据日期:休市日不会变成"今天",看返回里的 `date` 字段判断数据属于哪个交易日
- 单位:`volume` 是手(×100 = 股)· `amount` 是元 · 比率字段是百分数(`20` = 20%)
- 分钟级 K 线:当前只提供日/周/月,分钟级不在范围内(明写,别猜)
常见问题
SDK 本身免费(MIT 开源),5 个免费端点(行情 / K线 / 热搜 / 市场总览 / 涨跌分布)无需 Key、无需注册即可调用。其余 25 个端点需要 API Key(¥9.9 起),SDK 不额外收费。
不需要。零运行时依赖 —— 只用 Node 原生 `fetch`(所以要求 Node ≥ 18)。安装包约 12 KB,没有传递依赖,也不会有供应链风险。
技术上我们的 API 允许跨域,但不建议也不支持:浏览器里调用意味着 API Key 会出现在前端代码/网络请求里,等于公开。请在服务端(Node / Next.js 服务端路由 / 云函数)调用,再把结果给前端。本包刻意不提供浏览器构建。
是。自带 `.d.ts`:编辑器里 `cli.` 会补全 32 个方法与参数;常用行类型(`Row` / `QuoteRow` / `Envelope`)已导出,可以 `import type { Row } from "ashareapi"`。
同一后端、同 32 个方法、同 5 类异常、同重试策略。差异只有语言惯例:JS 版方法名以 camelCase 为主(同时提供 snake_case 别名)、全部返回 Promise、返回对象数组而不是 DataFrame。
`npm install ashareapi@latest`。最新版本与全部变更见 [更新日志](/changelog)。
最后更新: 2026-09-23
代码与返回形态取自 SDK 的真实运行结果(2026-09-23 从打包产物安装验证:ESM 与 CJS 两种形态各跑通真实调用,quote 返回 30 行、hot 3 行、marketOverview("valuation") 8 行,付费端点无 Key 正确抛 AuthError)。