# On-page SEO checker

One page, fetched once, read the way Googlebot and the AI crawlers read it: what the title and description say and how long they run, whether the page may be indexed and which address it claims as its own, the outline of its headings, the images with no alt, the links in and out, the share tags, the structured data, and whether the text is in the HTML at all. Twelve checks, each with a verdict, and the three to fix first.

Updated 2026-09-14 · Source: https://porteur.ai/tools/on-page-seo-checker

## What it checks

The tool requests the address once, with a plain crawler's user agent, follows the redirects if there are any, and reads the HTML that comes back. It does not run scripts. That is deliberate: it is the same view Googlebot gets on its first pass and the only view the answering AI crawlers ever get, so what the tool cannot see, they cannot see either.

- Title tag: present, and its length against the sixty or so characters a results page shows.
- Meta description: present, and its length against the hundred and fifty or so a snippet shows.
- One h1: the page states one subject, not none and not three.
- Heading order: h2 under h1, h3 under h2, no level skipped, more than one heading on a long page.
- Canonical: declared, and whether it points at this address or somewhere else.
- Indexable: no noindex in the meta robots tag or in the X-Robots-Tag header.
- Visible text: how many words the HTML holds, and what share of the file they are.
- Readable without JavaScript: whether the text is in the HTML or arrives later by script.
- Image alt text: how many images, how many with no alt attribute, and which ones.
- Links: internal, external and nofollow, counted.
- Open Graph: title, description and image for shares.
- Structured data: the JSON-LD types found, or the block that does not parse.

Below the table the tool prints the facts it read: the title and description in full with their counts, the canonical, the robots directives, the html lang attribute, the heading outline in order, the first five images without alt, and the hreflang versions declared.

## Why one page is worth a check

Most of what decides whether a page ranks is on the page: a title that says what it is, a description that earns the click, headings that carry the outline, text a crawler can read, links that hand standing on. A crawler does not know what you meant; it knows what the HTML says. When the title says one thing and the h1 another, when the canonical points at the staging copy, when a template shipped with noindex on, the page loses quietly, and nothing in analytics says why.

The AI crawlers raise the stakes on one check in particular. OAI-SearchBot, PerplexityBot and ClaudeBot fetch the HTML and read it as it is; a page whose text is rendered by JavaScript after load is empty to them, however good it looks in a browser. The readable-without-JavaScript check is the one to look at first if you want to be cited.

> Run the check on the pages that earn: the home page, /pricing, the top three guides. A template fixed once fixes every page built from it.

## How to read the result

Each check ends in one of three words. Pass means nothing to do. Look means the page works but something is off the usual measure, a title of 25 characters, a canonical pointing elsewhere, a page with two headings. Fix means a crawler is losing something: no title, noindex on a page that should rank, an empty HTML shell, most images without alt. The verdict at the top names the three to fix first, failures before warnings.

| Check | Fix | Look |
| --- | --- | --- |
| Title tag | missing | over 60 or under 30 characters |
| Meta description | missing | over 160 or under 70 characters |
| One h1 | none | several |
| Heading order |  | a skipped level, or fewer than two headings |
| Canonical |  | missing, or pointing at another address |
| Indexable | noindex set |  |
| Visible text | under 60 words | under 300 words |
| Readable without JavaScript | an empty shell filled by scripts |  |
| Image alt text | more than half the images without alt | some without alt |
| Links |  | fewer than three internal links |
| Open Graph | no title and no image | one of title, description or image missing |
| Structured data | a block that does not parse | no JSON-LD at all |

A worked example. yourproduct.com/pricing comes back with a 71-character title that repeats the site name twice, a description of 40 characters, two h1 tags because the plan cards each carry one, a canonical pointing at yourproduct.com/pricing?ref=nav, and 180 words of visible text. Nothing fails; five things say look. The order to take them: the canonical (a parameter address is claiming the page), then the two h1 tags (the template), then the title and description (five minutes in the head), then the text, which for a pricing page is a judgement rather than a rule.

## What to do with it

