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 |
/v1/snapshot/v1/snapshot-batch (250 per call)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/v1/kline-batch K-lines/v1/snapshot-batch full snapshot/v1/fund-batch money flow/v1/technical-batch indicators/v1/chip-batch chips/v1/shareholder-batch shareholders/v1/profile-batch company profile/v1/finance-batch financialsThe "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.
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.
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
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
429withretry_after_s - Check remaining quota anytime:
GET /v1/usage?key=..., fieldheavy_quotas
Check quota before starting a batch job — cheaper than hitting 429 halfway through.
Three pitfalls
- A-shares only:
snapshot-batch/profile-batchacceptsh/sz/bjonly; HK/US symbols returnok:false - Prefixes are required:
sh600519, not600519 - Exceeding the cap rejects the whole call: 300 symbols to
snapshot-batch(cap 250) is an error, not a silent truncation
FAQ
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.
It resets at 00:00 Beijing time. To do more today, use another batch endpoint (each has its own quota) or upgrade the tier.
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).
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.