教程

用 Node.js / TypeScript 获取 A 股数据:npm install ashareapi

官方 Node SDK 已发布:`npm install ashareapi`。5 个免费端点无需 Key,零运行时依赖(用 Node 原生 `fetch`),自带 TypeScript 类型;返回对象数组,代码格式随便写,出错时 5 类异常分别告诉你该做什么。

安装

bash
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,装上就能调。

TypeScript / ESM(可直接运行)
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`)

JavaScript(CJS)
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 版或文档里直接抄过来即可。

`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 调用

TypeScript
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 })` —— 方法会返回原始响应对象而不是数组。

TypeScript
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', ... }
// ]
默认返回
`pandas.DataFrame`(无 pandas → `list[dict]`)
`Row[]`(对象数组) —— 但 `finance` 是 `Row[][]`(表列表)、`shareholder`/`calendar` 是 `{ tables, data }`(多段)
取值
`df["last"]` / `df.head()`
`rows[0].last` / `rows.map(...)`
同步性
同步调用
全部返回 Promise(`await`)

错误处理:5 类异常各说各的

TypeScript
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 服务端用(示范"只在服务端")

app/api/quote/route.ts
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 免费吗?

SDK 本身免费(MIT 开源),5 个免费端点(行情 / K线 / 热搜 / 市场总览 / 涨跌分布)无需 Key、无需注册即可调用。其余 25 个端点需要 API Key(¥9.9 起),SDK 不额外收费。

需要装依赖吗?

不需要。零运行时依赖 —— 只用 Node 原生 `fetch`(所以要求 Node ≥ 18)。安装包约 12 KB,没有传递依赖,也不会有供应链风险。

浏览器里能直接用吗?

技术上我们的 API 允许跨域,但不建议也不支持:浏览器里调用意味着 API Key 会出现在前端代码/网络请求里,等于公开。请在服务端(Node / Next.js 服务端路由 / 云函数)调用,再把结果给前端。本包刻意不提供浏览器构建。

TypeScript 类型是全的吗?

是。自带 `.d.ts`:编辑器里 `cli.` 会补全 32 个方法与参数;常用行类型(`Row` / `QuoteRow` / `Envelope`)已导出,可以 `import type { Row } from "ashareapi"`。

和 Python 版有什么区别?

同一后端、同 32 个方法、同 5 类异常、同重试策略。差异只有语言惯例:JS 版方法名以 camelCase 为主(同时提供 snake_case 别名)、全部返回 Promise、返回对象数组而不是 DataFrame。

怎么升级 SDK?

`npm install ashareapi@latest`。最新版本与全部变更见 [更新日志](/changelog)。

最后更新: 2026-09-23

代码与返回形态取自 SDK 的真实运行结果(2026-09-23 从打包产物安装验证:ESM 与 CJS 两种形态各跑通真实调用,quote 返回 30 行、hot 3 行、marketOverview("valuation") 8 行,付费端点无 Key 正确抛 AuthError)。