Check what a website really serves before you call it empty
Reading the home page tells you what a site says about itself, not what it serves. Before you write that a site has no data, crawl its sitemap and robots.txt with a script and read the numbers from the saved result. One wrong verdict is enough reason to automate it.
π― For Anyone who audits, compares or writes about a website, by hand or with an agent
- Why the first screen is not evidence
- How a deterministic surface check works and what it writes down
- How to avoid the opposite error, trusting a page because it returned HTTP 200
π The mistake
On 9 September 2026 we concluded that a company-data site had "no useful data". The conclusion came from reading one page, the home page. The same site served a ranking of the top thousand entries with sources and a catalogue of 56,138 profiles. The home page did not mention either number in a way a quick read would catch. The verdict was wrong, and it was said with confidence.
The error is general. A home page is a story the site tells. Whether the site serves what it claims is a question for the pages behind it.
π¬ What a surface check does
We replaced the habit with a command. For a domain, it reads the sitemap and the robots file, visits the addresses they list and records, for each page, the status and the values defined in a contract. A contract lists named values and the expression that reads them from the visible text, with scripts and markup removed. A value can be a printed number or a count of matches, such as how many links of a kind are on the page.
The result is written to a file for that domain, and the command exits with an error code when any value breaks its rule. Severity has three levels: info is reported, warn and error fail the run.
Today the repository holds contracts for 7 surfaces, and the tests for the checker number 21.
βοΈ The second rule: 200 is not data
A page that answers with status 200 can still be empty. We once saw every section of a dashboard answer 200 with zeros, because the underlying snapshot was empty. Acceptance is by content, for example a count greater than zero, not by status code. The same value on two pages must have one definition. If two pages show different labels for the same quantity with no link between them, that is a defect to report.
π οΈ Practice: write your first contract
- Pick one site and list five facts it claims: number of products, number of rankings, last update date.
- For each fact, find the page that should show it and write a regular expression that reads the number from the visible text.
- Add a rule: the value must exist and must be above a threshold you choose.
- Write a small script that fetches the sitemap and the robots file, visits each page once with a polite delay, and applies the contract.
- Save the result with the run time. Never overwrite it silently. Keep the last run for comparison.
- Decide which failures are warnings and which are errors, and make the script return the right exit code.
β Check yourself
- Break a rule on purpose, for example by pointing to a non-existent page. The script exits with an error and the saved file shows which value failed.
- The result file lists every address it visited and the status of each.
- Two pages that show the same quantity give the same number.
- A teammate can reproduce your verdict by running the command, not by trusting your description.
π§ When this does NOT work
- Pages rendered by script. If the numbers appear only after JavaScript runs, a plain fetch will not see them. Use a rendering step or a data endpoint.
- Login walls. A check cannot judge what it cannot reach. Say so in the report.
- Changing layouts. A regular expression breaks when the wording changes. Review contracts when pages change.
- Heavy sites. A crawl of tens of thousands of pages needs a budget and a delay. Sample, and say that you sampled.
- Meaning. The check proves that a value exists. It does not prove that it is true. For truth you need the source.
π Evidence
| What we measured | Number of surfaces with a contract and of tests for the checker in our repository; the original verdict error of 9 September 2026 |
| When | Repository read on 3 November 2026, 22:06 UTC |
| Artifact | The surface contract file (7 surfaces) and the checker test file (21 tests) in our private repository; the incident note in the contract file header |
| Limit | The numbers about the audited site come from our incident note. We did not re-crawl that site for this page |
β‘οΈ Next
Read how we label sources and dates in Sources and verification, and how to keep claims tied to evidence in AI judging.
Sources
- Sources, dates and what βverifiedβ means: how we label evidence.
- AI judging: why βit says it is doneβ is not acceptance: acceptance by checks.
- Why AI agents make things up, and how to check an answer: checking answers.
- Connections, backlinks and the knowledge graph: how pages link.
π Article connections
Open the full knowledge graph βPublished article links. Select a node to open its article at the heading.
Article links Β· keyboard / text view
Same topic
- A vector base is a map, not a source: what we learned from retrieval
- When you cannot tell what a model call cost: freeze, then reconcile
- Splitting a big task for a cheap model: the 24,000-byte lesson
- Skills, MCP tools and rules: three ways to give an agent capabilities
- Eight shell and git mistakes our agents made, and the rule for each
- Several agents, one repository: ownership rules from real incidents
Next steps
Related reading
A vector base is a map, not a source: what we learned from retrieval
A vector base finds passages that are close in meaning to your question. It does not know which are true or current. Treat every hit as a pointer: open the file it names, check the hash, and take numbers from the artifact, never from the retrieved paragraph.
AI agents and MCP explainedWhen you cannot tell what a model call cost: freeze, then reconcile
Sometimes a model call times out and you do not know whether the provider charged you. Never record that as zero. Mark it uncertain, stop new paid calls, and let a named person reconcile it with the provider's statement. Refusals before generation are the exception.
AI agents and MCP explainedSplitting a big task for a cheap model: the 24,000-byte lesson
A cheap model does well on one small, well-defined job and badly on a big pile. We cap a task at 24,000 bytes and refuse larger ones before any model is called. Split by unit, one file or one country per task, and check the size before you start.
AI agents and MCP explainedSkills, MCP tools and rules: three ways to give an agent capabilities
Agents get abilities in different ways. A rule constrains what they do, a skill tells them how to do a job, and an MCP tool lets them call a function. Each has its own risk, so declare all three in a register and test that nothing exists unlisted.
π¬ Comments