Guide

Realtime quotes and daily close with /v1/quote

Getting "what is this stock worth right now" takes one GET: `/v1/quote` is free, needs no Key and no signup, and returns the last 30 trading days of OHLC plus volume/value/turnover. `data[0]` is the most recent day.

1. The 5 lines you actually need

`/v1/quote` is a free endpoint (no Key, no signup). The only required param is `code`. It returns a unified envelope `{ ok, endpoint, tier, elapsed_ms, source, data }`, where `data` is a day array, newest first (30 by default) and `data[0]` is the latest trading day.

Python: latest price for one stock
import requests

r = requests.get(
    "https://api.ashareapi.com/v1/quote",
    params={"code": "sh600667"},   # market prefix required
    timeout=10,
)
body = r.json()
if not body.get("ok"):
    raise RuntimeError(body)        # failures return ok=false + error

bar = body["data"][0]               # most recent trading day
print(bar["date"], bar["last"], bar["turnover"])
  • `code` needs a market prefix: `sh600667` (Shanghai) / `sz000001` (Shenzhen) / `bj920002` (Beijing) / `hk00700` (HK) / `usAAPL` (US). A bare 6-digit code returns an empty result.
  • `data` is an array (30 by default, `data[0]` newest), not a single object.

2. Fields and units (the part people get wrong)

date
Trading date
YYYY-MM-DD — the data date, not query date
open / high / low
Open / high / low
numeric strings
last
Close (previous session)
not the intraday live price — see section 3
volume
Volume
lots (×100 = shares)
amount
Turnover value
CNY (not thousands/millions)
turnover
Turnover rate
percent (4.92 = 4.92%)

Unit reminders: `volume` is in lots, `amount` in CNY, `turnover` is a percent — the three classic newbie traps. The same fields in `/v1/kline` are identically named and valued, so you can mix them safely.

3. Realtime or close? — data-date semantics

`last` is the close for that trading day, and `date` tells you which day. When you call during market hours, `data[0].date` is today and `last` is the latest price up to the request moment (usable as the current price); after the close it is that day's close. So check whether `date` equals today to tell which one you are looking at.

This is by design: one endpoint serves both "realtime snapshot" and "historical close", disambiguated by `date`. For a live display, check `date` first so you never show yesterday's close as the current price.

  • During hours: `date` = today → `last` is the current price
  • After close / holiday: `date` = last trading day → `last` is the close
  • How to tell: `bar["date"] == today` (or use the trading calendar)

4. Multiple stocks (concurrency + rate limits)

`/v1/quote` takes one `code` per call (not comma-separated). For many stocks, use a thread pool — and mind the anonymous limit: 5 requests/minute.

Python: fetch several stocks concurrently
from concurrent.futures import ThreadPoolExecutor
import requests

def q(code):
    r = requests.get("https://api.ashareapi.com/v1/quote",
                     params={"code": code}, timeout=10)
    j = r.json()
    if not j.get("ok"):        # 429 / 401 also land here
        return code, j.get("error")
    return code, j["data"][0]["last"]

codes = ["sh600667", "sz000001", "sh600519"]
with ThreadPoolExecutor(max_workers=3) as ex:
    for code, price in ex.map(q, codes):
        print(code, price)
  • Anonymous: 5 requests/minute — beyond that returns 429. For more, solve one PoW challenge to reach 60/min (see section 5), or apply for a Key.
  • Keep concurrency modest: 3-5 workers is plenty; more just hits the limit sooner.

5. Hitting 429? There is a free speed-up

Anonymous calls have a per-minute quota; over it you get `429 Too Many Requests`. `/v1/challenge` is the free upgrade path: fetch a challenge (PoW), solve it, and send it back in `X-PoW` to raise the anonymous quota from 5/min to 60/min.

Python: challenge → solve → call
import requests

# 1) fetch a challenge (difficulty can only be raised, not lowered)
ch = requests.get("https://api.ashareapi.com/v1/challenge", timeout=10).json()
# ch = {"challenge": ..., "difficulty": 18, ...}

# 2) solve the PoW: find a nonce so sha256(challenge+nonce) has 'difficulty' leading zero bits
#    (details in /docs/errors; for most cases applying for a Key is simpler)

# 3) call with the X-PoW header for the higher quota
# r = requests.get("https://api.ashareapi.com/v1/quote",
#                  params={"code": "sh600667"},
#                  headers={"X-PoW": solved}, timeout=10)
  • Usually enough: 5/min covers a single-machine display or review flow; batch jobs are better off with a Key (see /pricing).
  • Do not retry 429 in a tight loop — back off a few seconds or slow down.

6. quote vs kline — which one?

Use for
Quote snapshot + last 30 days
Historical bars (custom period/count)
Params
code
code / period / count
Default
last 30 trading days
last 30 bars (count up to 1212)
Adjustment
raw prices
forward-adjusted (no gap)
Fields
date/open/high/low/last/volume/amount/turnover
same names, same values

One line: use `quote` for "current / last few days", and `kline` (forward-adjusted) for full history, indicators or backtests. The fields line up between the two.

FAQ

Why do I get a close price instead of a realtime price?

Check `data[0].date`: when it equals today, `last` is the live price up to now (usable as the current price); when it is a past date, it is that session close. The endpoint intentionally serves both snapshot and close use cases, disambiguated by date — so you never mistake yesterday close for the current price.

Is volume in shares or lots? Is amount in CNY or thousands?

volume is in lots (1 lot = 100 shares), amount is in CNY, and turnover is a percent (4.92 means 4.92%). These are the three most common unit mistakes — worth a code comment.

Can I fetch several stocks in one call?

No — one code per call. Use a thread pool for batches and mind the anonymous limit (5/min); for higher rates apply for a Key or solve the PoW challenge to reach 60/min.

Do I need the market prefix? Can I pass just 600667?

A prefix is required (sh600667 / sz000001 / bj920002 / hk00700 / usAAPL). A bare 6-digit code returns an empty result (not an error) — the most common newbie pitfall.

Is this endpoint free?

Yes — no signup, no Key, anonymous calls are fine (5 requests/minute). Higher quotas are on /pricing.

Last updated: 2026-10-01

Data from live ashareapi /v1/quote responses (measured 2026-10-01: 600667 returned 30 rows, data[0] date=2026-09-30 last=17.29 high=18.28 volume=1029096 amount=1804480000 turnover=4.92); fields and units verified against live responses.