Tutorial

A-Share Data in Python with the Official SDK

The official SDK is live: `pip install ashareapi`. Five endpoints need no key, results come back as pandas DataFrames (plain `list[dict]` without pandas), symbol formats are forgiving, and 5 exception types tell you exactly what to do.

Install

bash
pip install ashareapi            # base: returns list[dict]
pip install "ashareapi[pandas]"  # add DataFrame support (recommended)
  • Requires Python 3.9+; the only hard dependency is `requests` — pandas is optional
  • Without pandas every method returns `list[dict]` — nothing breaks

Quickstart in 30 seconds (free endpoints need no key)

Five free endpoints: `quote` / `kline` / `hot` / `market_overview` / `changedist` — no signup, no key.

Python (runnable)
from ashareapi import AShareAPI

cli = AShareAPI()                       # free endpoints need no key
df = cli.quote("sh600667")              # realtime quote -> DataFrame
print(df[["date", "last", "turnover"]])

print(cli.kline("600667.SH", count=5))  # symbol format is forgiving
print(cli.hot(limit=10))                # hot list
print(cli.changedist())                 # advance/decline breadth

Symbol formats: all three work

`cli.quote("600667.SH")` and `cli.quote("sh600667")` are the same call — code migrated from another data source usually works unchanged.

`sh600667`
`sh600667`
Native form (market prefix + code)
`600667.SH`
`sh600667`
Common suffix style, converted for you
`600667`
`sh600667`
Bare 6 digits: 5/6 -> Shanghai, 0/3 -> Shenzhen, 4/8 -> Beijing

Paid endpoints: pass a key

Python
from ashareapi import AShareAPI

cli = AShareAPI("ct-your-key")           # or set ASHARE_API_KEY
df = cli.screen(preset="low_pe", orderby="ROETTM", limit=10)
print(df.head())

print(cli.fund("sh600667"))              # fund flow + boards + block trades + margin
print(cli.finance("sh600667"))           # three financial statements
print(cli.lhb("institution"))            # top-trader institution board
  • Keys come from the [pricing page](https://ashareapi.com/pricing/) (from CNY 9.9)
  • 32 endpoints = 32 methods, named 1:1 with the HTTP paths (`/v1/margin-trade` -> `margin_trade()`)
  • Full list: [endpoint reference](https://ashareapi.com/endpoints/)

Return types: DataFrame or list?

The SDK converts the object array into a DataFrame (it prefers `structured`, falling back to `data`); table lists (`finance`) and sectioned structures (`shareholder` / `calendar`) are returned as-is (not force-wrapped, which would degrade into a 3x1 table); use `raw=True` for the full envelope.

pandas installed (`ashareapi[pandas]`)
`pandas.DataFrame`
`df.head()` / `df[["date","last"]]` / plotting
No pandas
`list[dict]`
Iterate yourself — the same code does not crash

Error handling: 5 exception types, each actionable

Python
from ashareapi import (AShareAPI, AuthError, RateLimitError,
                       UpstreamError, EmptyResultError)

cli = AShareAPI()
try:
    df = cli.fund("sh600667")
except AuthError as e:          # 401 -> paid endpoint, get a key
    print(e)
except RateLimitError as e:     # 429 -> slow down / solve one PoW / upgrade
    print(e)
except UpstreamError as e:      # upstream fetch failed (failover done, not counted) -> retry once
    print(e)
except EmptyResultError as e:   # no data right now (e.g. no block trades today) -> free, change filters
    print(e)
`AuthError`
401 / paid endpoint without a key
Get a key, or use a free endpoint
`RateLimitError`
429 over your tier limit
Slow down; solve a PoW challenge; or upgrade
`UpstreamError`
Upstream fetch failed (failover done, not counted)
One retry usually works
`EmptyResultError`
Request succeeded but there is no such data now
Change filters or retry later, not billed
`APIError`
Anything else (network / retries exhausted)
Read the message

SDK vs raw HTTP vs Tushare / AkShare

Time to first call
pip install and go
Wrap retries/exceptions yourself
Signup + credit thresholds
Install and go
Return type
DataFrame (list without pandas)
Parse JSON yourself
DataFrame
DataFrame
Free trial
5 endpoints, no key
Also keyless
Signup required (credits)
Free
Errors
5 exception types ("no data" != failure)
Your own checks
Return values
Your own checks
Maintenance
Ours (multi-source failover)
You fix when upstream changes
Vendor maintained
Frequent upstream churn

Gotchas and boundaries

  • `401` on a paid endpoint -> missing key: only 5 endpoints are free
  • `429` -> anonymous limits are low; solve one PoW (`cli.challenge()`) for 60 req/min, or upgrade
  • `EmptyResultError` is not a failure: it means "there is genuinely no such data right now" (e.g. no block trades today) — not billed, do not treat it as an outage
  • Data dates: holidays do not become "today"; read the `date` field to see which session the data belongs to
  • Units: `volume` is in lots (x100 = shares), `amount` in CNY, ratio fields are percentages (`20` = 20%)
  • Minute-level K-line is out of scope (daily / weekly / monthly only) — stated plainly

FAQ

Is the SDK free?

The SDK itself is free (MIT), and 5 endpoints (quote / K-line / hot list / market overview / breadth) need no key and no signup. The other 25 endpoints need an API key (from CNY 9.9); the SDK adds no extra charge.

Do I have to install pandas?

No. pandas is an optional dependency: with it you get `DataFrame` (recommended), without it you get `list[dict]` and nothing breaks. Install both via `pip install "ashareapi[pandas]"`.

Why does 600667.SH work too?

The SDK normalizes symbols: `sh600667`, `600667.SH` and `600667` are all accepted and converted to `sh600667` before the request. Bare 6-digit codes infer the market from the first digit (5/6 -> Shanghai, 0/3 -> Shenzhen, 4/8 -> Beijing).

What is the difference between EmptyResultError and UpstreamError?

EmptyResultError = there is no such data right now (e.g. no block trades today): the request succeeded and is not billed — change filters or retry later. UpstreamError = the upstream fetch failed (we already failed over, also not counted) — one retry usually works. Splitting them tells you instantly whether to change filters or retry.

How do I upgrade the SDK?

`pip install -U ashareapi`. For the latest version and the full change history, see the [changelog](/en/changelog).

Last updated: 2026-09-23

Code and return shapes come from real runs of the SDK (installed from PyPI and verified 2026-09-23: quote 30 rows / hot 3 rows / RateLimitError raised correctly under anonymous limits). Tushare and AkShare descriptions follow their official docs; their interfaces and thresholds are theirs to change.