> Source: https://ashareapi.com/en/docs/guides/batch-fetch/  ·  Markdown version for LLMs / AI agents

Tutorial

# Batch Fetching: 5,000 Requests Down to 23
 Scanning all 5,000+ A-shares one by one costs 5,000+ requests. With batch endpoints at 250 symbols per call it takes 23. Table, code and quota rules below.

## When to use batch endpoints
 If your loop calls the same endpoint over and over for a list of symbols, switch to the batch version. Typical cases: full-market screening, refreshing a watchlist on a schedule, preparing data before a multi-symbol backtest.
 Batch endpoints are not just faster — they bill **per returned symbol**, and **failed symbols are not billed**, so they are also cheaper and easier to handle errors with.
 |
| | Approach | Requests for 5,000+ symbols | Measured time

| | Loop `/v1/snapshot` | 5,000+ requests | ~30 min (rate-limited)

| | `/v1/snapshot-batch` (250 per call) | **23 requests** | ~10 seconds

 Loop `/v1/snapshot`
 5,000+ requests
 ~30 min (rate-limited)

 `/v1/snapshot-batch` (250 per call)
 **23 requests**
 ~10 seconds

## The nine batch endpoints: caps and daily quotas
 Per-call caps and daily quotas differ per endpoint because the upstream sources differ. Quotas count **calls**, and reset at 00:00 Beijing time.
 |
| | Endpoint | Max per call | Pro ¥99 daily | Institutional ¥199 daily

| | `/v1/quote-batch` quotes | 200 / 1000 | 200 | 1000

| | `/v1/kline-batch` K-lines | 200 / 1000 | 200 | 1000

| | `/v1/snapshot-batch` full snapshot | 200 / 250 | 200 | 1000

| | `/v1/fund-batch` money flow | 200 / 1000 | 200 | 1000

| | `/v1/technical-batch` indicators | 500 / 1000 | 200 | 500

| | `/v1/chip-batch` chips | 200 / 300 | 200 | 1000

| | `/v1/shareholder-batch` shareholders | 200 / 300 | 200 | 1000

| | `/v1/profile-batch` company profile | 100 / 150 | 100 | 300

| | `/v1/finance-batch` financials | 10 / 20 | 100 | 500

 `/v1/quote-batch` quotes
 200 / 1000
 200
 1000

 `/v1/kline-batch` K-lines
 200 / 1000
 200
 1000

 `/v1/snapshot-batch` full snapshot
 200 / 250
 200
 1000

 `/v1/fund-batch` money flow
 200 / 1000
 200
 1000

 `/v1/technical-batch` indicators
 500 / 1000
 200
 500

 `/v1/chip-batch` chips
 200 / 300
 200
 1000

 `/v1/shareholder-batch` shareholders
 200 / 300
 200
 1000

 `/v1/profile-batch` company profile
 100 / 150
 100
 300

 `/v1/finance-batch` financials
 10 / 20
 100
 500

 The "max per call" column shows **Pro / Institutional**. `finance-batch` allows only 10–20 symbols per call, so a full-market pass needs 250+ calls — still within its 500/day quota, but plan for it.

## Runnable example: 50 full snapshots in one call
 The response marks every symbol individually: `{code, ok, data}` or `{code, ok:false, error}`. One bad code never breaks the batch — just filter on `ok`.

 Python (replace KEY)
```
import requests

KEY = "ct-your-key"
codes = ["sh600519", "sz000001", "sz300750"] # up to 250 (Institutional)

r = requests.get(
 "https://api.ashareapi.com/v1/snapshot-batch",
 params={"codes": ",".join(codes), "key": KEY},
 timeout=20,
).json()

print(r["requested"], r["returned"], r["failed"]) # 3 3 0
for item in r["data"]:
 if item["ok"]:
 d = item["data"]
 print(item["code"], d["name"], d["price"], d["pe"])
 else:
 print(item["code"], "failed:", item.get("error"))
```

## Full-market scan in 23 requests
 Use the endpoint cap from the table above as your chunk size. A smaller chunk is not an error — it just wastes call quota, which is the most common way people burn through a daily quota.

 Python (chunked)
```
def chunks(seq, n):
 for i in range(0, len(seq), n):
 yield seq[i:i + n]

all_rows, failed = [], []
for i, batch in enumerate(chunks(all_codes, 250), 1): # 5,000+ => about 23 batches
 r = requests.get(
 "https://api.ashareapi.com/v1/snapshot-batch",
 params={"codes": ",".join(batch), "key": KEY},
 timeout=30,
 ).json()
 all_rows += [x for x in r["data"] if x["ok"]]
 failed += [x["code"] for x in r["data"] if not x["ok"]]
 print(f"batch {i}, {len(all_rows)} symbols so far")
```

## How quota is counted

 Check today's remaining calls
```
u = requests.get("https://api.ashareapi.com/v1/usage",
 params={"key": KEY}).json()

print(u["heavy_quotas"]["snapshot-batch"])
# {'used': 0, 'limit': 1000, 'left': 1000}
```

-
 **Billed per returned symbol**: request 250, get 248 back, billed 248

-
 **Failed symbols are refunded automatically** — no action needed

-
 **The daily quota counts calls**, not symbols

-
 **Resets at 00:00 Beijing time**; when exhausted the API returns `429` with `retry_after_s`

-
 **Check remaining quota anytime**: `GET /v1/usage?key=...`, field `heavy_quotas`

 Check quota before starting a batch job — cheaper than hitting 429 halfway through.

## Three pitfalls

-
 **A-shares only**: `snapshot-batch` / `profile-batch` accept `sh` / `sz` / `bj` only; HK/US symbols return `ok:false`

-
 **Prefixes are required**: `sh600519`, not `600519`

-
 **Exceeding the cap rejects the whole call**: 300 symbols to `snapshot-batch` (cap 250) is an error, not a silent truncation

## FAQ
 Is a 250-symbol call slow?
 `snapshot-batch` does 300 symbols in 0.40s (10x faster than `/v1/quote-batch`); `profile-batch` is the slowest at ~10s for 150. Use a 30s timeout, or 60s for `finance-batch`.

 What happens when the daily quota runs out?
 It resets at 00:00 Beijing time. To do more today, use another batch endpoint (each has its own quota) or upgrade the tier.

 Is the data identical to the single-symbol endpoints?
 Yes — same fields. `snapshot-batch` returns exactly the `/v1/snapshot` payload (35+ fields), just packed into an array. Units are unchanged (volume in lots, amount in 10k CNY, market cap in 100M CNY).

 Why did 250 symbols return only 200?
 Fifty of them were malformed or outside the A-share universe. Check the `ok:false` entries and their `error` field — failed symbols are not billed.

 Last updated: 2026-11-02
 Caps and daily quotas read from backend config (verified 2026-11-02: full HEAVY_DAILY and _batch_cap tables). Timings measured: snapshot-batch 300 symbols 0.40s, profile-batch 150 symbols 10.02s.

 Related

-
[Endpoint reference (nine batch endpoints)](/en/endpoints)

-
[Getting A-share quotes in Python: 3 approaches](/en/docs/guides/python-ashare-quotes)

-
[Factor screening across the whole market](/en/docs/guides/factor-screening)

-
[Error codes & rate limits](/en/docs/errors)

 [← All tutorials](/en/docs/guides)
