Where PRC Court Data Is Actually Published: A Verified Inventory of Eleven Official Endpoints
Open any law-school research guide to Chinese law and you will find the same list. China Judgements Online. The Supreme People's Court website. The Gazette. The enforcement disclosure portal. The English site. The lists are accurate, they are maintained by librarians who know the subject, and they answer the question a student asks.
They do not answer the question an engineer asks, which is different: what does that URL return to a program? A list of official sources tells you where the material is published. It does not tell you that one of those hosts serves its robots file as an HTML error page with a success status, that another is reachable only without TLS, or that the case count printed in a third's markup is sixteen hundred cases out of date.
So we measured all of them. Eleven national hosts under court.gov.cn, read on 28 August 2026 from a single machine, recording status codes, byte counts, final URLs after redirects, how much text survives with scripts removed, and what each host's robots.txt actually contains. The point of this page is not the numbers. It is the twenty-line procedure at the end, which anyone can re-run in two minutes and which will give a different and more current answer than ours.
court.gov.cn. Provincial and municipal court sites are numerous and were not measured. All observations are from one network vantage point on 28 August 2026; status codes on Chinese government infrastructure can vary by origin, and several of these hosts sit behind edge filtering. Where figures from our own index appear, they count records, not cases: our 160,291,678 records resolve to 127,191,468 distinct case numbers and at most 130,700,854 distinct cases.The inventory
Eleven hosts, sorted by what they carry. “Text” is the visible character count after removing script blocks, style blocks, HTML comments and tags — that is, what a crawler that does not execute JavaScript would have to work with.
| Host | Carries | HTTPS front page | Text | robots.txt |
|---|---|---|---|---|
wenshu.court.gov.cn | Judgment documents | 200 · 22,309 B | 376 | 200 · 982 B · parseable |
rmfyalk.court.gov.cn | Curated case database | 200 · 8,540 B | 377 | 500 · HTML |
splcgk.court.gov.cn | Trial-process disclosure | 200 · 197 B | 0 | 200 · 61 B · parseable |
zxgk.court.gov.cn | Enforcement disclosure | 200 · 53,666 B | 715 | 404 · HTML |
tingshen.court.gov.cn | Hearing broadcasts | 200 · 173,214 B | 1,109 | 200 · 26 B · parseable |
gongbao.court.gov.cn | SPC Gazette | 502 (3 of 3) | 0 | 502 · HTML |
www.court.gov.cn | SPC institutional site | 200 · 84,103 B | 3,492 | 200 · HTML |
english.court.gov.cn | SPC English site | 200 · 34,065 B | 4,772 | 404 · HTML |
ipc.court.gov.cn | IP Court (Chinese) | 200 · 67,057 B | 2,320 | 404 · HTML |
enipc.court.gov.cn | IP Court (English) | 200 · 32,690 B | 4,193 | 404 · HTML |
cicc.court.gov.cn | Int'l Commercial Court | 200 · 31,278 B | 1,121 | 404 · HTML |
Totals: 507,119 bytes of HTML yielding 18,475 characters of text, a ratio of 3.6 percent. Ten of eleven answered over HTTPS. Three of eleven served a parseable robots file. None exposed a documented public API.
Finding 1: the pages that matter are the emptiest
Three of the eleven hosts carry case or docket content: the judgment portal, the curated case database, and the trial-process disclosure site. Between them they account for 753 of the 18,475 characters of server-rendered text on this surface — about four percent of the text on the four percent of hosts that hold nearly all of the substance.
The inversion is not an accident and it is not neglect. It is what happens when a site is built for a person with a browser: the shell arrives first, the content arrives afterwards by script, and search is a form submission rather than a URL you can construct. The judgment portal returns 376 characters, which on inspection are the navigation labels, the case-category menu, a set of empty statistics slots waiting to be filled, and a maintenance notice. The trial-process portal returns nothing at all — its entire 197-byte front page is a commented-out line and a one-line script redirect, and following that redirect produces 412 Precondition Failed with 2,628 bytes and zero text, which is the signature of an edge filter that wants a real browser.
The practical consequence is worth being blunt about, because it is the most common thing a scoping deck gets wrong. A crawl of these hosts does not return a partial corpus that you can improve with more workers or better retries. It returns furniture. The gap between “the data is public” and “the data is retrievable in bulk” is the entire engineering problem, and it does not narrow with effort spent on the published web surface. We have written elsewhere about why platforms that did solve this for reading did not solve it for machines.
Finding 2: the markup and the browser disagree, by 1,609 cases
This is the finding that changed our own mind about what this page was for.
The People's Court Case Database prints its total on the front page. In the served HTML, that total is 3,927. It is stable across repeated requests, and it is written into the markup as a literal, not computed. But the page also loads a small script that posts an empty JSON body to a statistics endpoint on load, and that endpoint returns 5,536, stamped with the current month. The script then rewrites the element.
So a human sees 5,536 and a non-executing crawler sees 3,927 — a figure that is 1,609 cases low, roughly 29 percent. Both numbers come from the same official server on the same day. Yesterday we published 5,536 as that database's size, having read it in a browser; today's sweep is what verified it, and produced the discrepancy as a by-product.
We want to be careful about what this does and does not show. It does not show that any particular model or index is carrying the stale figure — we have not tested that and cannot. What it shows is a mechanism: on official Chinese judicial infrastructure, the machine-readable layer can disagree with the human-readable layer, the disagreement is silent, and the machine-readable layer is the one that propagates. Any pipeline that harvests figures from official sites without rendering them will accumulate this class of error, and because the numbers look plausible, nothing downstream will flag them.
The defensive habit is cheap. When a number from an official site is going to end up in a deck, a contract schedule or a coverage claim, fetch the page twice — once as raw HTML and once rendered — and diff the figure. If they differ, the rendered one is what the publisher intends and the raw one is what the internet will believe.
Finding 3: most of these hosts do not have a robots.txt, and one of them is worse than that
Three of eleven served an actual robots file:
wenshu.court.gov.cn— 982 bytes, 55 directive lines across 20 user-agent groups. Fifteen named search crawlers are admitted with query strings excluded; four named shopping crawlers are blocked outright; the catch-all group is disallowed entirely. It is a whitelist, and we read it line by line in a separate piece, including the point that matters most: no AI crawler is named in it, in either direction.tingshen.court.gov.cn— 26 bytes.Disallow: /. An unambiguous no, and worth respecting as one.splcgk.court.gov.cn— 61 bytes that disallow everything twice, in two separate catch-all groups. Duplicate groups for the same user-agent are not what the standard contemplates, and parsers differ on whether to merge them or take the first. Here it does not matter, because both say the same thing. It is a reminder that these files are hand-maintained.
The other eight returned HTML. Five with 404, one with 500, one with 502. Those are all fine, in the sense that a missing robots file is a well-defined condition and every serious crawler handles it.
The eighth is the one to write down. https://www.court.gov.cn/robots.txt — the Supreme People's Court's own main site — returns HTTP 200, content-type text/html, 3,144 bytes, and the body is the site's styled “page not found” screen. Zero directive lines. A compliant crawler does not see an error; it sees a valid robots file that grants unrestricted access, because a 200 response containing no rules is, under the standard, exactly that.
There is a second wrinkle. Requested with HEAD instead of GET, the same URL returns 403 from a web application firewall, stable across attempts. Crawlers that probe with HEAD before fetching will conclude the file is forbidden; crawlers that GET will conclude it is permissive. Same URL, same second, two opposite answers depending on verb.
None of this is a criticism of anyone's operations, and none of it is a licence. A misconfigured robots file is not consent, an absent one is not consent, and the question of what may lawfully be collected from these sites is not answered by a status code. What it is is a warning to anyone whose compliance story rests on “we honour robots.txt”: on this infrastructure, that sentence does not mean what it means elsewhere, and a crawler that reports it obeyed the rules may have been handed no rules at all.
Finding 4: transport is not uniform, and two hosts leave the perimeter
Two observations that will break an allow-list before they break anything else.
The Gazette answers only without TLS. https://gongbao.court.gov.cn/ returned 502 on three consecutive attempts, each taking six to nine seconds. The same host over plain http:// returned 200 with 45,068 bytes and 2,440 characters of real content — the Gazette masthead, its editorial board, judicial interpretations, work reports, statutes. The publication is up. The HTTPS front door was not, in our window. An enterprise fetcher configured to refuse plain HTTP, which is the correct default, will record this source as down rather than as insecure, and the operator will go looking for the wrong problem.
The English IP court site ends up somewhere else. Requesting https://enipc.court.gov.cn/ yields a 302 to https://enipc.court.gov.cn/en-us/index.html, and following the chain to its end lands on http://enipc.court.gov.cn.cdurl.cn/ — plain HTTP, and a hostname whose registrable domain is not court.gov.cn but a content delivery provider's. The content is the court's. The origin, by the time you have the bytes, is not on the domain you allow-listed and the connection is not encrypted. If you are pinning certificates, restricting egress by domain, or recording provenance for an audit trail, this is the row that will surprise you, and it is invisible unless you follow redirects all the way rather than to the first hop.
Finding 5: two of the doors are explicitly closed, and that is useful information
It is easy to read an inventory like this as a list of obstacles. It is more useful to read it as a map of intent. Two hosts say no in plain terms: the hearing broadcast site disallows all crawlers in twenty-six bytes, and the trial-process portal disallows everything twice and then challenges non-browser clients at the edge. That is a clear signal from the publisher, and the correct response is to route around those sources rather than through them.
The distinction we would draw for anyone assembling a China data plan: a 404 on robots.txt is silence, a Disallow: / is a refusal, and a 200 carrying an error page is a malfunction. Three different conditions that a naive pipeline collapses into one boolean. Treating them as one is how teams end up with a compliance posture they cannot defend and a coverage claim they cannot support — the same failure mode that shows up when nobody verifies a coverage claim before signing.
Re-run this yourself
Everything above comes from about twenty requests. This is the whole procedure; it needs no credentials and completes in roughly two minutes.
import re, html, urllib.request as u
HOSTS = ["wenshu","rmfyalk","splcgk","zxgk","tingshen","gongbao",
"www","english","ipc","enipc","cicc"]
UA = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 Chrome/128.0.0.0 Safari/537.36"}
def get(url):
try:
r = u.urlopen(u.Request(url, headers=UA), timeout=25)
return r.status, r.geturl(), r.read()
except Exception as e:
return getattr(e, "code", 0), url, getattr(e, "read", bytes)()
def text_of(b):
s = b.decode("utf-8", "replace")
s = re.sub(r"(?is)<(script|style)[^>]*>.*?</\1>", " ", s)
s = re.sub(r"(?s)<!--.*?-->", " ", s)
s = re.sub(r"(?s)<[^>]+>", " ", s)
return re.sub(r"\s+", " ", html.unescape(s)).strip()
for h in HOSTS:
base = f"https://{h}.court.gov.cn/"
st, final, body = get(base)
rst, _, rbody = get(base + "robots.txt")
directives = len(re.findall(rb"(?im)^\s*(user-agent|allow|disallow|sitemap)\s*:", rbody))
print(f"{h:10} page={st} bytes={len(body):>7} text={len(text_of(body)):>5} "
f"robots={rst} rbytes={len(rbody):>6} directives={directives} final={final}")
Two additions catch what the loop above misses. Request robots.txt with HEAD as well as GET and compare, which is how the 200-versus-403 split surfaces. And retry any non-200 host over http:// before recording it as down, which is how the Gazette turns out to be alive. To reproduce the stale-count finding specifically, post an empty JSON body to the statistics endpoint that rmfyalk's own front-page script calls, and compare the integer it returns with the one written into the served markup.
What a research guide entry should say
The librarians who maintain these lists are not doing anything wrong, and we are not proposing they add status codes to their guides. But there is one annotation that would save a great many people a great deal of time, and it costs a single clause per entry: what kind of object is this, and can a program have it?
Three categories cover all eleven hosts. There are reading surfaces — sites that publish real material intended to be read one item at a time, through a search form, by a person. That is the judgment portal, the curated case database, and the enforcement and hearing sites. There are institutional surfaces — the main site, the English site, the specialist courts — which publish news, appointments, work reports and selected translations, and which are perfectly good sources for what an institution says about itself and poor sources for what its courts decided. And there is one publication, the Gazette, which behaves like a periodical because it is one.
Confusing the second category for the first is the most common error we see in scoping documents, and it is easy to make, because an institutional site with four thousand characters of front-page text looks far richer than a judgment portal with three hundred and seventy-six. The richer-looking page is the one with no cases on it. Volume of visible text on these hosts is very close to inversely correlated with legal substance, and a guide that flags which entries are docket sources would prevent most of the misreadings this page exists to correct.
What this page cannot tell you
- One vantage point, one date. Every observation is from one machine on 28 August 2026. Several of these hosts sit behind edge filtering that varies by origin network, and a reader elsewhere may see different codes. The
502on the Gazette in particular is a snapshot of one window, not a claim about its uptime. - Nothing here is a legality finding. We recorded what servers returned. We did not attempt authenticated access, did not test rate limits, did not evaluate terms of use, and take no position on what any party may lawfully collect. Status codes are not permissions.
- National only. Provincial and municipal court sites, of which there are many, were not measured, and we would not assume they resemble these.
- We did not render the pages. Text counts are of served HTML by design, because that is the thing crawlers consume. The one dynamic figure we resolved, the case count, we resolved by reading the page's own script and calling the endpoint it names, not by running a browser engine.
- No inference about other suppliers. We measured public government surfaces and our own index. We have not measured anyone else's corpus or pipeline and cannot say whether these patterns affect them.
- Our own data has documented defects. We publish the gaps in our corpus — its year distribution and the state of its metadata fields — and nothing on this page should be read as suggesting our normalisation problems are solved. They are not.
The short version
China publishes court data on eleven national endpoints. All of them are real, most of them work in a browser, and collectively they return 507,119 bytes of HTML containing 18,475 characters of text, of which the three hosts that hold case content contribute 753. Three serve a parseable robots file; one serves an HTML error page with a success status, which reads as permission; one is reachable only over plain HTTP; one ends its redirect chain on a delivery network outside the government domain; and one prints a case count in its markup that is 1,609 cases behind what its own API returns.
None of that makes these bad sources. They are the authoritative sources, and a research guide is right to list them. What the measurement establishes is narrower and more useful: published and retrievable are different properties, and the distance between them on this particular surface is not a matter of crawler tuning. Anyone scoping a China-coverage project should spend the two minutes to confirm that for themselves rather than take our word for it, and should re-confirm it whenever a figure from these sites is about to become a commitment.
Frequently asked questions
At the national level, eleven hosts under court.gov.cn carry the material a researcher is usually pointed to. Three of them hold case or docket content: China Judgements Online at wenshu.court.gov.cn, the People's Court Case Database at rmfyalk.court.gov.cn, and the trial-process disclosure portal at splcgk.court.gov.cn. Two more carry proceedings rather than decisions: the enforcement disclosure portal at zxgk.court.gov.cn and the hearing broadcast site at tingshen.court.gov.cn. The Supreme People's Court Gazette sits at gongbao.court.gov.cn. The rest are institutional or English-language sites: www.court.gov.cn, english.court.gov.cn, the intellectual property court at ipc.court.gov.cn and enipc.court.gov.cn, and the International Commercial Court at cicc.court.gov.cn. Measured on 28 August 2026, none of the eleven exposed a documented public API.
Not as published web pages. Measured on 28 August 2026, the eleven national hosts returned 507,119 bytes of HTML between them and only 18,475 characters of visible text, about 3.6 percent. The three hosts that actually carry case content accounted for 753 of those characters, roughly four percent of the text on a surface that holds essentially all of the substance, because their content is assembled by client-side script after the page loads. A crawler that does not execute JavaScript sees navigation furniture on the pages that matter. These sites are built to be read by a person in a browser, and treating the served markup as a corpus produces an empty pipeline rather than a partial one.
Three of eleven served a parseable robots file on 28 August 2026. China Judgements Online served 982 bytes containing 55 directive lines across 20 user-agent groups: fifteen named search crawlers are admitted with query strings excluded, four named shopping crawlers are blocked outright, and the catch-all group is disallowed entirely. The hearing broadcast site served 26 bytes disallowing everything. The trial-process portal served 61 bytes that disallow everything twice, in two separate catch-all groups. The other eight hosts returned HTML instead of a robots file. Five returned it with HTTP 404, one with 500, one with 502, and one, the Supreme People's Court's own main site, returned an HTML error page with HTTP 200, which a compliant parser reads as a valid file containing no rules.
One mechanism is visible in the markup. On 28 August 2026 the People's Court Case Database served a front page with the case count 3,927 written into the HTML, while the statistics endpoint the same page calls on load returned 5,536. The served figure is 1,609 cases low, about 29 percent. Any crawler that does not run the page's JavaScript, which includes most bulk crawlers and many indexing pipelines, records the stale number as the official one. This is not a claim about any particular model's training data; it is an observation that the machine-readable layer of an official site can disagree with the layer a human sees, and that the machine-readable layer is the one that gets copied.
Request each host's front page and its robots.txt, record the status code, byte count and final URL after redirects, then strip scripts, comments and tags from the body and count what text remains. The whole sweep is about twenty requests and finishes in a couple of minutes. Two checks are worth adding because they catch failures a status code hides: request robots.txt with both GET and HEAD, since one national host answers 200 to one and 403 to the other, and follow redirects to the end rather than to the first hop, since one English-language host finishes on plain HTTP at a content delivery hostname outside court.gov.cn. Results vary by network vantage point and date, so the value of the method is that it can be re-run, not that our numbers can be cited indefinitely.
Check the official sources. Then decide what you still need.
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. Tell us which questions your product has to answer and we will show you, on your slice and with counts, which of them the record supports and which it does not. Write to chenjiaxin@wenshucha.com or use the form.
Request trial access