Counting a government register: 5,305 records and a paging bug

2026-11-16来源 dev.toEnglish

I spent a morning counting a Chinese government register that went live in September. The goal was modest: find out how many visa agencies had actually filed, and whether the deadline everyone is quoting is real. The interesting part turned out to be the plumbing — a paging parameter that is ignored, an identifier that carries a date, and three questions the data cannot answer no matter how you slice it.

The setup

China's State Council Order No. 841, in force 15 September 2026, created a filing duty for anyone who charges a fee to handle someone else's visa paperwork. The implementing measures (National Immigration Administration and market regulator, Announcement No. 6 of 2026) set three clocks: 15 days from establishment for a new agency, 90 days from 15 September for an agency already trading, and 15 days from the day an existing company starts the service. The 90-day window puts the first real deadline on 14 December 2026.

The measures also require a national public register of filed agencies. That register exists, and it answers to a list endpoint that takes a page size. Which means it can be counted.

The paging bug that wastes a morning

The list page loads records through a POST. My first try sent pageNo=1&pageSize=1000 and got 1,000 records back. Then I sent pageNo=2, pageNo=3, and so on, and kept getting 1,000 records each time — all of them the same.

The tell was in the response body: pageInfo.curPage came back as 0 no matter what I sent. The parameter the server actually reads is curPage, and it is zero-based.

# what worked data = {"curPage": n, "pageSize": 500} 

Eleven pages at 500, and the endpoint's own totalContentNum (5,305) matched the number of unique ids I had collected. If it had not matched, that mismatch would have been the signal that pages were overlapping or being silently reused.

Two habits saved this from being a wrong number: dedupe by primary key while collecting, and compare the collected count against the total the API reports. Neither is clever, and both would have caught the failure immediately.

The identifier carries two fields for free

Every record has a filing number that looks like this:

310105261110I6279 

Characters 7 to 12 are the filing date as YYMMDD — 261110 is 10 November 2026. The first two digits are the province-level administrative division code, so 31 is Shanghai, 44 Guangdong, 11 Beijing. That gives month and province breakdowns without any joins:

def filing_date(code): s = code[6:12] return f"20{s[0:2]}-{s[2:4]}-{s[4:6]}" 

What the date does not mean is when the company started trading. It is the date the filing was accepted. A 15-year-old agency and one that opened last month can sit a few weeks apart in the same register, and the register holds no other history to tell them apart.

The arithmetic

Pulled on 16 November 2026: 5,305 records, the oldest dated 15 September (the day the rule started), the newest 15 November.

Period Records
15–30 September 611
October 2,721
1–15 November 1,973

Filing happens on working days. The five weekdays from 9 to 13 November added 935 records, about 187 a day; the two weekend days after them added five. Guangdong, Beijing and Shanghai account for 49.95% of the register between them.

Twenty working days remain before 14 December. At 187 a day that is roughly 3,700 more records, ending near 9,000. That is arithmetic on an observed rate — the rate has climbed every month, so treat it as a description of the queue rather than a forecast.

Three things the register cannot tell you

What an agency actually does. The record has a name, a credit code, an address, a legal representative, the names of client-facing staff, and a violations field. There is no business-scope field. An agency serving only Chinese citizens going abroad and one handling inbound work permits look identical. If you are a foreigner choosing an agent, the register confirms a filing and nothing else.

How many companies there are. A branch is filed separately, so a chain with five offices is five records. The total counts filings, not businesses.

Whether enforcement is happening. I found no published list of penalties under the regulation's articles 12 and 13. The violations field was empty on the one record I opened. One empty field is not evidence of a clean industry, and it is not evidence of anything about the other 5,304.

What I would check before trusting a number like this

  • Does the API's own total match your deduplicated count?
  • Does a "last page" request return an empty list rather than repeating content?
  • Are the dates you are charting event dates or record-creation dates? They are usually not the same thing.
  • Does the schema have the field your headline depends on? Mine did not, so the headline became "5,305 filed" rather than "half the market is unregistered".

The regulation itself is at gov.cn, the implementing measures at nia.gov.cn, and the register is under the immigration administration's service pages. All three were read in Chinese; I found no official English text for either instrument, which is the other thing worth saying out loud when the underlying documents are not in your reader's language.

If you want the clause numbers and the two penalty tables, the long version is at notebookfield.com — same documents, sorted by article.

Drafted with an AI assistant from my own reading of the primary documents; every clause number and link here was checked against the source.

原文:https://www.a8q9.cn/en/article/counting-a-government-register-5-305-records-and-a-paging-bug-75578c.html

相关文章