Accessibility Auditor — reads every
h1–h6 heading of the audited page in document order and checks that no level is skipped and that no heading sits inside another heading.Accessibility
Screen reader users navigate by heading level; a consistent outline lets them jump straight to the section they need.
Rendered pages
When the raw HTML has no heading at all, the page is rendered in a headless Chromium so JavaScript-built content is judged too.
h2 under an h1, an h3 under an h2. A jump from h2 straight to h4 reads as a missing section, and a heading placed inside another heading is invalid HTML that browsers repair in different ways. This auditor parses the page and reports both problems, one check per heading.
How it works
- Fetch — downloads the audited URL as 37AuditsBot with a
GETrequest. A blocked request ends the audit with590; any other failure (timeout, DNS, TLS, non-2xx answer) ends it with500. - Parse — reads every
h1–h6element from the HTML in document order. - Render when needed — when the raw HTML has no heading at all, loads the page in a headless Chromium, waits for the network to go idle and parses the rendered DOM instead. A browser error, after one relaunch on a crash, ends the audit with
501. - Rules — a heading more than one level deeper than the previous one fails (
400, one check per jump); a heading whose nearest heading ancestor is at the same or a deeper level fails (401, one check per heading); a page with no heading even after rendering warns (300). - Aggregate — FAIL wins over WARNING; when every rule passes the audit is
SUCCESS(200) and the message counts the headings per level.
What it audits
Every row maps to onecheckRule* method and one CheckCode, in the order the auditor runs them. CheckCode suffixes use status ranges: 200 success, 300–399 warning, 400–499 fail, 500–599 error.
Output documentation
Risks and considerations
Why the outline matters
- Screen reader users typically press a key to move from heading to heading and read the level of each one; a jump from
h2toh4sounds like a missingh3and sends them looking for content that is not there. - WCAG success criterion 1.3.1 (Info and Relationships) expects headings to convey the structure of the page, and heading levels are the main way to do it.
- Search engines use headings to understand what each section covers; a page without any is harder to summarize and to rank for a specific topic.
Document order, not DOM depth
- The level check follows the order in which headings appear in the page, which is also the order assistive technologies read them. Where a heading sits in the DOM does not matter for that rule, only which heading came before it.
- Going back up any number of levels (an
h4followed by anh2) is fine: that opens a new section. Only going down more than one level fails. - Only the first jump after a given heading is reported; a page with several jumps gets one check per jump, each naming the heading that caused it.
JavaScript-rendered pages
- The browser render only runs when the raw HTML has no heading. A page whose server-side HTML already has headings is judged on that HTML, even when JavaScript adds more headings later.
- Rendering waits for the network to go idle plus a short grace period; headings that appear after a slow request or on scroll may be missed, which can turn into a
300warning for a page that does have headings once fully loaded.
What this auditor does not check
- Whether the page has exactly one
h1, or whether the first heading is anh1. - The wording of the headings, their length, or whether they describe the content below them.
- Elements that look like headings but are not (
<div class="title">,role="heading"witharia-level). - Pages beyond the audited URL.