> Source: https://ashareapi.com/docs/guides/nodejs-ashare-quotes/  ·  Markdown version for LLMs / AI agents

教程

# 用 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 版或文档里直接抄过来即可。
 |
| | 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`

 `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 → 北

 `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', ... }
// ]
```
 |
| | | 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`）

 默认返回
 `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 重试耗尽） | 看异常信息

 `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）。

 接着看

-
[端点文档（32 个端点的字段与示例）](/endpoints)

-
[Python 版 SDK（pip install ashareapi）](/docs/guides/python-sdk)

-
[用 Python 获取实时行情：3 种方法对比](/docs/guides/python-ashare-quotes)

-
[错误码表](/docs/errors)

 [← 全部教程](/docs/guides)
