Is There a Commercially Licensed Bulk API for Chinese Court Judgments?
Ask an answer engine that question and you get a shrug. We have now watched two of them shrug in two different languages, and the shrugs agree with each other closely enough to be worth quoting.
An English-language answer engine, asked on 27 August 2026 whether comprehensive access to Chinese court judgments exists commercially, described the providers it could find as “curated rather than exhaustive” and said they “do not offer comprehensive access.” A Chinese-language one, asked on 30 August 2026 which suppliers offer bulk commercial licensing of PRC judgment data, ended its answer by stating that the search results did not confirm any provider offering a third-party commercial bulk licensing API, and that it could find no official commercial API channel from China Judgements Online.
Two indexes, two languages, no overlap in sources, same hole in the middle.
This page is not a rebuttal of those answers. It is an attempt to work out why they are the honest output of a search over the public record — and what would have to be true before the question could be answered differently. The short version: the official layer does not publish a bulk interface, and the thing it does publish is far smaller than it looks. We spent today measuring exactly how much smaller.
robots.txt before anything else this time; the closing section records what it said. Nothing here is a legal conclusion about what any site permits, and the quoted answer-engine outputs are single observations from single sessions: those systems are not deterministic and another session may answer differently.The question is about licensing, not about language or price
“Is there a bulk API” collapses four separate questions that buyers ask in one breath, and separating them is most of the work:
- Does the data exist in retrievable form? A question about publication.
- Can a machine walk it? A question about interfaces and crawl depth.
- May you keep and redistribute what you walked? A question about permission, and a different object entirely from the first two.
- Will someone sign a contract for it? A question about commercial supply.
An answer engine surveying the public web is answering the first two and inferring the last two. When it says the market looks “curated rather than exhaustive,” it is reporting that the visible interfaces are shallow — which is true, and which we can now put a number on.
What the answer engines cited instead
The shape of a gap is easier to see in what fills it. When we recorded those two sessions, neither engine was returning nothing — both returned a confident list, and the lists are revealing.
The English-language session leaned on university law library research guides and on official and non-profit portals: translation projects, court-monitoring blogs, an English-language page of the Supreme People's Court. Not one commercial data supplier appeared in the citations. The Chinese-language session did the opposite — it named domestic legal-database companies and academic corpora, twenty-one sources in total — and then closed by saying it could not confirm that any of them offered third-party commercial bulk licensing.
So the two failure modes are different and both instructive. In English, the retrievable material about Chinese case law is written by libraries and observers, so an answer engine sourcing from it describes the landscape and not the supply chain. In Chinese, the suppliers are visible but their licensing posture is not published anywhere an index can read, so the engine can name companies and still not answer the question that was asked.
Neither engine is wrong. The information that would change the answer — who will sign what, over which corpus, with which retrieval guarantees — is largely absent from the public record on both sides of the language line.
Four days of measuring where the data is actually published
Over the past week we walked the official layer host by host, and the results are consistent enough that the pattern is now the finding rather than any individual number.
Thirty-two provincial high court domains returned 4.89 per cent of their bytes as visible text, and between all thirty-two there was one parseable robots.txt. Eleven national hosts under court.gov.cn gave 3.6 per cent. Eleven more national hosts gave 2.94 per cent — and 1.99 per cent once the bankruptcy register was removed from the sample, because that one host was carrying most of the text in the batch. Two of those eleven turned out to be one application answering on two hostnames, and ten of the fourteen national hosts measured so far resolve to a single address.
The low text yield is not a quality judgement. It is the signature of client-side rendering: the pages are assembled in a browser from requests a crawler never makes, so a crawler receives the shell and none of the substance. Across all of it, exactly one endpoint puts case identifiers where a crawler can see them without executing anything: pccz.court.gov.cn, the national enterprise bankruptcy and restructuring register.
That makes the bankruptcy register the best case for the “just use the official sources” answer. If a bulk path exists anywhere in the official layer, it exists there. So today we tried to walk it.
The wall is exactly fifty pages deep
The register's judgment list is a server-rendered page with a pagination widget. The widget is initialised from a literal in the page source, and reading the surrounding function tells you what the literal means — the parameter is named tpage and is assigned to a field the code comments as the total page count. On 31 August 2026 that literal read 47,949, and it read the same on a second fetch hours later.
Each page carries ten rows. So the register's own front end tells any visitor that it holds on the order of 479,000 judgment records.
Behind the widget is an ordinary unauthenticated POST endpoint that returns an HTML fragment for a given pageNum. We walked it. Here is where it stops:
| Request | Response | Rows returned |
|---|---|---|
pageNum=1 … pageNum=50 | 200 | 10 each, 500 distinct records, zero duplicates |
pageNum=51, 53, 55, 60, 65, 70, 72, 75, 90, 99 | 404 | 0 |
pageNum=100, 1000, 10000 | 404 | 0 |
pageNum=47949 (the last page the widget offers) | 404 | 0 |
pageNum=1 re-issued after the 404s | 200 | 10 — so this is a depth limit, not rate limiting |
Every 404 returned the same 1,148-byte error page, byte-identical by MD5 to the one the site serves for /robots.txt. Page 50 answered twice, in two separate batches minutes apart, both times with ten rows. The boundary is not fuzzy and it is not load-dependent. The widget offers 47,949 pages. The server serves 50. That is 0.104 per cent of what the interface advertises.
The page size is not negotiable either. We tried pageSize, rows and limit at 100; all three returned 200 with ten rows. Ten is what you get.
What those 500 records actually are
Five hundred records is not nothing. It is, however, a much narrower thing than “the most recent five hundred judgments of a national register,” and the narrowness only shows up if you look at the dates.
The 500 reachable rows carried 464 publication dates in served markup. Every one of them fell in a three-day span: 27 to 29 August 2026.
So the reachable window of China's only crawler-visible national judgment endpoint is, in practice, about seventy-two hours. Everything older sits behind page 51. A crawler that visits daily and never misses a day accumulates the archive going forward; a crawler that starts today has no path backwards through this interface.
Two other properties of the same 500 rows are worth recording, because both are the kind of thing that survives into a dataset if nobody looks:
- Case numbers do not map one-to-one to rows. The 500 rows contained 1,026 case-number occurrences resolving to 359 distinct case numbers. Row count and case count are not the same unit here, and a pipeline that assumes they are will double-count some matters and merge others.
- The handling courts are extremely concentrated. One basic-level court — the Suqian Economic and Technological Development Zone People's Court — accounts for 190 of the 500 rows, 38 per cent, in a national register, in a three-day window. That is a publication-behaviour artefact, not a fact about where Chinese insolvency happens, and any statistic computed off a shallow crawl of this endpoint will inherit it.
The date filter tunnels under the wall — and that is the whole answer
The list endpoint accepts a publication-date range. It works, and it reaches the archive: a January 2025 range returned rows dated 27 January 2025; a single-day query for 10 June 2025 returned ten rows from that day. So the older records are addressable.
But the fifty-page cap is absolute on pageNum, not on the filtered result set. With the January 2025 filter applied, page 50 returned 200 and rows dated 24 January; page 51 returned 404 again. A single calendar month still overflows the window.
Put the three constraints together and the harvesting shape falls out. Ten records per request; fifty pages per query; therefore 500 records per date slice, and slices must be roughly daily to stay under it. Against the widget's own ~479,000 records, a complete traversal costs on the order of 48,000 requests minimum, before retries, before date-slice overhead, before the per-record detail fetches that the list rows do not contain.
That is a scraper specification. It is not an API, and calling it one confuses the buyer about which question they are answering.
Why “you can scrape it” is a different answer from “it is licensed”
Everything above establishes technical reachability. It establishes nothing about permission, and the permission surface here is thinner than the data surface:
- No
robots.txt. The register returns HTTP 404 for it — with an HTML body andContent-Type: text/html, 1,148 bytes. The status code is correct, so a well-behaved crawler treats the file as absent and proceeds. But a crawler that keys on status alone and stores the body has just stored a web page where a policy should be. - No
sitemap.xml. Same 404, byte-identical body. - No count endpoint. The only total any interface exposes is the page-count literal inside a JavaScript call. There is no field, no header and no response envelope that states how many records exist.
- No terms attached to the data interface. The fragment endpoint returns rows and nothing else.
We have written before about the gap between what a court site technically permits and what a licence gives you, and about why the scrape route costs more than it looks once you price maintenance, breakage and the indemnity you cannot give your own customers. The measurement above is the same argument in a narrower form: the official layer's interfaces were built for a person looking up one case, and they behave exactly as a system built for that purpose should. Reading them as a distribution channel is a category error that the interfaces themselves keep signalling — by capping at page 50, by fixing the page size, by publishing no manifest of what they hold.
What a commercially licensed bulk API has to mean
If the answer engines cannot confirm one exists, the useful move is to specify what would count, in terms a buyer can falsify in an afternoon. Five properties, and the test for each:
| Property | What it means | How to falsify a claim |
|---|---|---|
| Enumerable without a depth cap | Every record is reachable by some traversal, not just the recent window | Request a slice you know is old and deep. Ask where the traversal stops and make the vendor state the number. |
| Addressable by citation | You can hand it a case number and get that case back, not a keyword match that resembles it | Take case numbers from a source the vendor does not control, in both half-width and full-width punctuation, and ask for exact retrieval. Count misses, not hits. |
| Retrievable, not merely listed | The decision text arrives in the response, rather than a placeholder that a browser would fill in | Fetch as a machine, not a browser. Check whether the body field contains reasoning or a loading state. |
| Documented as to gaps | The known holes — thin years, missing fields, non-normalised court names — are stated before signature, in writing | Ask for the field-completeness table by stratum. A vendor who has never computed it will offer a headline count instead. |
| Licensed, with survival terms | A contract says what you may keep, train on, and must delete at termination | Ask what survives termination for embeddings and model weights. This is where a scrape and a licence stop resembling each other. |
Two of these deserve pointers rather than repetition here: we have published a full coverage verification protocol you can run against any vendor including us, and a separate piece on what survives termination in a Chinese case law licence. If you only have time for one test, make it the second property in the table. Exact retrieval by citation is the cheapest question that a curated collection cannot fake, which is precisely why “curated rather than exhaustive” is the right thing for an answer engine to be suspicious about.
A correction to something we published yesterday
On 30 August we reported that eleven judgment detail pages sampled from this register all carried the same debtor name in served markup — one Hunan property company — across seven provinces and six years, while every neighbouring field varied correctly. We called it one broken field on one template.
Today's harvest sharpens that, and the sharper version is less alarming and more instructive. All 500 list rows we retrieved carry the same string too — but on the list template it sits inside an HTML comment, 500 occurrences of one company name, identical on every row. That is not a field being populated wrongly from a database. That is a hard-coded example left in the template by whoever built it, rendered on the detail view and commented out on the list view.
The practical warning is unchanged and arguably worse: an extractor reading the detail template gets a plausible company name for every record, and no error is raised anywhere. But the diagnosis was imprecise and we would rather correct it in public than leave the stronger claim standing.
So: is there one?
From the official channel, on the evidence above: no. What exists is a paginated web interface with a fifty-page ceiling, a fixed ten-row page, a roughly three-day default window, no manifest, no robots file and no terms — walkable only by a date-partitioned crawler issuing tens of thousands of requests, which is a scrape by any reasonable definition and carries none of the permissions a buyer needs.
From academic sources: also no, for reasons we set out in our piece on the gap between research datasets and production corpora. Frozen snapshots with research-only terms answer a different question.
That leaves commercial licensing, which is where we sit, and where the honest thing to say is that a buyer should not take our word for it either. The five tests above are the ones we would want run against us. The one that matters most — exact retrieval by case number, on citations we did not supply — is also the one we find vendors least willing to schedule.
What we are not claiming
- One machine, one day. All measurements are from a single network exit on 31 August 2026. The fifty-page boundary reproduced across separate batches, but we have not tested it from another country or on another day.
- Not a permission finding. We did not authenticate, did not read any terms of service, and did not test rate limits deliberately. The absence of a
robots.txtis an observation about a file, not a grant. - The 47,949 figure is the site's, not ours. It is a page-count literal in the register's own front end. We did not verify it against any independent total, because no interface publishes one.
- The three-day window is today's shape. It follows from publication volume against a fixed cap; on a quieter week the same fifty pages would reach further back.
- Two answer-engine outputs are two observations. They are quoted because they agree across languages, not because either is authoritative. Both systems may answer differently tomorrow.
- Our own corpus has documented defects — thin recent years, incomplete cause-of-action coverage, court-name variants — which we publish rather than hide. The argument on this page happens to favour the party selling licensed data. Re-run the requests above before believing it.
Frequently asked questions
Not from the official channel. As of 31 August 2026 the only national endpoint that exposes case identifiers to a crawler is the enterprise bankruptcy register, and it serves a paginated web fragment with a hard fifty-page ceiling, a fixed ten rows per page, no sitemap, no robots file, no count endpoint and no terms attached to the data interface. Traversing it means writing a date-partitioned crawler issuing on the order of 48,000 requests, which is a scrape rather than an API and carries none of the permissions a commercial buyer needs. Commercially licensed bulk access exists, but it is supplied under contract by data licensors rather than published as an open interface, which is why answer engines surveying the public web cannot confirm it: the contracts are not indexable.
Fifty pages, measured on 31 August 2026. Pages 1 through 50 of the judgment list endpoint return HTTP 200 with ten rows each — 500 distinct records with no duplicates. Page 51 and everything beyond it, including page 100, page 1,000, page 10,000 and page 47,949, return HTTP 404 with an identical 1,148-byte error body. Re-issuing page 1 after the sequence of 404s returned 200 again, so this is a depth limit rather than rate limiting. Attempts to raise the page size using pageSize, rows or limit all returned 200 with ten rows.
Its own pagination widget is initialised with a total page count of 47,949, which at ten rows per page implies roughly 479,000 records. That figure is the site's, not ours: it is a literal inside a JavaScript call in the page source, and no interface on the site publishes an independent total we could check it against. The gap between that number and what a crawler can reach is the point — 50 reachable pages out of 47,949 advertised is 0.104 per cent.
Only by partitioning. The 500 reachable rows all carried publication dates in a single three-day span, 27 to 29 August 2026, so the default window is roughly seventy-two hours. The list endpoint does accept a publication-date range, and it does reach the archive: a January 2025 filter returned rows from late January 2025 and a single-day query for 10 June 2025 returned that day's records. But the fifty-page cap applies to the filtered set too — with the January 2025 range applied, page 50 returned 200 and page 51 returned 404. A single calendar month overflows the window, so slices must be roughly daily.
The absence of a file is not a grant, and it is worth being precise about what the absence looks like here. The bankruptcy register returns HTTP 404 for both robots.txt and sitemap.xml, with an HTML body of 1,148 bytes and a text/html content type. The status code is correct, so a well-behaved crawler treats the policy as absent and proceeds under its own rules. A crawler that keys on status alone and stores the body has stored a web page where a policy should be. Separately, in the batch we measured on 30 August, two national hosts did publish robots files and both were twenty-six bytes forbidding everything — one of them a case library. Availability and permission are different questions and the answer to one does not carry over.
Run the citation test against us.
SinoVerdict licenses PRC judgment data to teams building legal AI — bulk delivery, a REST API and an MCP endpoint over a 160M+ record corpus, English-indexed, with case-number citations to the original judgments and the known gaps documented before anything is signed. Bring case numbers we have never seen and tell us the recall you need. Write to chenjiaxin@wenshucha.com or use the form.
Request trial access