1. **Fix the checks that fail, in the order given** A missing title or a stray noindex is a five-minute change with a large effect. An empty shell is a rendering decision, the one change that may take a sprint, and the one that matters most for AI answers.
2. **Take the warnings that come from the template** Two h1 tags, a skipped heading level, images without alt in a component: each is one edit that fixes every page built from the template. Check a second page of the same kind to confirm.
3. **Rewrite the title and description last** They are the easiest to change and the easiest to change badly. Say what the page is, for whom, in the words the searcher used; keep the site name once, at the end.
4. **Run the check again after the deploy** A cache in front of the site can serve the old HTML for a while. When the tool reads the new tags, the crawlers will too, on their next visit.

A fixed page reads like this: one title of about 55 characters that names the page and the product, one description of about 140 that says what the reader will find, one h1 that agrees with the title, h2 sections in order, a canonical pointing at itself, no robots directive, the text in the HTML, every image described, a dozen internal links, Open Graph set, and one JSON-LD block that parses.

## Limits

- One address per check, thirty checks an hour per visitor. The page must be public: the tool refuses private addresses and follows at most five redirects.
- The HTML is read as sent, up to two megabytes. Text added by JavaScript after load is not read, which is the point of the readable-without-JavaScript check and the reason the word count can differ from what you see in a browser.
- Length checks use character counts. Google truncates by pixel width, so a title of 58 characters in wide letters can still be cut; the title checker measures pixels if you want that precision.
- The tool reads what the page says about itself. Whether the title matches what people search, whether the text answers the query, whether the page has links from elsewhere: those are questions for the free check, which reads the site, its searches and its rivals together.

## Questions

### How long should a title tag be?

About 60 characters, or under 600 pixels on a desktop results page. Longer titles are cut with an ellipsis; shorter ones leave room unused. Put the words that name the page first and the site name last.

### Does the tool run JavaScript?

No, on purpose. It reads the HTML the server sends, which is what Googlebot reads on its first pass and what the AI crawlers read every time. If the tool finds an empty shell, so do they.

### Is more than one h1 a problem?

Google has said several h1 tags do not break ranking. One is still the convention: it states the page's subject once, screen readers announce it as the page title, and templates that put an h1 on every card usually did not mean to.

### What does a canonical pointing elsewhere mean?

The page is telling search engines that another address is the original and this one is a copy. Right when it is a copy (a parameter version, a print version). Wrong when this is the page you want indexed: the other address gets the ranking instead.

### Why is my word count lower than what I see on the page?

The tool counts words in the HTML the server sends, after removing scripts, styles and markup. Text loaded by JavaScript, text inside images, and navigation repeated in components are not in that count.

### Does the check store my page?

No. The HTML is read in memory, the result is sent back to your browser, and nothing is kept.

## Read next

- [On-page SEO checklist: the twelve things on the page](https://porteur.ai/guides/on-page-seo-checklist): The twelve page elements that move clicks and rankings, with examples you can copy to your own product pages today.
- [Title tag length: what fits, what Google rewrites, and how to write one](https://porteur.ai/guides/title-tag-length): About 60 characters is a safe line. Learn pixels versus characters, why Google rewrites titles, and how to write titles that earn clicks.
- [Heading tags](https://porteur.ai/glossary/heading-tags): Heading tags are h1 to h6 in HTML. See how to structure pages, help Google and screen readers, and write headings that win snippets.
- [Alt text](https://porteur.ai/glossary/alt-text): Alt text is the image alt attribute. Write what the image shows, keep it brief, use empty alt for decoration, and avoid stuffing keywords.
- [Canonical URL](https://porteur.ai/glossary/canonical-url): A canonical URL names the original version of a page. Use it to handle parameters and duplicates, avoid split signals and keep the right page indexed.
- [Social preview checker](https://porteur.ai/tools/social-preview-checker): Paste a URL and see the card a share produces on X, LinkedIn and Slack: the Open Graph tags read, the image fetched and measured, and what to fix first.
- [hreflang checker](https://porteur.ai/tools/hreflang-checker): Paste a URL and check its hreflang: the versions declared, whether the codes are ones Google reads, the self-reference, whether each version points back.
- [Server response checker](https://porteur.ai/tools/server-response-checker): Paste a URL and time the server's answer: time to first byte, HTTP/2 or HTTP/3, brotli or gzip, Cache-Control, HSTS, the headers that decide when a page starts.

This reads one page. The free check reads the whole site with the searches around it and the rivals on them, and says which pages are shown and never clicked, which two fight over one search, and what to change first. Free check: https://porteur.ai/
