↑↓ to move ↵ to open Esc to close Browse all tools

Heading Structure Checker

Paste a page's HTML to see its heading outline from H1 to H6 as an indented tree. Skipped levels, a missing or repeated H1, empty headings, hidden headings and headings made of only an image are marked, with what the specs and Google say about each.

Heading structure checker

Heading structure
-

    Try:

    Outline

      Your HTML is read in your browser. Nothing is fetched or uploaded.

      What the heading structure checker shows

      Headings are the table of contents of a web page. Screen reader users jump from heading to heading to find their way, and everyone else scans them to decide what to read. This heading structure checker reads the HTML you paste and lists every h1 to h6 element in the order it appears, indented by level, so the outline of the page becomes visible at a glance. A summary counts the headings per level and shows the page title.

      Each heading shows the text a screen reader would read: the text inside it, plus the alt text of any image in it, or the aria-label or aria-labelledby text when the heading has one. Elements with role="heading" count too, at the level given by aria-level. The checks then run on the headings a visitor can actually see:

      CheckWhat it findsWhy
      Skipped levelA heading more than one level below the heading before it, such as an H4 right after an H2.HTML Standard: must not
      No H1No shown heading has level 1.HTML Standard: should have one
      Empty headingA heading with no text, or with only an image that has no alt text.Nothing to read out
      Hidden headingHidden with the hidden attribute, an inline display: none or visibility: hidden, aria-hidden="true", inside noscript or a closed dialog.Left out of the outline
      Image-only headingA heading whose only content is an image. Its text is the alt text, shown here.Check the alt text
      Several H1sMore than one shown heading with level 1.Allowed; worth a look
      role="heading" without levelAn element with role="heading" but no aria-level.WAI-ARIA: required

      The HTML is parsed by your browser into an inert document, the same way the keyword density checker reads pasted pages: scripts do not run, images are not loaded and nothing is fetched. Two limits follow from that. Style sheets are not applied, so a heading hidden by a CSS class still counts as shown; only inline styles are read. And headings that JavaScript adds after loading are not in the page source. For those, copy the rendered HTML from your browser's developer tools.

      What the HTML Standard says about headings

      The HTML Standard gives each h1 to h6 element a heading level equal to the number in its name, and defines the outline of a document as all its headings, in tree order. Earlier versions described an outline algorithm in which section and article elements changed the level of the headings inside them. Browsers never implemented it, and it was removed in 2022 and replaced with the plain heading levels in use today (WHATWG pull request 7829). An h1 inside a section is an h1, which is how this checker reads it.

      Two rules matter for the checks. First, a heading after another heading must have a level that is less than, equal to, or one greater than that heading's level. So going from H2 to H3 is fine, going back from H4 to H2 is fine, but jumping from H2 to H4 is not. Second, if a document has headings, at least one of them should have level 1. The standard does not forbid several h1 elements.

      The standard also defines two new attributes, headingoffset and headingreset, which shift the level of the headings inside an element. According to MDN's compatibility data, browsers support them only behind a flag so far, so the checker keeps the level from the tag name and shows the shifted level next to it when the attributes are used.

      Headings and accessibility (WCAG 2.2)

      WCAG 2.2 success criterion 1.3.1 Info and Relationships (Level A) asks that structure shown visually can also be determined by software. W3C's sufficient technique H42 is to mark headings with h1 to h6, and its test is simple: heading markup is used where content is a heading, at the right level, and not used where content is not a heading. Technique G141 adds that headings should be properly nested, for example an h2 followed by an h2 or an h3. For headings built from other elements, technique ARIA12 describes role="heading" with aria-level, and WAI-ARIA 1.2 requires aria-level for that role.

      Hidden headings deserve care. MDN notes that display: none removes an element from the accessibility tree, and that the hidden attribute hides content from all presentations, screen readers included. A heading meant only for screen reader users should be visually hidden with CSS instead, which this checker cannot see and therefore treats as shown.

      What Google says about headings

      Google Search Central does not ask for one H1. Its SEO Starter Guide lists the number and order of headings among the things not to focus on: headings in semantic order are fantastic for screen readers, but from the Google Search perspective it does not matter if they are out of order, and there is no magical, ideal amount of headings. The same guide recommends breaking long content into sections with headings that help users navigate.

      Headings do play a part in how a result looks. Google's documentation on title links lists heading elements, such as h1, among the sources it uses to create the title shown in search results, next to the title element and the main visual title. So a clear main heading that matches the page title is worth having, for people first. Google's separate developer documentation style guide, a writing guide for its own documentation rather than a ranking rule, uses one level-1 heading per page and asks writers not to skip levels.

      Fix the structure, then check the rest of the page. The SERP snippet preview shows how the title and description may look in search results, and the meta tag generator writes the tags.

      How to use the heading structure checker

      1. 1Open your page, view its source and copy all of it, or copy the rendered HTML from your browser's developer tools.
      2. 2Paste it into the box. The outline and the issues update as you type.
      3. 3Fix skipped levels, empty and image-only headings in your page, then copy the outline as text or Markdown for your notes or a ticket.

      Frequently asked questions

      Is more than one H1 bad for SEO?

      Google does not say so. Its SEO Starter Guide says there is no magical, ideal amount of headings, and that from the Google Search perspective it does not matter if headings are used out of order. The HTML Standard also allows several h1 elements. The checker lists several H1s as a note, not an error, so you can check that each one really is a top-level title.

      Is skipping a heading level an error?

      In HTML, yes. The HTML Standard says each heading must have a level that is less than, equal to, or one greater than the heading before it, so an H4 straight after an H2 does not conform. W3C's technique G141 also asks for properly nested headings. Google Search, on the other hand, says the order does not matter to it.

      Does my page need an H1?

      The HTML Standard says that if a document has headings, at least one should have level 1. It is a should, not a must. In practice the main title of the page is the natural H1, and Google lists heading elements such as h1 among the sources it may use for the title link in search results.

      Why are hidden headings left out of the outline?

      A heading hidden with display: none or the hidden attribute is not shown, and MDN notes that display: none removes it from the accessibility tree, so screen readers do not announce it either. The checker lists such headings separately and checks the order of the headings that remain. It only sees inline styles: a heading hidden by a CSS class still counts.

      Can it check a live URL?

      No. Paste the HTML instead: open the page, view its source or copy the element from your browser's developer tools, and paste it here. Nothing is fetched and nothing is sent anywhere. Headings that JavaScript adds after the page loads are only in the HTML you copy from the developer tools, not in the original source.

      What about headings made with role="heading"?

      They count. WAI-ARIA lets any element act as a heading with role="heading", and requires aria-level to say which level. The checker reads aria-level for those and for h1 to h6 elements that carry it. W3C's technique ARIA12 still recommends using a real h1 to h6 element when possible.